PageSourceSearch

https://www.purdys.com/customer/account/login/

html purdys.com collected 2026-09-25 19:47:35 UTC 810,431 bytes, 14,055 lines download raw bytes

1<!doctype html>
2<html lang="en" dir="ltr">
3<head >
4    <meta charset="utf-8"/>
4<script type="text/javascript">(window.NREUM||(NREUM={})).init={privacy:{cookies_enabled:true},ajax:{deny_list:["bam.nr-data.net"]},distributed_tracing:{enabled:true}};(window.NREUM||(NREUM={})).loader_config={agentID:"1120013411",accountID:"3291613",trustKey:"1322840",xpid:"VwQOUFBSCxABVVBaBgIDUVIA",licenseKey:"NRJS-8c25a1a7b460fa8b963",applicationID:"1118134761",browserID:"1120013411"};;/*! For license information please see nr-loader-spa-1.322.0.min.js.LICENSE.txt */
5(()=>{var e={8122(e,t,r){"use strict";r.d(t,{a:()=>i});var n=r(944);function i(e,t){try{if(!e||"object"!=typeof e)return(0,n.R)(3);if(!t||"object"!=typeof t)return(0,n.R)(4);const r=Object.create(Object.getPrototypeOf(t),Object.getOwnPropertyDescriptors(t)),s=0===Object.keys(r).length?e:r;for(let a in s)if(void 0!==e[a])try{if(null===e[a]){r[a]=null;continue}Array.isArray(e[a])&&Array.isArray(t[a])?r[a]=Array.from(new Set([...e[a],...t[a]])):e[a]instanceof Map||e[a]instanceof Set||e[a]instanceof Date||e[a]instanceof RegExp?r[a]=e[a]:"object"==typeof e[a]&&null!==t[a]&&"object"==typeof t[a]?r[a]=i(e[a],t[a]):r[a]=e[a]}catch(e){r[a]||(0,n.R)(1,e)}return r}catch(e){(0,n.R)(2,e)}}},2555(e,t,r){"use strict";r.d(t,{f:()=>a});var n=r(384),i=r(8122);const s={beacon:n.NT.beacon,errorBeacon:n.NT.errorBeacon,licenseKey:void 0,applicationID:void 0,sa:void 0,queueTime:void 0,applicationTime:void 0,ttGuid:void 0,user:void 0,account:void 0,product:void 0,extra:void 0,jsAttributes:{},userAttributes:void 0,atts:void 0,transactionName:void 0,tNamePlain:void 0};function a(e){try{return!!e.licenseKey&&!!e.errorBeacon&&!!e.applicationID}catch(e){return!1}}r.d(t,["D",0,e=>(0,i.a)(e,s)])},7699(e,t,r){"use strict";var n=r(860);const i={[n.K7.logging]:!0,[n.K7.genericEvents]:!0,[n.K7.jserrors]:!0,[n.K7.ajax]:!0};r.d(t,["It",0,1e6,"KC",0,i,"qh",0,"SESSION_ERROR"])},9324(e,t,r){"use strict";r.d(t,["A",0,"@newrelic/rrweb","x",0,"1.322.0"])},981(e,t,r){"use strict";r.d(t,["R",0,{AJAX:"AjaxRequest",PA:"PageAction",UA:"UserAction",BP:"BrowserPerformance",WS:"WebSocket",SPV:"SecurityPolicyViolation",JSE:"JavaScriptError",LOG:"Log",PVE:"PageView",PVT:"PageViewTiming",SR:"SessionReplay",ST:"SessionTrace",BI:"BrowserInteraction"}])},9752(e,t,r){"use strict";const n="newrelic-iframe-",i=n+"timing-update",s=n+"api",a=n+"api-response",o=n+"vitals-update",c=n+"ajax";r.d(t,["$8",0,o,"Gi",0,a,"KU",0,c,"Pl",0,n,"cS",0,s,"cr",0,i])},6154(e,t,r){"use strict";var n=r(1863);const i="undefined"!=typeof window&&!!window.document,s="undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self.navigator instanceof WorkerNavigator||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis.navigator instanceof WorkerNavigator),a=i?window:"undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis),o=Boolean("hidden"===a?.document?.visibilityState),c=""+a?.location,d=/iPad|iPhone|iPod/.test(a.navigator?.userAgent),u=d&&"undefined"==typeof SharedWorker,l=(()=>{const e=a.navigator?.userAgent?.match(/Firefox[/\s](\d+\.\d+)/);return Array.isArray(e)&&e.length>=2?+e[1]:0})(),f=Date.now()-(0,n.t)();r.d(t,["OF",0,d,"RI",0,i,"WN",0,f,"bv",0,s,"gm",0,a,"lR",0,l,"m",0,c,"mw",0,o,"sb",0,u,"zk",0,()=>{const e=a?.performance?.getEntriesByType?.("navigation")?.[0];if(e&&e.responseStart>0&&e.responseStart<a.performance.now())return e}])},7295(e,t,r){"use strict";r.d(t,{Xv:()=>a,gX:()=>i,iW:()=>s});var n=[];function i(e){if(!e||s(e))return!1;if(0===n.length)return!0;if("*"===n[0].hostname)return!1;for(var t=0;t<n.length;t++){var r=n[t];if(r.hostname.test(e.hostname)&&r.pathname.test(e.pathname))return!1}return!0}function s(e){return void 0===e.hostname}function a(e){if(n=[],e&&e.length)for(var t=0;t<e.length;t++){let r=e[t];if(!r)continue;if("*"===r)return void(n=[{hostname:"*"}]);0===r.indexOf("http://")?r=r.substring(7):0===r.indexOf("https://")&&(r=r.substring(8));const i=r.indexOf("/");let s,a;i>0?(s=r.substring(0,i),a=r.substring(i)):(s=r,a="*");let[c]=s.split(":");n.push({hostname:o(c),pathname:o(a,!0)})}}function o(e,t=!1){const r=e.replace(/[.+?^${}()|[\]\\]/g,e=>"\\"+e).replace(/\*/g,".*?");return new RegExp((t?"^":"")+r+"$")}},3241(e,t,r){"use strict";r.d(t,{W:()=>i});var n=r(6154);function i(e={}){try{n.gm.dispatchEvent(new CustomEvent("newrelic",{detail:e}))}catch(e){}}},1687(e,t,r){"use strict";r.d(t,{Ak:()=>o,Ze:()=>d,x3:()=>c});var n=r(3241),i=r(3606),s=r(860),a=r(2646);function o(e,t){if(!e)return;const r={staged:!1,priority:s.P3[t]||0};
5e.runtime.drainRegistry.get(t)||e.runtime.drainRegistry.set(t,r)}function c(e,t){if(!e)return;const r=e.runtime.drainRegistry;r&&(r.get(t)&&r.delete(t),l(e,t,!1),r.size&&u(e))}function d(e,t="feature",r=!1){if(e){if(!e.runtime.drainRegistry.get(t)||r)return l(e,t);e.runtime.drainRegistry.get(t).staged=!0,u(e)}}function u(e){if(!e)return;const t=Array.from(e.runtime.drainRegistry);t.every(([e,t])=>t.staged)&&(t.sort((e,t)=>e[1].priority-t[1].priority),t.forEach(([t])=>{e.runtime.drainRegistry.delete(t),l(e,t)}))}function l(e,t,r=!0){if(!e)return;const s=e.ee,o=i.i.handlers;if(s&&!s.aborted&&s.backlog&&o){if((0,n.W)({type:"lifecycle",name:"drain",feature:t}),r){const e=s.backlog[t],r=o[t];if(r){for(let t=0;e&&t<e.length;++t)f(e[t],r);Object.entries(r).forEach(([e,t])=>{Object.values(t||{}).forEach(t=>{t[0]?.on&&t[0].context()instanceof a.y&&!t[0].listeners(e).includes(t[1])&&t[0].on(e,t[1])})})}}s.isolatedBacklog||delete o[t],s.backlog[t]=null,s.emit("drain-"+t,[])}}function f(e,t){var r=e[1];Object.values(t[r]||{}).forEach(t=>{var r=e[0];if(t[0]===r){var n=t[1],i=e[3],s=e[2];n.apply(i,s)}})}},7836(e,t,r){"use strict";var n=r(384),i=r(8990),s=r(2646),a=r(5607);const o="nr@context:".concat(a.W),c=function e(t,r){var n={},a={},u={},l=!1;try{l=16===r.length&&d.initializedAgents?.[r]?.runtime.isolatedBacklog}catch(e){}var f={on:p,addEventListener:p,removeEventListener:function(e,t){var r=n[e];if(!r)return;for(var i=0;i<r.length;i++)r[i]===t&&r.splice(i,1)},emit:function(e,r,n,i,s){!1!==s&&(s=!0);if(c.aborted&&!i)return;t&&s&&t.emit(e,r,n);var o=h(n);g(e).forEach(e=>{e.apply(o,r)});var d=v()[a[e]];d&&d.push([f,e,r,o]);return o},get:m,listeners:g,context:h,buffer:function(e,t){const r=v();if(t=t||"feature",f.aborted)return;Object.entries(e||{}).forEach(([e,n])=>{a[n]=t,t in r||(r[t]=[])})},abort:function(){f._aborted=!0,Object.keys(f.backlog).forEach(e=>{delete f.backlog[e]})},isBuffering:function(e){return!!v()[a[e]]},debugId:r,backlog:l?{}:t&&"object"==typeof t.backlog?t.backlog:{},isolatedBacklog:l};return Object.defineProperty(f,"aborted",{get:()=>{let e=f._aborted||!1;return e||(t&&(e=t.aborted),e)}}),f;function h(e){return e&&e instanceof s.y?e:e?(0,i.I)(e,o,()=>new s.y(o)):new s.y(o)}function p(e,t){n[e]=g(e).concat(t)}function g(e){return n[e]||[]}function m(t){return u[t]=u[t]||e(f,t)}function v(){return f.backlog}}(void 0,"globalEE"),d=(0,n.Zm)();d.ee||(d.ee=c),r.d(t,["P",0,o,"ee",0,c])},2646(e,t,r){"use strict";r.d(t,{y:()=>n});class n{constructor(e){this.contextId=e}}},9908(e,t,r){"use strict";r.d(t,{d:()=>n,p:()=>i});var n=r(7836).ee.get("handle");function i(e,t,r,i,s){s?(s.buffer([e],i),s.emit(e,t,r)):(n.buffer([e],i),n.emit(e,t,r))}},3606(e,t,r){"use strict";r.d(t,{i:()=>s});var n=r(9908);s.on=a;var i=s.handlers={};function s(e,t,r,s){a(s||n.d,i,e,t,r)}function a(e,t,r,i,s){s||(s="feature"),e||(e=n.d);var a=t[s]=t[s]||{};(a[r]=a[r]||[]).push([e,i])}},3878(e,t,r){"use strict";function n(e,t){return{capture:e,passive:!1,signal:t}}function i(e,t,r=!1,i){window.addEventListener(e,t,n(r,i))}function s(e,t,r=!1,i){document.addEventListener(e,t,n(r,i))}r.d(t,{DD:()=>s,jT:()=>n,sp:()=>i})},5607(e,t,r){"use strict";const n=(0,r(9566).bz)();r.d(t,["W",0,n])},9566(e,t,r){"use strict";r.d(t,{LA:()=>a,ZF:()=>o,bz:()=>s,el:()=>c});var n=r(6154);function i(e,t){return e?15&e[t]:16*Math.random()|0}function s(){const e=n.gm?.crypto||n.gm?.msCrypto;let t,r=0;return e&&e.getRandomValues&&(t=e.getRandomValues(new Uint8Array(30))),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split("").map(e=>"x"===e?i(t,r++).toString(16):"y"===e?(3&i()|8).toString(16):e).join("")}function a(e){const t=n.gm?.crypto||n.gm?.msCrypto;let r,s=0;t&&t.getRandomValues&&(r=t.getRandomValues(new Uint8Array(e)));const a=[];for(var o=0;o<e;o++)a.push(i(r,s++).toString(16));return a.join("")}function o(){return a(16)}function c(){return a(32)}},2614(e,t,r){"use strict";r.d(t,["BB",0,18e5,"Wt",0,"NRBA_SESSION::","g",0,{OFF:0,FULL:1,ERROR:2},"iL",0,{SAME_TAB:"same-tab",CROSS_TAB:"cross-tab"},"tS",0,{STARTED:"session-started",PAUSE:"session-pause",RESET:"session-reset",RESUME:"session-resume",UPDATE:"session-update"},"wk",0,144e5])},733(e,t,r){"use strict";function n(e,t){return function(e){let t=2166136261;for(let r=0;r<e.length;r++)t^=e.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}("".concat(String(e),":").concat(String(t)))}r.d(t,{Y:()=>n})},1863(e,t,r){"use strict";function n(){return Math.floor(performance.now())}r.d(t,{t:()=>n})},9119(e,t,r){"use strict";r.d(t,{L:()=>s});var n=/([^?#]*)[^#]*(#[^?]*|$).*/,i=/([^?#]*)().*/;function s(e,t){return e?e.replace(t?n:i,"$1$2"):e}},7485(e,t,r){"use strict";r.d(t,{D:()=>i});var n=r(6154);function i(e){if(0===(e||"").indexOf("data:"))return{protocol:"data"};try{const t=new URL(e,location.href),r={port:t.port,hostname:t.hostname,pathname:t.pathname,search:t.search,protocol:t.protocol.slice(0,t.protocol.indexOf(":")),sameOrigin:t.protocol===n.gm?.location?.protocol&&t.host===n.gm?.location?.host};return r.port&&""!==r.port||("http:"===t.protocol&&(r.port="80"),"https:"===t.protocol&&(r.port="443")),r.pathname&&""!==r.pathname?r.pathname.startsWith("/")||(r.pathname="/".concat(r.pathname)):r.pathname="/",r}catch(e){return{}}}},7866(e,t,r){"use strict";r.d(t,["Nc",0,/^\s*at Function code \(Function code:\d+:\d+\)\s*/i,"cn",0,/^\s*(?:([^@]*)(?:\(.*?\))?@)?((?:file|http|https|chrome|safari-extension).*?):(\d+)(?::(\d+))?\s*$/i,"fL",0,/^\s*at .+ \(eval at \S+ \((?:(?:file|http|https):[^)]+)?\)(?:, [^:]*:\d+:\d+)?\)$/i,"h3",0,/function (.+?)\s*\(/,"hB",0,/^\s*at (?:((?:\[object object\])?(?:[^(]*\([^)]*\))*[^()]*(?: \[as \S+\])?) )?\(?((?:file|http|https|chrome-extension):.*?)?:(\d+)(?::(\d+))?\)?\s*$/i])},944(e,t,r){"use strict";r.d(t,{R:()=>i});var n=r(3241);function i(e,t){"function"==typeof console.debug&&(console.debug("New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/docs/warning-codes.md#".concat(e),t),(0,n.W)({drained:null,type:"data",name:"warn",feature:"warn",data:{code:e,secondary:t}}))}},8990(e,t,r){"use strict";r.d(t,{I:()=>i});var n=Object.prototype.hasOwnProperty;function i(e,t,r){if(n.call(e,t))return e[t];var i=r();if(Object.defineProperty&&Object.keys)try{return Object.defineProperty(e,t,{value:i,writable:!0,enumerable:!1}),i}catch(e){}return e[t]=i,i}},6389(e,t,r){"use strict";function n(e,t=500,r={}){const n=r?.leading||!1;let i;return(...r)=>{n&&void 0===i&&(e.apply(this,r),i=setTimeout(()=>{i=clearTimeout(i)},t)),n||(clearTimeout(i),i=setTimeout(()=>{e.apply(this,r)},t))}}function i(e){let t=!1;return(...r)=>{t||(t=!0,e.apply(this,r))}}r.d(t,{J:()=>i,s:()=>n})},1910(e,t,r){"use strict";r.d(t,{i:()=>s});var n=r(944);const i=new Map;function s(...e){return e.every(e=>{if(i.has(e))return i.get(e);const t="function"==typeof e?e.toString():"",r=t.includes("[native code]"),s=t.includes("nrWrapper");return r||s||(0,n.R)(64,e?.name||t),i.set(e,r),r})}},3304(e,t,r){"use strict";r.d(t,{A:()=>i});var n=r(7836);function i(e){try{return JSON.stringify(e,(()=>{const e=new WeakSet;return(t,r)=>{if("object"==typeof r&&null!==r){if(e.has(r))return;e.add(r)}return r}})())??""}catch(e){try{n.ee.emit("internal-error",[e])}catch(e){}return""}}},9232(e,t,r){"use strict";r.d(t,["f",0,{MFE:"MFE",BA:"BA"}])},7560(e,t,r){"use strict";r.d(t,{N:()=>a,j:()=>c});var n=r(9119),i=r(944);const s=(0,r(6389).J)(e=>(0,i.R)(80,e));function a(e){if(!Array.isArray(e?.assets)||!e.assets.length)return;
5const t=e.assets.map(o).filter(Boolean);return t.length?{assets:t,scripts:t.filter(e=>e.isScript)}:void 0}function o(e){if(!e||"object"!=typeof e)return;const{matcher:t,type:r}=e;let i="string"==typeof t&&t.endsWith(".js");return void 0!==r&&(!function(e){return"script"===e||"asset"===e}(r)?s(r):i=function(e){return"script"===e}(r)),a=t,"[object RegExp]"===Object.prototype.toString.call(a)?{pattern:t,test:e=>(t.lastIndex=0,t.test((0,n.L)(e))),isScript:i}:"string"==typeof t&&t.length>0?{pattern:t,test:e=>(0,n.L)(e).includes(t),isScript:i}:void s(t);var a}function c(e,t,{scriptsOnly:r=!1}={}){if(!e||!t)return!1;return(r?e.scripts:e.assets).some(e=>e.test(t))}},5718(e,t,r){"use strict";r.d(t,{xo:()=>T,AZ:()=>v,cI:()=>g,Qr:()=>A,QL:()=>y});var n=r(6154),i=r(1863),s=r(9119),a=r(7866);class o{dom=new c;performance=new c;constructor(e){this.url=e,this.claimedBy=new Set}get script(){const e=Math.max(this.dom.start,this.performance.end);return{start:e,end:Math.max(this.dom.end,this.performance.end,e)}}}class c{start=0;end=0;value=void 0}function d(e=()=>{},t){return{get:()=>void 0!==t?t:e(),set:e=>{t=e}}}let u;try{u=v(y())[0]}catch(e){u=v(e)[0]}const l=new Map;let f=[];const h=new WeakMap;function p(e){let t=h.get(e);return t||(t={weighedAssetUrls:new Set,recordManifestScriptWindow:(t,r)=>{t&&(e.scriptStart=e.scriptStart>0?Math.min(e.scriptStart,t):t),r&&(e.scriptEnd=e.scriptEnd>0?Math.max(e.scriptEnd,r):r)}},h.set(e,t)),t}function g(e){return l.get(e)}function m(e){const t=g(e);
5if(t)return t;const r=new o(e);if(l.set(e,r),l.size>1e3){const e=l.keys().next().value;l.delete(e)}return r}if(n.gm.MutationObserver&&n.gm.document){new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{if("SCRIPT"===e.nodeName&&e.src){const t=m((0,s.L)(e.src));t.dom.start=(0,i.t)(),t.dom.value=e;const r=()=>{t.dom.end=(0,i.t)()};["load","error"].forEach(t=>e.addEventListener(t,r,{once:!0}))}})})}).observe(n.gm.document,{childList:!0,subtree:!0})}if(n.gm.PerformanceObserver?.supportedEntryTypes.includes("resource")){new PerformanceObserver(e=>{e.getEntries().forEach(e=>{if((e=>"script"===e.initiatorType||["link","fetch"].includes(e.initiatorType)&&(0,s.L)(e.name).endsWith(".js"))(e)){const t=m((0,s.L)(e.name));t.performance.start=Math.floor(e.startTime),t.performance.end=Math.floor(e.responseEnd),t.performance.value=e}if(!f.length)return;const t=[];f.forEach(({test:r,addedAt:n},s)=>{(r(e)||(0,i.t)()-n>1e4)&&t.push(s)}),f=f.filter((e,r)=>!t.includes(r))})}).observe({type:"resource",buffered:!0})}function v(e){if(!e||"string"!=typeof e)return[];const t=new Set,r=e.split("\n");for(const e of r){const r=e.match(a.cn)||e.match(a.hB)||e.match(a.fL);if(r&&r[2])t.add((0,s.L)(r[2]));else{const r=e.match(/\(([^)]+\.js):\d+:\d+\)/)||e.match(/^\s+at\s+([^\s(]+\.js):\d+:\d+/);r&&r[1]&&t.add((0,s.L)(r[1]))}}return[...t]}function y(){let e;try{const t=Error.stackTraceLimit;Error.stackTraceLimit=50,e=(new Error).stack,Error.stackTraceLimit=t}catch(t){e=(new Error).stack}return e}function b(e,t){return(0,s.L)(e.name)===t}function E(e,t){e.fetchStart=Math.floor(t.startTime),e.fetchEnd=Math.floor(t.responseEnd),e.asset=t.name,e.type=t.initiatorType,w(e,t)}function w(e,t){const r=(0,s.L)(t.name),{weighedAssetUrls:n}=p(e);n.has(r)||(n.add(r),e.totalWeight=(e.totalWeight||0)+(t.transferSize||0),"blocking"===t.renderBlockingStatus?e.renderBlocking=!0:"non-blocking"===t.renderBlockingStatus&&!0!==e.renderBlocking&&(e.renderBlocking=!1))}function R(e,t,r,n,i){if(w(e,t),"scripts"!==i&&"all"!==i)return;if("all"===i||r.isScript){const r=Math.floor(t.startTime),n=Math.floor(t.responseEnd);e.fetchStart=e.fetchStart>0?Math.min(e.fetchStart,r):r,e.fetchEnd=e.fetchEnd>0?Math.max(e.fetchEnd,n):n}if(r.isScript){const r=g((0,s.L)(t.name));if(r){const t=()=>{const{start:t,end:n}=r.script;p(e).recordManifestScriptWindow(t,n)};t(),!r.dom.end&&r.dom.value&&["load","error"].forEach(e=>r.dom.value.addEventListener(e,t,{once:!0}))}n.resolved||(e.asset=t.name,e.type=t.initiatorType,n.resolved=!0)}}function T(e,t){const r=t?.manifest;if(!r||!r.assets.length)return;const s={resolved:!1},a=new Set(r.assets);(n.gm.performance?.getEntriesByType("resource")||[]).forEach(r=>{const n=[...a].find(e=>e.test(r.name));n&&(R(e,r,n,s,t.timingMethod),a.delete(n))}),a.size&&function(e,t,r,s){n.gm.PerformanceObserver?.supportedEntryTypes?.includes("resource")&&f.push({addedAt:(0,i.t)(),test:n=>{const i=[...t].find(e=>e.test(n.name));return i&&(R(e,n,i,r,s),t.delete(i)),0===t.size}})}(e,a,s,t.timingMethod)}function A(e){const t=e?.id,r={registeredAt:(0,i.t)(),reportedAt:void 0,fetchStart:0,fetchEnd:0,scriptStart:0,scriptEnd:0,asset:void 0,type:"unknown",totalWeight:0,renderBlocking:void 0},a=y();if(!a)return r;const o=n.gm.performance?.getEntriesByType("navigation")?.[0]?.name||"";try{const e=v(a),c=(e.length>1?e.filter(e=>u!==e):e)[0];if(!c)return r;if(o.includes(c))return r.asset=(0,s.L)(o),r.type="inline",r;r.correlation=g(c);const l=r.correlation?.performance.value||n.gm.performance?.getEntriesByType("resource")?.find(e=>b(e,c));if(l)E(r,l);else{(function(e){if(!e||!n.gm.document)return!1;try{const t=n.gm.document.querySelectorAll('link[rel="preload"][as="script"]');for(const r of t)if((0,s.L)(r.href)===e)return!0}catch(e){}return!1})(c)&&(r.asset=c,r.type="preload"),function(e,t){n.gm.PerformanceObserver?.supportedEntryTypes?.includes("resource")&&f.push({addedAt:(0,i.t)(),test:r=>!!b(r,t)&&(E(e,r),!0)})}(r,c)}const h=r.correlation,m=!!t&&!!h?.claimedBy.has(t);h&&t&&h.claimedBy.add(t);const y=()=>{const e=h?.script.start;if(!m||!e)return!1;return r.registeredAt-e>1e4};let w=0,R=0;p(r).recordManifestScriptWindow=(e,t)=>{e&&(w=w>0?Math.min(w,e):e),t&&(R=R>0?Math.max(R,t):t)},Object.defineProperty(r,"scriptStart",d(()=>{const e=y()?r.registeredAt:h?.script.start??r.fetchEnd;return w>0?Math.min(e,w):e})),Object.defineProperty(r,"scriptEnd",d(()=>{const e=y()?r.registeredAt:h?.script.end??r.registeredAt;return R>0?Math.max(e,R):e}))}catch(e){}return r}},5732(e,t,r){"use strict";r.d(t,{$5:()=>m,B5:()=>g,K6:()=>u,M$:()=>
5o,Ms:()=>d,NG:()=>c,Ux:()=>h,YA:()=>p,yx:()=>l});var n=r(5718),i=r(7560),s=r(9119),a=r(9232);function o(e){return e?.type===a.f.MFE}function c(e,t){if(!y(e,t))return;const r=t.runtime.registeredEntities;return r?.find(t=>t.metadata.target.iframeInterfaceId===e)}function d(e,t){if(!y(e,t))return[];const r=t.runtime.registeredEntities;return r?.filter(t=>String(t.metadata.target.id)===String(e)).map(e=>e.metadata.target)||[]}function u(e,t){if(!y(e,t))return[];const r=t.runtime.registeredEntities,n=(0,s.L)(e),a=r?.filter(t=>{const r=t.metadata.target?.manifest;return r?(0,i.j)(r,e,{scriptsOnly:!1}):!!t.metadata.timings?.asset&&(0,s.L)(t.metadata.timings.asset)===n});return f(a).map(e=>e.metadata.target)}function l(e,t){if(!y(e,t))return[];const r=t.runtime.registeredEntities,n=r?.filter(t=>{const r=t.metadata.target?.manifest;return r?(0,i.j)(r,e,{scriptsOnly:!0}):!!t.metadata.timings?.asset?.endsWith(e)});return f(n).map(e=>e.metadata.target)}function f(e){if(!e?.length)return e||[];const t=new Map,r=[];for(const n of e){const e=n.metadata?.timings?.asset;if(!e){r.push(n);continue}const i="".concat(e,"::").concat(n.metadata?.target?.id),s=t.get(i);if(s){if(s.metadata.target?.blocked&&!n.metadata.target?.blocked){const e=r.indexOf(s);-1!==e&&(r[e]=n),t.set(i,n)}}else t.set(i,n),r.push(n)}return r}function h(e,t){return v(t)?o(e)?e.attributes:t.agentRef.runtime.v2Target.attributes:{}}function p(e,t){return g(e,t)?{"child.id":e.id,"child.type":e.type,...h(void 0,t)}:{}}function g(e,t){return o(e)&&!!v(t)&&t.agentRef.init.api.register.duplicate_data_to_container}function m(e){if(!e?.runtime)return[];if(!y(!0,e)||!e.runtime.registeredEntities?.length)return[e.runtime.v2Target];const t=[];try{var r=(0,n.AZ)((0,n.QL)());let i=r.length-1;for(;r[i];)t.push(...l(r[i--],e))}catch(e){}const i=function(e){const t=new Set,r=[];for(const n of e){const e=n?.instance;t.has(e)||(t.add(e),r.push(n))}return r}(t);return i.length||i.push(e.runtime.v2Target),i}function v(e){return 2===e?.harvestEndpointVersion}function y(e,t){return!!e&&!!t?.init.api.register.enabled}},5289(e,t,r){"use strict";r.d(t,{GG:()=>a,Qr:()=>c,sB:()=>o});var n=r(3878),i=r(6389);function s(){return"undefined"==typeof document||"complete"===document.readyState}function a(e,t){if(s())return e();const r=(0,i.J)(e),a=setInterval(()=>{s()&&(clearInterval(a),r())},500);(0,n.sp)("load",r,t)}function o(e){if(s())return e();(0,n.DD)("DOMContentLoaded",e)}function c(e){if(s())return e();(0,n.sp)("popstate",e)}},384(e,t,r){"use strict";r.d(t,{Zm:()=>c,bQ:()=>u,dV:()=>d,pV:()=>l});var n=r(6154),i=r(1863),s=r(944),a=r(1910);const o={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net"};function c(){return n.gm.NREUM||(n.gm.NREUM={}),void 0===n.gm.newrelic&&(n.gm.newrelic=n.gm.NREUM),n.gm.NREUM}function d(){let e=c();return e.o||(e.o={ST:n.gm.setTimeout,SI:n.gm.setImmediate||n.gm.setInterval,CT:n.gm.clearTimeout,XHR:n.gm.XMLHttpRequest,REQ:n.gm.Request,EV:n.gm.Event,PR:n.gm.Promise,MO:n.gm.MutationObserver,FETCH:n.gm.fetch,WS:n.gm.WebSocket},(0,a.i)(...Object.values(e.o))),e}function u(e,t){let r=c();r.initializedAgents??={},t.initializedAt={ms:(0,i.t)(),date:new Date},r.initializedAgents[e]=t,2===Object.keys(r.initializedAgents).length&&(0,s.R)(69)}function l(){return function(){let e=c();const t=e.info||{};e.info={beacon:o.beacon,errorBeacon:o.errorBeacon,...t}}(),function(){let e=c();const t=e.init||{};e.init={...t}}(),d(),function(){let e=c();const t=e.loader_config||{};e.loader_config={...t}}(),c()}r.d(t,["NT",0,o])},2843(e,t,r){"use strict";r.d(t,{G:()=>s,u:()=>i});var n=r(3878);function i(e,t=!1,r,i){(0,n.DD)("visibilitychange",function(){if(t)return void("hidden"===document.visibilityState&&e());e(document.visibilityState)},r,i)}function s(e,t,r){(0,n.sp)("pagehide",e,t,r)}},8139(e,t,r){"use strict";r.d(t,{u:()=>f});var n=r(7836),i=r(3434),s=r(8990),a=r(6154);const o={},c=a.gm.XMLHttpRequest,d="addEventListener",u="removeEventListener",l="nr@wrapped:".concat(n.P);function f(e,t){var r=function(e){return(e||n.ee).get("events")}(e);if(o[r.debugId]++)return r;o[r.debugId]=1;var f=(0,i.YM)(r,!0,t);function p(e){f.inPlace(e,[d,u],"-",g)}function g(e,t){return e[1]}return"getPrototypeOf"in Object&&(a.RI&&h(document,p),c&&h(c.prototype,p),h(a.gm,p)),r.on(d+"-start",function(e,t){var r=e[1];if(null!==r&&("function"==typeof r||"object"==typeof r)&&"newrelic"!==e[0]){var n=(0,s.I)(r,l,function(){var e={object:function(){if("function"!=typeof r.handleEvent)return;return r.handleEvent.apply(r,arguments)},function:r}[typeof r];return e?f(e,"fn-",null,e.name||"anonymous"):r});this.wrapped=e[1]=n}}),r.on(u+"-start",function(e){e[1]=this.wrapped||e[1]}),r}function h(e,t,...r){let n=e;for(;"object"==typeof n&&!Object.prototype.hasOwnProperty.call(n,d);)n=Object.getPrototypeOf(n);n&&t(n,...r)}},3434(e,t,r){"use strict";r.d(t,{YM:()=>d});var n=r(7836),i=r(5607),s=r(5732);const a="nr@original:".concat(i.W);var o=Object.prototype.hasOwnProperty,c=!1;function d(e,t,r){return e||(e=n.ee),i.inPlace=function(e,t,r,n,s,a){r||(r="");const o="-"===r.charAt(0);for(let c=0;c<t.length;c++){const d=t[c],u=e[d];l(u)||(e[d]=i(u,o?d+r:r,n,d,s,a))}},i.flag=a,i;function i(t,n,i,c,f,h){return l(t)?t:(n||(n=""),nrWrapper[a]=t,function(e,t,r){if(Object.defineProperty&&Object.keys)try{return Object.keys(e).forEach(function(r){Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t,t}})}),t}catch(e){u([e],r)}for(var n in e)o.call(e,n)&&(t[n]=e[n])}
5(t,nrWrapper,e),nrWrapper);function nrWrapper(){var a,o,l,p;let g,m;try{o=this,a=[...arguments],m=h?(0,s.$5)(r):[r?.runtime?.v2Target],l="function"==typeof i?i(a,o):i||{}}catch(t){u([t,"",[a,o,c],l],e)}d(n+"start",[a,o,c,m],l,f);const v=performance.now();let y;try{return p=t.apply(o,a),y=performance.now(),p}catch(e){throw y=performance.now(),d(n+"err",[a,o,e,m],l,f),g=e,g}finally{const e=y-v,t={start:v,end:y,duration:e,isLongTask:e>=50,methodName:c,thrownError:g};t.isLongTask&&d("long-task",[t,o,m],l,f),d(n+"end",[a,o,p,m],l,f)}}}function d(r,n,i,s){if(!c||t){var a=c;c=!0;try{e.emit(r,n,i,t,s)}catch(t){u([t,r,n,i],e)}c=a}}}function u(e,t){t||(t=n.ee);try{t.emit("internal-error",e)}catch(e){}}function l(e){return!(e&&"function"==typeof e&&e.apply&&!e[a])}r.d(t,["Jt",0,a])},9300(e,t,r){"use strict";const n=r(860).K7.ajax;r.d(t,["TZ",0,n,"f5",0,"ajaxRequest.id","mo",0,{NONE:"none",FAILURES:"failures",ALL:"all"}])},3333(e,t,r){"use strict";var n=r(981);const i=r(860).K7.genericEvents,s=[n.R.PA,n.R.UA,n.R.BP];r.d(t,["$v",0,{RESOURCES:"experimental.resources",REGISTER:"register"},"TZ",0,i,"Zp",0,["auxclick","click","copy","keydown","paste","scrollend"],"kd",0,s,"qN",0,["focus","blur"]])},6774(e,t,r){"use strict";const n=r(860).K7.jserrors;r.d(t,["T",0,n])},993(e,t,r){"use strict";const n=r(860).K7.logging;r.d(t,["A$",0,{OFF:0,ERROR:1,WARN:2,INFO:3,DEBUG:4,TRACE:5},"TZ",0,n,"p_",0,{ERROR:"ERROR",WARN:"WARN",INFO:"INFO",DEBUG:"DEBUG",TRACE:"TRACE"}])},3785(e,t,r){"use strict";r.d(t,{R:()=>c,b:()=>d});var n=r(9908),i=r(1863),s=r(860),a=r(3969),o=r(993);function c(e,t,r={},c=o.p_.INFO,d=!0,u,l=(0,i.t)()){(0,n.p)(a.xV,["API/logging/".concat(c.toLowerCase(),"/called")],void 0,s.K7.metrics,e),(0,n.p)("log",[l,t,r,c,d,u],void 0,s.K7.logging,e)}function d(e){return"string"==typeof e&&Object.values(o.p_).some(t=>t===e.toUpperCase().trim())}},3969(e,t,r){"use strict";const n=r(860).K7.metrics;r.d(t,["TZ",0,n,"XG",0,"storeEventMetrics","xV",0,"storeSupportabilityMetrics"])},6630(e,t,r){"use strict";const n=r(860).K7.pageViewEvent;r.d(t,["T",0,n])},782(e,t,r){"use strict";const n=r(860).K7.pageViewTiming;r.d(t,["T",0,n])},6344(e,t,r){"use strict";var n=r(2614);const i=r(860).K7.sessionReplay,s={[n.g.ERROR]:15e3,[n.g.FULL]:3e5,[n.g.OFF]:0}
5;r.d(t,["Qb",0,{API:"api",RESUME:"resume",SWITCH_TO_FULL:"switchToFull",INITIALIZE:"initialize",PRELOAD:"preload"},"TZ",0,i,"Vh",0,"errorDuringReplay","_s",0,{DomContentLoaded:0,Load:1,FullSnapshot:2,IncrementalSnapshot:3,Meta:4,Custom:5},"bc",0,{RESET:{message:"Session was reset",sm:"Reset"},IMPORT:{message:"Recorder failed to import",sm:"Import"},TOO_MANY:{message:"429: Too Many Requests",sm:"Too-Many"},TOO_BIG:{message:"Payload was too large",sm:"Too-Big"},CROSS_TAB:{message:"Session Entity was set to OFF on another tab",sm:"Cross-Tab"},ENTITLEMENTS:{message:"Session Replay is not allowed and will not be started",sm:"Entitlement"}},"yP",0,s])},5270(e,t,r){"use strict";r.d(t,{Aw:()=>a,SR:()=>s,rF:()=>o});var n=r(384),i=r(7767);function s(e){return!!(0,n.dV)().o.MO&&(0,i.V)(e)&&!0===e?.session_trace.enabled}function a(e){return!0===e?.session_replay.preload&&s(e)}function o(e,t){try{if("string"==typeof t?.type&&"password"===t.type.toLowerCase())return"*".repeat(e?.length||0);if(void 0!==t?.dataset?.nrUnmask||t?.classList?.contains("nr-unmask"))return e}catch(e){}return"string"==typeof e?e.replace(/[\S]/g,"*"):"*".repeat(e?.length||0)}},3738(e,t,r){"use strict";const n=r(860).K7.sessionTrace,i="-start",s="-end",a="fn"+i,o="fn"+s;r.d(t,["He",0,"bstResource","Kp",0,s,"Lc",0,o,"Rz",0,"pushState","TZ",0,n,"bD",0,"resource","bc",0,{CROSS_TAB:{message:"Session Entity was set to OFF on another tab"},ENTITLEMENTS:{message:"Session Trace is not allowed and will not be started"},RESET:{message:"Session was reset"},SESSION_CHANGED:{message:"Session identifier changed unexpectedly"}},"d3",0,i,"uP",0,a])},3962(e,t,r){"use strict";const n=r(860).K7.softNav;r.d(t,["O2",0,{INITIAL_PAGE_LOAD:"",ROUTE_CHANGE:1,UNSPECIFIED:2},"OV",0,"popstate","Qu",0,{INTERACTION:1,AJAX:2,CUSTOM_END:3,CUSTOM_TRACER:4},"TZ",0,n,"ih",0,{IP:"in progress",PF:"pending finish",FIN:"finished",CAN:"cancelled"},"pP",0,"initialPageLoad","tC",0,["click","keydown","submit"]])},4234(e,t,r){"use strict";r.d(t,{W:()=>i});var n=r(1687);class i{constructor(e,t){this.agentRef=e,this.ee=e?.ee,this.featureName=t,this.blocked=!1}deregisterDrain(){(0,n.x3)(this.agentRef,this.featureName)}}},7767(e,t,r){"use strict";var n=r(6154);r.d(t,["V",0,e=>n.RI&&!0===e?.privacy.cookies_enabled])},8362(e,t,r){"use strict";r.d(t,{d:()=>s});var n=r(9566),i=r(1741);class s extends i.W{agentIdentifier=(0,n.LA)(16)}},1741(e,t,r){"use strict";r.d(t,{W:()=>s});var n=r(944),i=r(4261);class s{#e(e,...t){if(this[e]!==s.prototype[e])return this[e](...t);(0,n.R)(35,e)}addPageAction(e,t){return this.#e(i.hG,e,t)}register(e){return this.#e(i.eY,e)}recordCustomEvent(e,t){return this.#e(i.fF,e,t)}setPageViewName(e,t){return this.#e(i.Fw,e,t)}setCustomAttribute(e,t,r){return this.#e(i.cD,e,t,r)}noticeError(e,t){return this.#e(i.o5,e,t)}setUserId(e,t=!1){return this.#e(i.Dl,e,t)}setApplicationVersion(e){return this.#e(i.nb,e)}setErrorHandler(e){return this.#e(i.bt,e)}addRelease(e,t){return this.#e(i.k6,e,t)}log(e,t){return this.#e("log",e,t)}start(){return this.#e("start")}finished(e){return this.#e(i.BL,e)}recordReplay(){return this.#e(i.CH)}pauseReplay(){return this.#e(i.Tb)}addToTrace(e){return this.#e(i.U2,e)}setCurrentRouteName(e){return this.#e(i.PA,e)}interaction(e){return this.#e(i.dT,e)}wrapLogger(e,t,r){return this.#e(i.Wb,e,t,r)}measure(e,t){return this.#e(i.V1,e,t)}consent(e){return this.#e(i.Pv,e)}}},4261(e,t,r){"use strict";r.d(t,["BL",0,"finished","CH",0,"recordReplay","Dl",0,"setUserId","Fw",0,"setPageViewName","PA",0,"setCurrentRouteName","Pv",0,"consent","Tb",0,"pauseReplay","U2",0,"addToTrace","V1",0,"measure","Wb",0,"wrapLogger","bt",0,"setErrorHandler","cD",0,"setCustomAttribute","dT",0,"interaction","eY",0,"register","fF",0,"recordCustomEvent","hG",0,"addPageAction","hw",0,"api-ixn-","k6",0,"addRelease","nb",0,"setApplicationVersion","o5",0,"noticeError"])},1738(e,t,r){"use strict";r.d(t,{U:()=>l,Y:()=>u});var n=r(3241),i=r(9908),s=r(1863),a=r(944),o=r(3969),c=r(8362),d=r(860);function u(e,t,r,s){const u=s||r;!u||u[e]&&u[e]!==c.d.prototype[e]||(u[e]=function(){(0,i.p)(o.xV,["API/"+e+"/called"],void 0,d.K7.metrics,r.ee),(0,n.W)({drained:!!r.runtime?.activatedFeatures,type:"data",name:"api",feature:"api-"+e,data:{}});try{return t.apply(this,arguments)}catch(e){(0,a.R)(23,e)}})}function l(e,t,r,n,a){const o=e.info;null===r?delete o.jsAttributes[t]:o.jsAttributes[t]=r,(a||null===r)&&(0,i.p)("api-"+n,[(0,s.t)(),t,r],void 0,"session",e.ee)}},8374(e,t,r){r.nc=(()=>{try{return document?.currentScript?.nonce}catch(e){}return""})()},860(e,t,r){"use strict";const n="events",i="jserrors",s="browser/blobs",a="browser/logs",o={ajax:"ajax",genericEvents:"generic_events",jserrors:i,logging:"logging",metrics:"metrics",pageAction:"page_action",pageViewEvent:"page_view_event",pageViewTiming:"page_view_timing",sessionReplay:"session_replay",sessionTrace:"session_trace",softNav:"soft_navigations"},c={[o.pageViewEvent]:1,[o.pageViewTiming]:2,[o.metrics]:3,[o.jserrors]:4,[o.softNav]:5,[o.ajax]:6,[o.sessionTrace]:7,[o.sessionReplay]:8,[o.logging]:9,[o.genericEvents]:10},d={[o.pageViewEvent]:"rum",[o.pageViewTiming]:n,[o.ajax]:n,[o.softNav]:n,[o.metrics]:i,[o.jserrors]:i,[o.sessionTrace]:s,[o.sessionReplay]:s,[o.logging]:a,[o.genericEvents]:"ins"};r.d(t,["$J",0,d,"K7",0,o,"P3",0,c,"XX",0,i,"Yy",0,a,"df",0,s,"hg",0,"connect"])}};const t={};function r(n){const i=t[n];if(void 0!==i)return i.exports;const s=t[n]={exports:{}};return e[n](s,s.exports,r),s.exports}r.m=e,r.d=(e,t)=>{if(Array.isArray(t))for(var n=0;n<t.length;){var i=t[n++],s=t[n++];r.o(e,i)?0===s&&n++:0===s?Object.defineProperty(e,i,{enumerable:!0,value:t[n++]}):Object.defineProperty(e,i,{enumerable:!0,get:s})}else for(var i in t)r.o(t,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,n)=>(r.f[n](e,t),t),[])),r.u=e=>({212:"nr-spa-compressor",238:"nr-spa-iframe-message-handler",249:"nr-spa-recorder",478:"nr-spa"}[e]+"-1.322.0.min.js"),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{const e={},t="NRBA-1.322.0.PROD:";r.l=(n,i,s,a)=>
5{if(e[n])return void e[n].push(i);let o,c;if(void 0!==s){const e=document.getElementsByTagName("script");for(var d=0;d<e.length;d++){const r=e[d];if(r.getAttribute("src")==n||r.getAttribute("data-webpack")==t+s){o=r;break}}}if(!o){c=!0;var u={478:"sha512-SARROoir04gFygxlr/+mTI+PyMeFL+epi1vnUA2G5mTQ7s3G44ItQBJKbOaIMdIE5OBzuaKhb4k5JYta0NICxg==",249:"sha512-6DKQo5WP7YlpzX6l9UfYkgGLGK2oITdoaYTcZtgl5Foa22NY63lED/0z1hBBLeD7qZCz/YdlY19/r8drlol1tg==",212:"sha512-CYxuvSpDx6ErqWJwAvpoHn54eY37YdMcFao/axOumlw3BsSL7yioOeB2LWViY/Njs818sQG10dSglUhYCMfLPw==",238:"sha512-mvbMILWa3ohYst+u6TLfNrmtY2swUIB3rbJFN/uzt3W62KhgvUVwB81UEZ1R0/it5bfrQ5EVz864pi/CAmucNQ=="};o=document.createElement("script"),o.charset="utf-8",r.nc&&o.setAttribute("nonce",r.nc),o.setAttribute("data-webpack",t+s),o.src=n,0!==o.src.indexOf(window.location.origin+"/")&&(o.crossOrigin="anonymous"),u[a]&&(o.integrity=u[a])}e[n]=[i];const l=(t,r)=>{o.onerror=o.onload=null,clearTimeout(f);const i=e[n];if(delete e[n],o.parentNode?.removeChild(o),i?.forEach(e=>e(r)),t)return t(r)},f=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),c&&document.head.appendChild(o)}})(),r.r=e=>{Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="https://js-agent.newrelic.com/",(()=>{const e={38:0,788:0};r.f.j=(t,n)=>{let i=r.o(e,t)?e[t]:void 0;if(0!==i)if(i)n.push(i[2]);else{const s=new Promise((r,n)=>i=e[t]=[r,n]);n.push(i[2]=s);const a=r.p+r.u(t),o=new Error,c=n=>{if(r.o(e,t)&&(i=e[t],0!==i&&(e[t]=void 0),i)){const e=n&&("load"===n.type?"missing":n.type),r=n&&n.target&&n.target.src;o.message="Loading chunk "+t+" failed: ("+e+": "+r+")",o.name="ChunkLoadError",o.type=e,o.request=r,i[1](o)}};r.l(a,c,"chunk-"+t,t)}};const t=(t,n)=>{let[i,s,a]=n;var o,c,d=0;if(i.some(t=>0!==e[t])){for(o in s)r.o(s,o)&&(r.m[o]=s[o]);if(a)a(r)}for(t&&t(n);d<i.length;d++)c=i[d],r.o(e,c)&&e[c]&&e[c][0](),e[c]=0},n=self["webpackChunk:NRBA-1.322.0.PROD"]=self["webpackChunk:NRBA-1.322.0.PROD"]||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})(),(()=>{"use strict";r(8374);var e=r(8362),t=r(860);const n=Object.values(t.K7);var i=r(384),s=r(1741);var a=r(2555),o=r(3333),c=r(9300);const d=e=>{if(!e||"string"!=typeof e)return!1;try{document.createDocumentFragment().querySelector(e)}catch{return!1}return!0};var u=r(2614),l=r(944),f=r(8122);const h="[data-nr-mask]",p=e=>(0,f.a)(e,(()=>{const e={feature_flags:[],experimental:{register:!1,resources:!1,iframe_bridge:!1,iframe_domains:[]},mask_selector:"*",block_selector:"[data-nr-block]",mask_input_options:{color:!1,date:!1,"datetime-local":!1,email:!1,month:!1,number:!1,range:!1,search:!1,tel:!1,text:!1,time:!1,url:!1,week:!1,textarea:!1,select:!1,password:!0}};return{ajax:{deny_list:void 0,block_internal:!0,enabled:!0,autoStart:!0,capture_payloads:c.mo.NONE},api:{register:{get enabled(){return e.feature_flags.includes(o.$v.REGISTER)||e.experimental.register},set enabled(t){e.experimental.register=t},duplicate_data_to_container:!1,get allow_iframe_bridge(){return e.feature_flags.includes(o.$v.IFRAME_BRIDGE)||e.experimental.iframe_bridge},set allow_iframe_bridge(t){e.experimental.iframe_bridge=t},get iframe_domains(){return e.experimental.iframe_domains},set iframe_domains(t){Array.isArray(t)?e.experimental.iframe_domains=t:(0,l.R)(1,t)}}},browser_consent_mode:{enabled:!1},distributed_tracing:{enabled:void 0,exclude_newrelic_header:void 0,cors_use_newrelic_header:void 0,cors_use_tracecontext_headers:void 0,allowed_origins:void 0},get feature_flags(){return e.feature_flags},set feature_flags(t){e.feature_flags=t},generic_events:{enabled:!0,autoStart:!0},harvest:{interval:30},jserrors:{enabled:!0,autoStart:!0},logging:{enabled:!0,autoStart:!0},metrics:{enabled:!0,autoStart:!0},obfuscate:void 0,page_action:{enabled:!0},page_view_event:{enabled:!0,autoStart:!0},page_view_timing:{enabled:!0,autoStart:!0},performance:{capture_marks:!1,capture_measures:!1,capture_detail:!0,resources:{get enabled(){return e.feature_flags.includes(o.$v.RESOURCES)||e.experimental.resources},set enabled(t){e.experimental.resources=t},asset_types:[],first_party_domains:[],ignore_newrelic:!0}},privacy:{cookies_enabled:!0},proxy:{assets:void 0,beacon:void 0},session:{expiresMs:u.wk,inactiveMs:u.BB},session_replay:{autoStart:!0,enabled:!1,preload:!1,sampling_rate:10,error_sampling_rate:100,collect_fonts:!1,inl
5ine_images:!1,fix_stylesheets:!0,mask_all_inputs:!0,get mask_text_selector(){return e.mask_selector},set mask_text_selector(t){d(t)?e.mask_selector="".concat(t,",").concat(h):""===t||null===t?e.mask_selector=h:(0,l.R)(5,t)},get block_class(){return"nr-block"},get ignore_class(){return"nr-ignore"},get mask_text_class(){return"nr-mask"},get block_selector(){return e.block_selector},set block_selector(t){d(t)?e.block_selector+=",".concat(t):""!==t&&(0,l.R)(6,t)},get mask_input_options(){return e.mask_input_options},set mask_input_options(t){t&&"object"==typeof t?e.mask_input_options={...t,password:!0}:(0,l.R)(7,t)}},session_trace:{enabled:!0,autoStart:!0},soft_navigations:{enabled:!0,autoStart:!0},ssl:void 0,user_actions:{enabled:!0,elementAttributes:["id","className","tagName","type"]},web_sockets:{enabled:!1}}})());var g=r(6154),m=r(9324);let v=0;const y={buildEnv:"PROD",distMethod:"CDN",version:m.x,originTime:g.WN},b={consented:!1},E={activatedFeatures:void 0,appMetadata:{},configured:!1,get consented(){return this.session?.state?.consent||b.consented},set consented(e){b.consented=e},customTransaction:void 0,denyList:[],disabled:!1,drainRegistry:new Map,connector:void 0,harvester:void 0,v2Target:void 0,isolatedBacklog:!1,isRecording:!1,loaderType:void 0,maxBytes:3e4,obfuscator:void 0,onerror:void 0,ptid:void 0,releaseIds:{},session:void 0,timeKeeper:void 0,registeredEntities:[],jsAttributesMetadata:{bytes:0},get harvestCount(){return++v},listeningForIframeMessages:!1};var w=r(9232);var R=r(7836),T=r(3241);const A={accountID:void 0,trustKey:void 0,agentID:void 0,licenseKey:void 0,applicationID:void 0,xpid:void 0};var S=r(9908),x=r(9752);function O(e,t={},n,o){let{init:c,info:d,loader_config:u,runtime:l={},exposed:h=!0}=t;if(!d){const e=(0,i.pV)();c=e.init,d=e.info,u=e.loader_config}var m;e.init=p(c||{}),e.loader_config=(m=u||{},(0,f.a)(m,A)),d.jsAttributes??={},g.bv&&(d.jsAttributes.isWorker=!0),e.info=(0,a.D)(d);const v=e.init;e.runtime??=(e=>{const t=(0,f.a)(e,E),r=Object.keys(y).reduce((e,t)=>(e[t]={value:y[t],writable:!1,configurable:!0,enumerable:!0},e),{});return Object.defineProperties(t,r)})(l),e.runtime.v2Target??={type:w.f.BA,instance:e.agentIdentifier,get id(){return e.runtime.appMetadata?.agents?.[0]?.entityGuid},get attributes(){return{"entity.guid":this.id,appId:e.info.applicationID}}},v.proxy.assets&&(e=>{const t=e.startsWith("http");e+="/",r.p=t?e:"https://"+e})(v.proxy.assets),e.runtime.configured||(Object.defineProperty(e,"beacons",{get:()=>[e.info.beacon,e.info.errorBeacon,e.init.proxy.assets,e.init.proxy.beacon].filter(Boolean)}),Object.defineProperty(e.runtime,"denyList",{get:()=>[...e.init.ajax.deny_list||[],...e.init.ajax.block_internal?e.beacons:[]]}),e.runtime.ptid=e.agentIdentifier,function(e){const t=(0,i.pV)();Object.getOwnPropertyNames(s.W.prototype).forEach(r=>{const n=s.W.prototype[r];if("function"!=typeof n||"constructor"===n)return;let i=t[r];e[r]&&!1!==e.exposed&&"micro-agent"!==e.runtime?.loaderType&&(t[r]=(...t)=>{const n=e[r](...t);return i?i(...t):n})})}(e),e.runtime.loaderType=n,e.ee=R.ee.get(e.agentIdentifier),e.exposed=h,(0,T.W)({drained:!!e.runtime.activatedFeatures,type:"lifecycle",name:"initialize",feature:void 0,data:e.config}),e.init.api.register.allow_iframe_bridge&&g.gm.addEventListener("message",t=>{"string"==typeof t.data?.type&&t.data.type.startsWith(x.Pl)&&(0,S.p)("iframe-message",[t],void 0,"IFRAME",e.ee)}),e.runtime.configured=!0)}var _=r(1863),k=r(4261),N=r(1738);var L=r(1687),M=r(4234),P=r(5289),I=r(5270),j=r(7767),C=r(6389),D=r(7699);const B=new WeakSet,H=new WeakMap;class W extends M.W{constructor(e,t){super(e,t),this.abortHandler=void 0,this.featAggregate=void 0,this.loadedSuccessfully=void 0,this.onAggregateImported=new Promise(e=>{this.loadedSuccessfully=e}),this.deferred=Promise.resolve(),!1===e.init[this.featureName].autoStart?this.deferred=new Promise((t,r)=>{this.ee.on("manual-start-all",(0,C.J)(()=>{(0,L.Ak)(e,this.featureName),t()}))}):(0,L.Ak)(e,t)}importAggregator(e,t,n={}){if(this.featAggregate)return;const i=async()=>{if(await this.deferred,this.#t(e),!(0,a.f)(e.info))return(0,l.R)(43),e.ee.abort(),void this.loadedSuccessfully(!1);try{await async function(e,t,n){if(H.has(e))return H.get(e);const i=(async()=>
5{if((0,j.V)(e.init))try{const{setupAgentSession:t}=await r.e(478).then(r.bind(r,8766));t(e)}catch(e){(0,l.R)(20,e),t.emit("internal-error",[e]),(0,S.p)(D.qh,[e],void 0,n,t)}if(e.init.api.register.allow_iframe_bridge)try{const{setupIframeMFEMessageListener:t}=await r.e(238).then(r.bind(r,6417));t(e)}catch(e){(0,l.R)(23,e)}const[{Connector:i},{Harvester:s}]=await Promise.all([r.e(478).then(r.bind(r,6589)),r.e(478).then(r.bind(r,5237))]);e.runtime.connector=new i(e),e.runtime.harvester=new s(e);const a=Object.values(e.features).filter(t=>e.runtime.drainRegistry.has(t.featureName));Promise.all(a.map(e=>e.onAggregateImported)).then(()=>e.runtime.harvester.startTimer())})();H.set(e,i),await i}(e,this.ee,this.featureName)}catch(e){return(0,l.R)(79,e),this.ee.abort(),void this.loadedSuccessfully(!1)}try{if(!this.#r(this.featureName,e.runtime.session,e.init))return this.abortHandler?.(),(0,L.Ze)(this.agentRef,this.featureName),void this.loadedSuccessfully(!1);const{Aggregate:r}=await t();this.featAggregate=new r(e,n),e.runtime.harvester.initializedAggregates.push(this.featAggregate),this.loadedSuccessfully(!0)}catch(e){(0,l.R)(34,e),this.abortHandler?.(),(0,L.Ze)(this.agentRef,this.featureName,!0),this.loadedSuccessfully(!1)}};g.RI?(0,P.GG)(()=>i(),!0):i()}#r(e,r,n){if(this.blocked)return!1;switch(e){case t.K7.sessionReplay:return(0,I.SR)(n)&&!!r;case t.K7.sessionTrace:return!!r;default:return!0}}#t(e){if(!B.has(e)&&(B.add(e),!(0,a.f)(e.info))){const t=(0,i.pV)();let r={...t.info?.jsAttributes};try{r={...r,...e.info?.jsAttributes}}catch(e){}O(e,{...t,info:{...t.info,jsAttributes:r},runtime:e.runtime},e.runtime.loaderType)}}}var U=r(6630);class K extends W{static featureName=U.T;constructor(e){var t;super(e,U.T),this.setupInspectionEvents(),t=e,(0,N.Y)(k.Fw,function(e,r){"string"==typeof e&&("/"!==e.charAt(0)&&(e="/"+e),t.runtime.customTransaction=(r||"http://custom.transaction")+e,(0,S.p)("api-"+k.Fw,[(0,_.t)()],void 0,void 0,t.ee))},t),this.importAggregator(e,()=>e.init.feature_flags.includes("rum_v2")?r.e(478).then(r.bind(r,908)):r.e(478).then(r.bind(r,7927)))}setupInspectionEvents(){const e=(e,t)=>{e&&(0,T.W)({timeStamp:e.timeStamp,loaded:"complete"===e.target.readyState,type:"window",name:t,data:e.target.location+""})};(0,P.sB)(t=>{e(t,"DOMContentLoaded")}),(0,P.GG)(t=>{e(t,"load")}),(0,P.Qr)(t=>{e(t,"navigate")}),this.ee.on(u.tS.UPDATE,(e,t)=>{(0,T.W)({type:"lifecycle",name:"session",data:t})})}}class F extends e.d{constructor(e){var t;(super(),g.gm)?(this.features={},(0,i.bQ)(this.agentIdentifier,this),this.desiredFeatures=new Set(e.features||[]),this.desiredFeatures.add(K),O(this,e,e.loaderType||"agent"),t=this,(0,N.Y)(k.cD,function(e,r,n=!1){if("string"==typeof e){if(["string","number","boolean"].includes(typeof r)||null===r)return(0,N.U)(t,e,r,k.cD,n);(0,l.R)(40,typeof r)}else(0,l.R)(39,typeof e)},t),function(e){(0,N.Y)(k.Dl,function(t,r=!1){if("string"!=typeof t&&null!==t)return void(0,l.R)(41,typeof t);const n=e.info.jsAttributes["enduser.id"];r&&null!=n&&n!==t?(0,S.p)("api-setUserIdAndResetSession",[t],void 0,"session",e.ee):(0,N.U)(e,"enduser.id",t,k.Dl,!0)},e)}(this),function(e){(0,N.Y)(k.nb,function(t){if("string"==typeof t||null===t)return(0,N.U)(e,"application.version",t,k.nb,!1);(0,l.R)(42,typeof t)},e)}(this),function(e){(0,N.Y)("start",function(){e.ee.emit("manual-start-all")},e)}(this),function(e){(0,N.Y)(k.Pv,function(t=!0){if("boolean"==typeof t){if((0,S.p)("api-"+k.Pv,[t],void 0,"session",e.ee),e.runtime.consented=t,t){const t=e.features.page_view_event;t.onAggregateImported.then(e=>{const r=t.featAggregate;e&&!r.sentRum&&r.sendRum?.()})}}else(0,l.R)(65,typeof t)},e)}(this),this.run()):(0,l.R)(21)}get config(){return{info:this.info,init:this.init,loader_config:this.loader_config,runtime:this.runtime}}get api(){return this}run(){try{const e=function(e){const t={};return n.forEach(r=>{t[r]=!!e[r]?.enabled}),t}(this.init),r=[...this.desiredFeatures],i=this.init.feature_flags.includes("rum_v2");r.sort((e,r)=>t.P3[e.featureName]-t.P3[r.featureName]),r.forEach(r=>{if(!e[r.featureName]&&(i||r.featureName!==t.K7.pageViewEvent))return;const n=function(e){switch(e){case t.K7.ajax:return[t.K7.jserrors];case t.K7.sessionTrace:return[t.K7.ajax,t.K7.pageViewEvent];case t.K7.sessionReplay:return[t.K7.sessionTrace];case t.K7.pageViewTiming:return[t.K7.pageViewEvent];default:return[]}}(r.featureName).filter(e=>!(e in this.features));n.length>0&&(0,l.R)(36,{targetFeature:r.featureName,missingDependencies:n}),this.features[r.featureName]=new r(this)})}catch(e){(0,l.R)(22,e);for(const e in this.features)this.features[e].abortHandler?.();const t=(0,i.Zm)();delete t.initializedAgents[this.agentIdentifier]?.features,delete this.sharedAggregator;return t.ee.get(this.agentIdentifier).abort(),!1}}}var V=r(2843),z=r(782);class G extends W{static featureName=z.T;constructor(e){super(e,z.T),g.RI&&((0,V.u)(()=>(0,S.p)("docHidden",[(0,_.t)()],void 0,z.T,this.ee),!0),(0,V.G)(()=>(0,S.p)("winPagehide",[(0,_.t)()],void 0,z.T,this.ee)),this.importAggregator(e,()=>r.e(478).then(r.bind(r,9917))))}}var q=r(3969);class Y extends W{static featureName=q.TZ;constructor(e){super(e,q.TZ),this.importAggregator(e,()=>r.e(478).then(r.bind(r,6555)))}}var Z=r(6774),J=r(3878),X=r(3304);class Q{constructor(e,t,r,n,i){this.name="UncaughtError",this.message="string"==typeof e?e:(0,X.A)(e),this.sourceURL=t,this.line=r,this.column=n,this.__newrelic=i}}function ee(e){return ne(e)?e:new Q(void 0!==e?.message?e.message:e,e?.filename||e?.sourceURL,e?.lineno||e?.line,e?.colno||e?.col,e?.__newrelic,e?.cause)}function te(e){const t="Unhandled Promise Rejection: ";if(!e?.reason)return;if(ne(e.reason)){try{e.reason.message.startsWith(t)||(e.reason.message=t+e.reason.message)}catch(e){}return ee(e.reason)}const r=ee(e.reason);return(r.message||"").startsWith(t)||(r.message=t+r.message),r}function re(e){if(e.error instanceof SyntaxError&&!/:\d+$/.test(e.error.stack?.trim())){const t=new Q(e.message,e.filename,e.lineno,e.colno,e.error.__newrelic,e.cause);return t.name=SyntaxError.name,t}return ne(e.error)?e.error:ee(e)}function ne(e){return e instanceof Error&&!!e.stack}function ie(e,r,n,i,s=(0,_.t)()){"string"==typeof e&&(e=new Error(e)),(0,S.p)("err",[e,s,!1,r,n.runtime.isRecording,void 0,i],void 0,t.K7.jserrors,n.ee),(0,S.p)("uaErr",[],void 0,t.K7.genericEvents,n.ee)}var se=r(993),ae=r(3785);function oe(e,{customAttributes:t={},level:r=se.p_.INFO}={},n,i,s=(0,_.t)()){(0,ae.R)(n.ee,e,t,r,!1,i,s)}function ce(e,r,n,i,s=(0,_.t)()){(0,S.p)("api-"+k.hG,[s,e,r,i],void 0,t.K7.genericEvents,n.ee)}function de(e,r,n,i,s=(0,_.t)()){const{start:a,end:o,customAttributes:c}=r||{},d={customAttributes:c||{}};if("object"!=typeof d.customAttributes||"string"!=typeof e||0===e.length)return void(0,l.R)(57);const u=(e,t)=>
5null==e?t:"number"==typeof e?e:e instanceof PerformanceMark?e.startTime:Number.NaN;if(d.start=u(a,0),d.end=u(o,s),Number.isNaN(d.start)||Number.isNaN(d.end))(0,l.R)(57);else{if(d.duration=d.end-d.start,!(d.duration<0))return(0,S.p)("api-"+k.V1,[d,e,i],void 0,t.K7.genericEvents,n.ee),d;(0,l.R)(58)}}function ue(e,r={},n,i,s=(0,_.t)()){(0,S.p)("api-"+k.fF,[s,e,r,i],void 0,t.K7.genericEvents,n.ee)}var le=r(5718);const fe=(e,t)=>e?.nrMfeId===t.id&&(!e?.nrMfeObserved||e?.nrMfeObserved===t.instance),he=e=>{try{return g.gm.CSS.escape(e)}catch(t){return e}},pe=(e,t={})=>{const r=t.id,n=t.instance;if(!e||!r||!n)return!1;try{let r=1===e.nodeType?e:e.parentElement;for(;r?.tagName;){if(fe(r.dataset,t))return r.dataset.nrMfeObserved=n,!0;r=r.parentNode}}catch(e){}return!1},ge=(e,t)=>{const r=g.gm.document?.querySelectorAll('[data-nr-mfe-id="'.concat(he(e.id),'"]')),n=(Array.from(r)||[]).find(t=>fe(t.dataset,e));let i=!!n;i&&(n.dataset.nrMfeObserved??=e.instance);const s=new g.gm.MutationObserver(r=>{r.forEach(r=>{r.addedNodes.forEach(r=>{const n=1===r.nodeType?r:null;!i&&fe(n?.dataset,e)&&(s.disconnect(),s.observe(n,{childList:!0,subtree:!0}),i=!0,n.dataset.nrMfeObserved=e.instance),(e=>{try{return e?.textContent?.trim()||["img","video","canvas","svg"].includes(e?.nodeName?.toLowerCase())}catch(e){return!1}})(r)&&(i||pe(r,e))&&t(r,s)})})});return s.observe(n||g.gm.document,{childList:!0,subtree:!0}),s},me=(e,t,r)=>{try{const n=new g.gm.PerformanceObserver(e=>{e.getEntries().forEach(r)});return n.observe(t),e.push(n),n}catch(e){return null}};function ve(e,t){let r,n,i=!1;const s=e=>null==e?e:e-(t?.scriptStart||t?.registeredAt||0),a={fcp:{get value(){const e=s(r);return e>1e4?void 0:e},set value(e){i||(r=e)}},lcp:{get value(){if(void 0!==a.fcp.value)return s(n)},set value(e){i||(n=e)}},cls:{value:void 0},inp:{value:void 0},disconnect:()=>{}};if(!(e&&g.RI&&g.gm.MutationObserver&&g.gm.PerformanceObserver))return a;const o=[];setTimeout(()=>{r||a.disconnect()},1e4);const c=()=>{if(!i){if(null==r){const e=(0,_.t)();if(s(e)>1e4)return void a.disconnect();r=e}n??=(0,_.t)(),a.cls.value??=0}},d=ge(e,(e,t)=>{c(),t.disconnect()});o.push(d);let u=0,l=null;const f=new Set;try{l=new g.gm.ResizeObserver(e=>{i||e.forEach(e=>{try{const t=e.contentRect.width*e.contentRect.height;t>u&&(u=t,a.lcp.value=(0,_.t)()),l.unobserve(e.target)}catch(e){}})})}catch(e){}const h=ge(e,e=>{if(c(),l)try{const t=1===e.nodeType?e:e.parentElement;t&&!f.has(t)&&(f.add(t),"IMG"===t.tagName?t.complete?l.observe(t):t.addEventListener("load",()=>{l.observe(t)},{once:!0}):"VIDEO"===t.tagName?t.readyState>=2?l.observe(t):t.addEventListener("loadeddata",()=>{l.observe(t)},{once:!0}):l.observe(t))}catch(e){}});l&&o.push(l),o.push(h),me(o,{type:"layout-shift",buffered:!0},t=>{i||t.hadRecentInput||(t.sources||[]).some(r=>!!pe(r.node,e)&&(c(),a.cls.value+=t.value,!0))}),me(o,{type:"event",buffered:!0,durationThreshold:40},t=>{!i&&t.interactionId&&pe(t.target,e)&&(void 0===a.inp.value||t.duration>a.inp.value)&&(c(),a.inp.value=t.duration)});const p=["pointerdown","keydown"],m=()=>{p.forEach(e=>{g.gm.removeEventListener(e,v,{passive:!0})})};a.disconnect=()=>{i=!0,o.forEach(e=>{try{e?.disconnect()}catch(e){}}),m(),["visibilitychange","pagehide"].forEach(e=>{g.gm.removeEventListener(e,a.disconnect,{once:!0,passive:!0})})};const v=t=>{pe(t?.target,e)&&((()=>{try{h?.disconnect(),l?.disconnect()}catch(e){}})(),m())};p.forEach(e=>{g.gm.addEventListener(e,v,{passive:!0})}),["visibilitychange","pagehide"].forEach(e=>{g.gm.addEventListener(e,a.disconnect,{once:!0,passive:!0})});const y=g.gm.document?.querySelectorAll('[data-nr-mfe-id="'.concat(he(e.id),'"]'));return Array.from(y||[]).some(t=>fe(t.dataset,e))&&c(),a}var ye=r(9566),be=r(7560),Ee=r(9119);const we=["entry","scripts","all"],Re=["name","id","type"],Te=new Map([[ce,"addPageAction"],[oe,"log"],[de,"measure"],[ie,"noticeError"],[ue,"recordCustomEvent"]]),Ae={experimental:(0,C.J)(()=>(0,l.R)(54,"newrelic.register")),disabled:(0,C.J)(()=>(0,l.R)(55)),invalidTarget:(0,C.J)(e=>(0,l.R)(48,e)),deregistered:(0,C.J)(()=>(0,l.R)(68)),invalidTimingMethod:(0,C.J)(e=>(0,l.R)(80,e)),duplicateName:(0,C.J)(e=>(0,l.R)(81,e)),duplicateId:(0,C.J)(e=>(0,l.R)(82,e))};function Se(e){(0,N.Y)(k.eY,function(t){return xe(e,t)},e)}function xe(e,r){Ae.experimental(),r||={},r.instance=(0,ye.LA)(8),r.type=w.f.MFE,r.licenseKey||=e.info.licenseKey,r.blocked=!1,("object"!=typeof r.tags||null===r.tags||Array.isArray(r.tags))&&(r.tags={}),r.parent??={get id(){return e.runtime.appMetadata.agents?.[0].entityGuid},type:w.f.BA},r.manifest=(0,be.N)(r.manifest),void 0===r.timingMethod||we.includes(r.timingMethod)||(Ae.invali
5dTimingMethod(r.timingMethod),r.timingMethod=void 0);const n=(0,le.Qr)(r);r.manifest&&(0,le.xo)(n,r);const i=ve(r,n),s=(0,Ee.L)(""+location),a={};Object.prototype.hasOwnProperty.call(r,"attributes")||Object.defineProperty(r,"attributes",{get:()=>({...a,"source.id":r.id,"source.name":r.name,"source.type":r.type,"parent.type":r.parent?.type||w.f.BA,"parent.id":r.parent?.id})}),Object.entries(r.tags).forEach(([e,t])=>{Re.includes(e)||(a["source.".concat(e)]=t)});let o=()=>{};const c=e.runtime.registeredEntities,d=e=>{r.blocked=!0,o=e};function u(e){return"string"==typeof e&&!!e.trim()&&e.trim().length<501}e.init.api.register.enabled||d(Ae.disabled),u(r.id)&&u(r.name)||d(()=>Ae.invalidTarget(r)),c.forEach(e=>{try{const{name:t,id:n}=e.metadata.target;t===r.name&&n!==r.id&&Ae.duplicateName(r),n===r.id&&t!==r.name&&Ae.duplicateId(r)}catch(e){}});const f={addPageAction:(t,n={})=>m(ce,[t,{...a,...n},e],r),deregister:()=>{p(),d(Ae.deregistered)},log:(t,n={})=>m(oe,[t,{...n,customAttributes:{...a,...n.customAttributes||{}}},e],r),measure:(t,n={})=>m(de,[t,{...n,customAttributes:{...a,...n.customAttributes||{}}},e],r),noticeError:(t,n={})=>m(ie,[t,{...a,...n},e],r),recordCustomEvent:(t,n={})=>m(ue,[t,{...a,...n},e],r),setApplicationVersion:e=>g("application.version",e),setCustomAttribute:(e,t)=>g(e,t),setUserId:e=>g("enduser.id",e),metadata:{get customAttributes(){return a},target:r,timings:n,vitals:i,events:{latestTimestamp:void 0}}},h=()=>(r.blocked&&o(),r.blocked);function p(){if(n.reportedAt)return;n.reportedAt=(0,_.t)(),i.disconnect(),n.fcp=i.fcp,n.lcp=i.lcp,n.cls=i.cls,n.inp=i.inp;const e=n.fetchEnd-n.fetchStart,t=n.scriptEnd-n.scriptStart,r={assetUrl:n.asset,assetType:n.type,registerUrl:s,deregisterUrl:(0,Ee.L)(""+location),pageUrl:void 0,currentUrl:void 0,timeAlive:n.reportedAt-n.registeredAt,timeToBeRequested:n.fetchStart,timeToExecute:t,timeToFetch:e,timeToLoad:e+t,t
5imeToRegister:n.registeredAt,totalWeight:n.totalWeight,...void 0!==n.renderBlocking&&{renderBlocking:n.renderBlocking},...i.fcp.value>=0&&{"vitals.fcp.value":i.fcp.value},...i.lcp.value>=0&&{"vitals.lcp.value":i.lcp.value},...i.cls.value>=0&&{"vitals.cls.value":i.cls.value},...i.inp.value>=0&&{"vitals.inp.value":i.inp.value}};f.recordCustomEvent("MicroFrontEndTiming",r)}h()||(c.push(f),(0,V.G)(p));const g=(e,t)=>{h()||(a[e]=t)},m=(r,n,i)=>{if(h()&&r!==xe)return;const s=f.metadata.events.latestTimestamp??(0,_.t)();f.metadata.events.latestTimestamp=void 0;const a=Te.get(r)||"unknown";(0,S.p)(q.xV,["API/register/".concat(a,"/called")],void 0,t.K7.metrics,e.ee);try{return r(...n,i,s)}catch(e){(0,l.R)(50,e)}};return f}class Oe extends W{static featureName=Z.T;constructor(e){var t;super(e,Z.T),t=e,(0,N.Y)(k.o5,(e,r)=>ie(e,r,t),t),function(e){(0,N.Y)(k.bt,function(t){e.runtime.onerror=t},e)}(e),function(e){let t=0;(0,N.Y)(k.k6,function(e,r){++t>10||(this.runtime.releaseIds[e.slice(-200)]=(""+r).slice(-200))},e)}(e),Se(e);try{this.removeOnAbort=new AbortController}catch(e){}this.ee.on("internal-error",(t,r)=>{this.abortHandler&&(0,S.p)("ierr",[ee(t),(0,_.t)(),!0,{},e.runtime.isRecording,r],void 0,this.featureName,this.ee)}),g.gm.addEventListener("unhandledrejection",t=>{this.abortHandler&&(0,S.p)("err",[te(t),(0,_.t)(),!1,{unhandledPromiseRejection:1},e.runtime.isRecording],void 0,this.featureName,this.ee)},(0,J.jT)(!1,this.removeOnAbort?.signal)),g.gm.addEventListener("error",t=>{this.abortHandler&&(0,S.p)("err",[re(t),(0,_.t)(),!1,{},e.runtime.isRecording],void 0,this.featureName,this.ee)},(0,J.jT)(!1,this.removeOnAbort?.signal)),this.abortHandler=this.#n,this.importAggregator(e,()=>r.e(478).then(r.bind(r,9377)))}#n(){this.removeOnAbort?.abort(),this.abortHandler=void 0}}var _e=r(8990);let ke=1;function Ne(e){const t=typeof e;return!e||"object"!==t&&"function"!==t?-1:e===g.gm?0:(0,_e.I)(e,"nr@id",function(){return ke++})}function Le(e){if("string"==typeof e)return e.length;if("object"==typeof e){if("undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer&&e.byteLength)return e.byteLength;if("undefined"!=typeof Blob&&e instanceof Blob&&e.size)return e.size;if(!("undefined"!=typeof FormData&&e instanceof FormData))try{return(0,X.A)(e).length}catch(e){return}}}var Me=r(8139),Pe=r(3434),Ie=r(5732);const je={},Ce=["open","send","setRequestHeader"];function De(e,t){var r=e||R.ee;const n=function(e){return(e||R.ee).get("xhr")}(r);if(void 0===g.gm.XMLHttpRequest)return n;if(je[n.debugId]++)return n;je[n.debugId]=1,(0,Me.u)(r,t);var i=(0,Pe.YM)(n,void 0,t),s=g.gm.XMLHttpRequest,a=g.gm.MutationObserver,o=g.gm.Promise,c=g.gm.setInterval,d="readystatechange",u=["onload","onerror","onabort","onloadstart","onloadend","onprogress","ontimeout"],f=[],h=g.gm.XMLHttpRequest=function(e){const r=new s(e),a=n.context(r);a.targets=(0,Ie.$5)(t);try{n.emit("new-xhr",[r],a),r.addEventListener(d,(o=a,function(){var e=this;e.readyState>3&&!o.resolved&&(o.resolved=!0,n.emit("xhr-resolved",[],e)),i.inPlace(e,u,"fn-",E)}),(0,J.jT)(!1))}catch(e){(0,l.R)(15,e);try{n.emit("internal-error",[e])}catch(e){}}var o;return r};function p(e,t){i.inPlace(t,["onreadystatechange"],"fn-",E)}if(function(e,t){for(var r in e)t[r]=e[r]}(s,h),h.prototype=s.prototype,i.inPlace(h.prototype,Ce,"-xhr-",E),n.on("send-xhr-start",function(e,t){p(e,t),function(e){f.push(e),a&&(m?m.then(b):c?c(b):(v=-v,y.data=v))}(t)}),n.on("open-xhr-start",p),a){var m=o&&o.resolve();if(!c&&!o){var v=1,y=document.createTextNode(v);new a(b).observe(y,{characterData:!0})}}else r.on("fn-end",function(e){e[0]&&e[0].type===d||b()});function b(){for(var e=0;e<f.length;e++)p(0,f[e]);f.length&&(f=[])}function E(e,t){return t}return n}var Be="fetch-",He=Be+"body-",We=["arrayBuffer","blob","json","text","formData"],Ue=g.gm.Request,Ke=g.gm.Response,Fe="prototype";const Ve={};function ze(e,t){const r=function(e){return(e||R.ee).get("fetch")}(e);if(!(Ue&&Ke&&g.gm.fetch))return r;if(Ve[r.debugId]++)return r;function n(e,n,i){var s=e[n];"function"==typeof s&&(e[n]=function(){var e=[...arguments];const n={},a=(0,Ie.$5)(t);var o;r.emit(i+"before-start",[e],n),n[R.P]&&n[R.P].dt&&(o=n[R.P].dt);var c=s.apply(this,e);return r.emit(i+"start",[e,o],c),c.then(function(e){return r.emit(i+"end",[null,e,a],c),e},function(e){throw r.emit(i+"end",[e,void 0,a],c),e})})}
5return Ve[r.debugId]=1,We.forEach(e=>{n(Ue[Fe],e,He),n(Ke[Fe],e,He)}),n(g.gm,"fetch",Be),r.on(Be+"end",function(e,n,i){var s=this;if(s.targets=i||[t.runtime.v2Target],n){var a=n.headers.get("content-length");null!==a&&(s.rxSize=a),r.emit(Be+"done",[null,n],s)}else r.emit(Be+"done",[e],s)}),r}var Ge=r(7485);class qe{constructor(e){this.agentRef=e}generateTracePayload(e){const t=this.agentRef.loader_config;if(!this.shouldGenerateTrace(e)||!t)return null;var r=(t.accountID||"").toString()||null,n=(t.agentID||"").toString()||null,i=(t.trustKey||"").toString()||null;if(!r||!n)return null;var s=(0,ye.ZF)(),a=(0,ye.el)(),o=Date.now(),c={spanId:s,traceId:a,timestamp:o};return(e.sameOrigin||this.isAllowedOrigin(e)&&this.useTraceContextHeadersForCors())&&(c.traceContextParentHeader=this.generateTraceContextParentHeader(s,a),c.traceContextStateHeader=this.generateTraceContextStateHeader(s,o,r,n,i)),(e.sameOrigin&&!this.excludeNewrelicHeader()||!e.sameOrigin&&this.isAllowedOrigin(e)&&this.useNewrelicHeaderForCors())&&(c.newrelicHeader=this.generateTraceHeader(s,a,o,r,n,i)),c}generateTraceContextParentHeader(e,t){return"00-"+t+"-"+e+"-01"}generateTraceContextStateHeader(e,t,r,n,i){return i+"@nr=0-1-"+r+"-"+n+"-"+e+"----"+t}generateTraceHeader(e,t,r,n,i,s){if(!("function"==typeof g.gm?.btoa))return null;var a={v:[0,1],d:{ty:"Browser",ac:n,ap:i,id:e,tr:t,ti:r}};return s&&n!==s&&(a.d.tk=s),btoa((0,X.A)(a))}shouldGenerateTrace(e){return this.agentRef.init?.distributed_tracing?.enabled&&this.isAllowedOrigin(e)}isAllowedOrigin(e){var t=!1;const r=this.agentRef.init?.distributed_tracing;if(e.sameOrigin)t=!0;else if(r?.allowed_origins instanceof Array)for(var n=0;n<r.allowed_origins.length;n++){var i=(0,Ge.D)(r.allowed_origins[n]);if(e.hostname===i.hostname&&e.protocol===i.protocol&&e.port===i.port){t=!0;break}}return t}excludeNewrelicHeader(){var e=this.agentRef.init?.distributed_tracing;return!!e&&!!e.exclude_newrelic_header}useNewrelicHeaderForCors(){var e=this.agentRef.init?.distributed_tracing;return!!e&&!1!==e.cors_use_newrelic_header}useTraceContextHeadersForCors(){var e=this.agentRef.init?.distributed_tracing;return!!e&&!!e.cors_use_tracecontext_headers}}var Ye=r(7295);function Ze(e){return"string"==typeof e?e:e instanceof(0,i.dV)().o.REQ?e.url:g.gm?.URL&&e instanceof URL?e.href:void 0}function $e(e,t){var r=(0,Ge.D)(t),n=e.params||e;n.hostname=r.hostname,n.port=r.port,n.protocol=r.protocol,n.host=r.hostname+":"+r.port,n.pathname=r.pathname,e.parsedOrigin=r,e.sameOrigin=r.sameOrigin}var Je=["load","error","abort","timeout"],Xe=Je.length,Qe=(0,i.dV)().o.REQ,et=(0,i.dV)().o.XHR;const tt="X-NewRelic-App-Data",rt="internal-error";class nt extends W{static featureName=c.TZ;constructor(e){super(e,c.TZ),this.dt=new qe(e),this.handler=(e,t,r,n)=>(0,S.p)(e,t,r,n,this.ee);try{const e={xmlhttprequest:"xhr",fetch:"fetch",beacon:"beacon"};g.gm?.performance?.getEntriesByType("resource").forEach(r=>{if(r.initiatorType in e&&0!==r.responseStatus){const n={status:r.responseStatus},i={rxSize:r.transferSize,duration:Math.floor(r.duration),cbTime:0};$e(n,r.name),this.handler("xhr",[n,i,r.startTime,r.responseEnd,e[r.initiatorType]],void 0,t.K7.ajax)}})}catch(e){}ze(this.ee,e),De(this.ee,e),function(e,r,n,i){const s=[c.mo.ALL,c.mo.FAILURES].includes(e.init.ajax?.capture_payloads);function a(e){var t=this;t.totalCbs=0,t.called=0,t.cbTime=0,t.end=A,t.ended=!1,t.xhrGuids={},t.lastSize=null,t.loadCaptureCalled=!1,t.params=this.params||{},t.metrics=this.metrics||{},t.latestLongtaskEnd=0,e.addEventListener("load",function(r){O(t,e)},(0,J.jT)(!1)),g.lR||e.addEventListener("progress",function(e){t.lastSize=e.loaded},(0,J.jT)(!1))}function o(e){this.params={method:e[0]},$e(this,e[1]),this.metrics={}}function d(t,r){e.loader_config.xpid&&this.sameOrigin&&r.setRequestHeader("X-NewRelic-ID",e.loader_config.xpid);var n=i.generateTracePayload(this.parsedOrigin);if(n){var s=!1;n.newrelicHeader&&(r.setRequestHeader("newrelic",n.newrelicHeader),s=!0),n.traceContextParentHeader&&(r.setRequestHeader("traceparent",n.traceContextParentHeader),n.traceContextStateHeader&&r.setRequestHeader("tracestate",n.traceContextStateHeader),s=!0),s&&(this.dt=n)}}function u(e,t){s&&e.length>=2&&(this.requestHeaders??={},this.requestHeaders[e[0].toLowerCase()]=e[1])}function l(e,t){var n=this.metrics,i=e[0],s=this;if(n&&i){var a=Le(i);a&&(n.txSize=a)}this.startTime=(0,_.t)(),this.requestBody=i,this.listener=function(e){try{"abort"!==e.type||s.loadCaptureCalled||(s.params.aborted=!0),("load"
5!==e.type||s.called===s.totalCbs&&(s.onloadCalled||"function"!=typeof t.onload)&&"function"==typeof s.end)&&s.end(t)}catch(e){try{r.emit(rt,[e])}catch(e){}}};for(var o=0;o<Xe;o++)t.addEventListener(Je[o],this.listener,(0,J.jT)(!1))}function f(e,t,r){this.cbTime+=e,t?this.onloadCalled=!0:this.called+=1,this.called!==this.totalCbs||!this.onloadCalled&&"function"==typeof r.onload||"function"!=typeof this.end||this.end(r)}function h(e,t){var r=""+Ne(e)+!!t;this.xhrGuids&&!this.xhrGuids[r]&&(this.xhrGuids[r]=!0,this.totalCbs+=1)}function p(e,t){var r=""+Ne(e)+!!t;this.xhrGuids&&this.xhrGuids[r]&&(delete this.xhrGuids[r],this.totalCbs-=1)}function m(){this.endTime=(0,_.t)()}function v(e,t){t instanceof et&&"load"===e[0]&&r.emit("xhr-load-added",[e[1],e[2]],t)}function y(e,t){t instanceof et&&"load"===e[0]&&r.emit("xhr-load-removed",[e[1],e[2]],t)}function b(e,t,r){t instanceof et&&("onload"===r&&(this.onload=!0),("load"===(e[0]&&e[0].type)||this.onload)&&(this.xhrCbStart=(0,_.t)()))}function E(e,t){this.xhrCbStart&&r.emit("xhr-cb-time",[(0,_.t)()-this.xhrCbStart,this.onload,t],t)}function w(e){var t,r=e[1]||{};if("string"==typeof e[0]?0===(t=e[0]).length&&g.RI&&(t=""+g.gm.location.href):e[0]&&e[0].url?t=e[0].url:g.gm?.URL&&e[0]&&e[0]instanceof URL?t=e[0].href:"function"==typeof e[0].toString&&(t=e[0].toString()),"string"==typeof t&&0!==t.length){t&&(this.parsedOrigin=(0,Ge.D)(t),this.sameOrigin=this.parsedOrigin.sameOrigin);var n=i.generateTracePayload(this.parsedOrigin);if(n&&(n.newrelicHeader||n.traceContextParentHeader))if(e[0]&&e[0].headers)o(e[0].headers,n)&&(this.dt=n);else{var s={};for(var a in r)s[a]=r[a];s.headers=new Headers(r.headers||{}),o(s.headers,n)&&(this.dt=n),e.length>1?e[1]=s:e.push(s)}}function o(e,t){var r=!1;return t.newrelicHeader&&(e.set("newrelic",t.newrelicHeader),r=!0),t.traceContextParentHeader&&(e.set("traceparent",t.traceContextParentHeader),t.traceContextStateHeader&&e.set("tracestate",t.traceContextStateHeader),r=!0),r}}function R(e,t){this.params={},this.metrics={},this.startTime=(0,_.t)(),this.dt=t;let[r,n={}]=e;$e(this,Ze(r));const i=(""+(r&&r instanceof Qe&&r.method||n.method||"GET")).toUpperCase();this.params.method=i,this.txSize=Le(n.body||r?.body)||0;try{var a=n.headers||r?.headers;if(s&&a)if(this.requestHeaders??={},a instanceof Headers)a.forEach(function(e,t){this.requestHeaders[t.toLowerCase()]=e}.bind(this));else if("object"==typeof a)for(var o in a)this.requestHeaders[o.toLowerCase()]=a[o]}catch(e){}this.requestBody=n.body||r?.body}function T(e,t){if(this.endTime=(0,_.t)(),this.params||(this.params={}),(0,Ye.iW)(this.params))return;this.params.status=t?t.status:0;const n=()=>{const e=+this.rxSize,t=null==this.rxSize||isNaN(e)?void 0:e,r={txSize:this.txSize,rxSize:t,duration:this.endTime-this.startTime},n=[this.params,r,this.startTime,this.endTime,"fetch"];this.targets.forEach(e=>x(n,this,e))};t&&s?t.clone().text().then(e=>{this.responseBody=e,this.rxSize&&"0"!==this.rxSize&&0!==this.rxSize||void 0===e||0===this.params.status||(this.rxSize=Le(e)),t?.headers&&(this.responseHeaders={},t.headers.forEach(function(e,t){this.responseHeaders[t.toLowerCase()]=e}.bind(this)))}).catch(e=>{r.emit(rt,[e])}).finally(()=>{n()}):n()}function A(e){const t=this.params,n=this.metrics;if(this.ended)return;this.ended=!0;for(let t=0;t<Xe;t++)e.removeEventListener(Je[t],this.listener,!1);if(t.aborted)return;if((0,Ye.iW)(t))return;if(n.duration=this.endTime-this.startTime,this.loadCaptureCalled||4!==e.readyState?null==t.status&&(t.status=0):O(this,e),n.cbTime=this.cbTime,s){try{this.responseBody=e.responseText}catch(t){this.responseBody=e.response}if((!n.rxSize||0===n.rxSize)&&void 0!==this.responseBody&&0!==t.status){const e=Le(this.responseBody);void 0!==e&&(n.rxSize=e)}try{this.responseHeaders=function(e){const t={};return e?(e.split("\r\n").forEach(function(e){const r=e.indexOf(": ");if(r>0){const n=e.substring(0,r),i=e.substring(r+2);t[n.toLowerCase()]=i}}),t):t}(e.getAllResponseHeaders())}catch(e){r.emit(rt,[e])}}const i=[t,n,this.startTime,this.endTime,"xhr"];this.targets.forEach(e=>x(i,this,e))}function x(e,r,i){n("xhr",[...e,i],r,t.K7.ajax)}function O(e,n){e.params.status=n.status;var i=function(e,t){var r=e.responseType;return"json"===r&&null!==t?t:"arraybuffer"===r||"blob"===r||"json"===r?Le(e.response):"text"===r||""===r||void 0===r?Le(e.responseText):void 0}(n,e.lastSize);if(void 0!==i&&0!==n.status&&(e.metrics.rxSize=i),e.sameOrigin&&n.getAllResponseHeaders().indexOf(tt)>=0){var s=n.getResponseHeader(tt);s&&((0,S.p)("sm",["Ajax/CrossApplicationTracing/Header/Seen"],void 0,t.K7.metrics,r),e.params.cat=s.split(", ").pop())}e.loadCaptureCalled=!0}r.on("new-xhr",a),r.on("open-xhr-start",o),r.on("open-xhr-end",d),r.on("send-xhr-start",l),r.on("setRequestHeader-xhr-start",u),r.on("xhr-cb-time",f),r.on("xhr-load-added",h),r.on("xhr-load-removed",p),r.on("xhr-resolved",m),r.on("addEventListener-end",v),r.on("removeEventListener-end",y),r.on("fn-end",E),r.on("fetch-before-start",w),r.on("fetch-start",R),r.on("fn-start",b),r.on("fetch-done",T)}(e,this.ee,this.handler,this.dt),this.importAggregator(e,()=>r.e(478).then(r.bind(r,3845)))}}const it={},st=["pushState","replaceState"];function at(e,t){const r=function(e){return(e||R.ee).get("history")}(e);return!g.RI||it[r.debugId]++||(it[r.debugId]=1,(0,Pe.YM)(r,void 0,t).inPlace(window.history,st,"-")),r}var ot=r(3738);function ct(e){(0,N.Y)(k.BL,function(r=Date.now()){const n=r-g.WN;n<0&&(0,l.R)(62,r),(0,S.p)(q.XG,[k.BL,{time:n}],void 0,t.K7.metrics,e.ee),e.addToTrace({name:k.BL,start:r,origin:"nr"}),(0,S.p)("api-"+k.hG,[n,k.BL],void 0,t.K7.genericEvents,e.ee)},e)}const{He:dt,bD:ut,d3:lt,Kp:ft,TZ:ht,Lc:pt,uP:gt,Rz:mt}=ot;class vt extends W{static featureName=ht;constructor(e){var n;super(e,ht),n=e,(0,N.Y)(k.U2,function(e){if(!(e&&"object"==typeof e&&e.name&&e.start))return;const r={n:e.name,s:e.start-g.WN,e:(e.end||e.start)-g.WN,o:e.origin||"",t:"api"};r.s<0||r.e<0||r.e<r.s?(0,l.R)(61,{start:r.s,end:r.e}):(0,S.p)("bstApi",[r],void 0,t.K7.sessionTrace,n.ee)},n),ct(e);
5if(!(0,j.V)(e.init))return void this.deregisterDrain();const i=this.ee;let s;at(i,e),this.eventsEE=(0,Me.u)(i,e),this.eventsEE.on(gt,function(e,t){this.bstStart=(0,_.t)()}),this.eventsEE.on(pt,function(e,r){(0,S.p)("bst",[e[0],r,this.bstStart,(0,_.t)()],void 0,t.K7.sessionTrace,i)}),i.on(mt+lt,function(e){this.time=(0,_.t)(),this.startPath=location.pathname+location.hash}),i.on(mt+ft,function(e){(0,S.p)("bstHist",[location.pathname+location.hash,this.startPath,this.time],void 0,t.K7.sessionTrace,i)});try{s=new PerformanceObserver(e=>{const r=e.getEntries();(0,S.p)(dt,[r],void 0,t.K7.sessionTrace,i)}),s.observe({type:ut,buffered:!0})}catch(e){}this.importAggregator(e,()=>r.e(478).then(r.bind(r,6974)),{resourceObserver:s})}}var yt=r(733),bt=r(6344);class Et extends W{static featureName=bt.TZ;#i;recorder;constructor(e){var n;let i;super(e,bt.TZ),n=e,(0,N.Y)(k.CH,function(){(0,S.p)(k.CH,[],void 0,t.K7.sessionReplay,n.ee)},n),function(e){(0,N.Y)(k.Tb,function(){(0,S.p)(k.Tb,[],void 0,t.K7.sessionReplay,e.ee)},e)}(e);const s="".concat(u.Wt).concat((0,yt.Y)(e.info.licenseKey,e.info.applicationID));try{i=JSON.parse(localStorage.getItem(s))}catch(e){}(0,I.SR)(e.init)&&this.ee.on(k.CH,()=>this.#s()),this.#a(i)&&this.importRecorder().then(e=>{e.startRecording(bt.Qb.PRELOAD,i?.sessionReplayMode)}),this.abortHandler=this.#n,this.importAggregator(this.agentRef,()=>r.e(478).then(r.bind(r,6167)),this),this.ee.on("err",e=>{this.blocked||this.agentRef.runtime.isRecording&&(this.errorNoticed=!0,(0,S.p)(bt.Vh,[e],void 0,this.featureName,this.ee))})}#a(e){return e&&(e.sessionReplayMode===u.g.FULL||e.sessionReplayMode===u.g.ERROR)||(0,I.Aw)(this.agentRef.init)}importRecorder(){return this.recorder?Promise.resolve(this.recorder):(this.#i??=Promise.all([r.e(478),r.e(249)]).then(r.bind(r,4866)).then(({Recorder:e})=>(this.recorder=new e(this),this.recorder)).catch(e=>{throw this.ee.emit("internal-error",[e]),this.blocked=!0,e}),this.#i)}#s(){this.blocked||(this.featAggregate?this.featAggregate.mode!==u.g.FULL&&this.featAggregate.initializeRecording(u.g.FULL,!0,bt.Qb.API):this.importRecorder().then(()=>{this.recorder.startRecording(bt.Qb.API,u.g.FULL)}))}#n(){this.recorder?.stopRecording()}}var wt=r(3962);class Rt extends W{static featureName=wt.TZ;constructor(e){if(super(e,wt.TZ),function(e){const r=e.ee.get("tracer");function n(){}(0,N.Y)(k.dT,function(e){return(new n).get("object"==typeof e?e:{})},e);const i=n.prototype={createTracer:function(n,i){var s={},a=this,o="function"==typeof i;return(0,S.p)(q.xV,["API/createTracer/called"],void 0,t.K7.metrics,e.ee),function(){if(r.emit((o?"":"no-")+"fn-start",[(0,_.t)(),a,o],s),o)try{return i.apply(this,arguments)}catch(e){const t="string"==typeof e?new Error(e):e;throw r.emit("fn-err",[arguments,this,t],s),t}finally{r.emit("fn-end",[(0,_.t)()],s)}}}};["actionText","setName","setAttribute","save","ignore","onEnd","getContext","end","get"].forEach(r=>{N.Y.apply(this,[r,function(){return(0,S.p)(k.hw+r,[performance.now(),...arguments],this,t.K7.softNav,e.ee),this},e,i])}),(0,N.Y)(k.PA,function(){(0,S.p)(k.hw+"routeName",[performance.now(),...arguments],void 0,t.K7.softNav,e.ee)},e)}(e),!g.RI||!(0,i.dV)().o.MO)return;const n=at(this.ee,e);try{this.removeOnAbort=new AbortController}catch(e){}wt.tC.forEach(e=>{(0,J.sp)(e,e=>{c(e)},!0,this.removeOnAbort?.signal)}
5);const s=()=>(0,S.p)("newURL",[(0,_.t)(),""+window.location],void 0,this.featureName,this.ee);n.on("pushState-end",s),n.on("replaceState-end",s),(0,J.sp)(wt.OV,e=>{c(e),(0,S.p)("newURL",[e.timeStamp,""+window.location],void 0,this.featureName,this.ee)},!0,this.removeOnAbort?.signal);let a=!1;const o=new((0,i.dV)().o.MO)((e,t)=>{a||(a=!0,requestAnimationFrame(()=>{(0,S.p)("newDom",[(0,_.t)()],void 0,this.featureName,this.ee),a=!1}))}),c=(0,C.s)(e=>{"loading"!==document.readyState&&((0,S.p)("newUIEvent",[e],void 0,this.featureName,this.ee),o.observe(document.body,{attributes:!0,childList:!0,subtree:!0,characterData:!0}))},100,{leading:!0});this.abortHandler=function(){this.removeOnAbort?.abort(),o.disconnect(),this.abortHandler=void 0},this.importAggregator(e,()=>r.e(478).then(r.bind(r,4393)),{domObserver:o})}}var Tt=r(981);const At={},St=new Set;function xt(e){return"string"==typeof e?{type:"string",size:(new TextEncoder).encode(e).length}:e instanceof ArrayBuffer?{type:"ArrayBuffer",size:e.byteLength}:e instanceof Blob?{type:"Blob",size:e.size}:e instanceof DataView?{type:"DataView",size:e.byteLength}:ArrayBuffer.isView(e)?{type:"TypedArray",size:e.byteLength}:{type:"unknown",size:0}}class Ot{constructor(e,t){this.timestamp=(0,_.t)(),this.currentUrl=(0,Ee.L)(window.location.href),this.socketId=(0,ye.LA)(8),this.requestedUrl=(0,Ee.L)(e),this.requestedProtocols=Array.isArray(t)?t.join(","):t||"",this.openedAt=void 0,this.protocol=void 0,this.extensions=void 0,this.binaryType=void 0,this.messageOrigin=void 0,this.messageCount=0,this.messageBytes=0,this.messageBytesMin=0,this.messageBytesMax=0,this.messageTypes=void 0,this.sendCount=0,this.sendBytes=0,this.sendBytesMin=0,this.sendBytesMax=0,this.sendTypes=void 0,this.closedAt=void 0,this.closeCode=void 0,this.closeReason="unknown",this.closeWasClean=void 0,this.connectedDuration=0,this.hasErrors=void 0}}class _t extends W{static featureName=o.TZ;constructor(e){super(e,o.TZ);const n=e.init.feature_flags.includes("websockets")||e.init.web_sockets?.enabled,s=!e.init.feature_flags.includes("no_spv"),a=[e.init.page_action.enabled,e.init.performance.capture_marks,e.init.performance.capture_measures,e.init.performance.resources.enabled,e.init.user_actions.enabled,n,s];var c;let d;if(c=e,(0,N.Y)(k.hG,(e,t)=>ce(e,t,c),c),function(e){(0,N.Y)(k.fF,(t,r)=>ue(t,r,e),e)}(e),ct(e),Se(e),function(e){(0,N.Y)(k.V1,(t,r)=>de(t,r,e),e)}(e),this.removeOnAbort=new AbortController,this.abortHandler=()=>{this.removeOnAbort.abort(),this.abortHandler=void 0},n){const u=function(e,t){if(!(0,i.dV)().o.WS)return e;const r=e.get("websockets");if(At[r.debugId]++)return r;At[r.debugId]=1,(0,V.G)(()=>{const e=(0,_.t)();St.forEach(t=>{t.nrData.closedAt=e,t.nrData.closeCode=1001,t.nrData.closeReason="Page navigating away",t.nrData.closeWasClean=!1,t.nrData.openedAt&&(t.nrData.connectedDuration=e-t.nrData.openedAt),r.emit("ws",[t.nrData,t.targets],t)})});
5class n extends WebSocket{static name=Tt.R.WS;static toString(){return"function WebSocket() { [native code] }"}toString(){return"[object WebSocket]"}get[Symbol.toStringTag](){return n.name}#o(e){(e.__newrelic??={}).socketId=this.nrData.socketId,this.nrData.hasErrors??=!0}constructor(...e){super(...e),this.nrData=new Ot(e[0],e[1]),this.targets=(0,Ie.$5)(t),this.addEventListener("open",()=>{this.nrData.openedAt=(0,_.t)(),["protocol","extensions","binaryType"].forEach(e=>{this.nrData[e]=this[e]}),St.add(this)}),this.addEventListener("message",e=>{const{type:t,size:r}=xt(e.data);this.nrData.messageOrigin??=(0,Ee.L)(e.origin),this.nrData.messageCount++,this.nrData.messageBytes+=r,this.nrData.messageBytesMin=Math.min(this.nrData.messageBytesMin||1/0,r),this.nrData.messageBytesMax=Math.max(this.nrData.messageBytesMax,r),(this.nrData.messageTypes??"").includes(t)||(this.nrData.messageTypes=this.nrData.messageTypes?"".concat(this.nrData.messageTypes,",").concat(t):t)}),this.addEventListener("close",e=>{this.nrData.closedAt=(0,_.t)(),this.nrData.closeCode=e.code,e.reason&&(this.nrData.closeReason=e.reason),this.nrData.closeWasClean=e.wasClean,this.nrData.connectedDuration=this.nrData.closedAt-this.nrData.openedAt,St.delete(this),r.emit("ws",[this.nrData,this.targets],this)})}addEventListener(e,t,...r){const n=this,i="function"==typeof t?function(...e){try{return t.apply(this,e)}catch(e){throw n.#o(e),e}}:t?.handleEvent?{handleEvent:function(...e){try{return t.handleEvent.apply(t,e)}catch(e){throw n.#o(e),e}}}:t;return super.addEventListener(e,i,...r)}send(e){if(this.readyState===WebSocket.OPEN){const{type:t,size:r}=xt(e);this.nrData.sendCount++,this.nrData.sendBytes+=r,this.nrData.sendBytesMin=Math.min(this.nrData.sendBytesMin||1/0,r),this.nrData.sendBytesMax=Math.max(this.nrData.sendBytesMax,r),(this.nrData.sendTypes??"").includes(t)||(this.nrData.sendTypes=this.nrData.sendTypes?"".concat(this.nrData.sendTypes,",").concat(t):t)}try{return super.send(e)}catch(e){throw this.#o(e),e}}close(...e){try{super.close(...e)}catch(e){throw this.#o(e),e}}}return g.gm.WebSocket=n,r}(this.ee,e);u.on("ws",(e,t)=>{(0,S.p)("ws-complete",[e,t],void 0,this.featureName,this.ee)})}if(s){if("function"==typeof g.gm.ReportingObserver){const l=new g.gm.ReportingObserver(e=>{e.forEach(e=>{(0,S.p)("spv",[kt(e),(0,_.t)()],void 0,t.K7.genericEvents,this.ee)}),l.disconnect()},{types:["csp-violation"],buffered:!0});l.observe()}g.gm.addEventListener("securitypolicyviolation",e=>{(0,S.p)("spv",[kt(e),e.timeStamp],void 0,t.K7.genericEvents,this.ee)},(0,J.jT)(!1,this.removeOnAbort.signal))}if(g.RI){if(ze(this.ee,e),De(this.ee,e),d=at(this.ee,e),e.init.user_actions.enabled){function f(t){const r=(0,Ge.D)(t);return e.beacons.includes(r.hostname+":"+r.port)}function h(){d.emit("navChange")}o.Zp.forEach(e=>(0,J.sp)(e,e=>(0,S.p)("ua",[e],void 0,this.featureName,this.ee),!0)),o.qN.forEac
5h(e=>{const t=(0,C.s)(e=>{(0,S.p)("ua",[e],void 0,this.featureName,this.ee)},500,{leading:!0});(0,J.sp)(e,t)}),g.gm.addEventListener("error",()=>{(0,S.p)("uaErr",[],void 0,t.K7.genericEvents,this.ee)},(0,J.jT)(!1,this.removeOnAbort.signal)),this.ee.on("open-xhr-start",(e,r)=>{f(e[1])||r.addEventListener("readystatechange",()=>{2===r.readyState&&(0,S.p)("uaXhr",[],void 0,t.K7.genericEvents,this.ee)},(0,J.jT)(void 0,this.removeOnAbort.signal))}),this.ee.on("fetch-start",e=>{e.length>=1&&!f(Ze(e[0]))&&(0,S.p)("uaXhr",[],void 0,t.K7.genericEvents,this.ee)}),d.on("pushState-end",h),d.on("replaceState-end",h),window.addEventListener("hashchange",h,(0,J.jT)(!0,this.removeOnAbort.signal)),window.addEventListener("popstate",h,(0,J.jT)(!0,this.removeOnAbort.signal))}if(e.init.performance.resources.enabled&&g.gm.PerformanceObserver?.supportedEntryTypes.includes("resource")){new PerformanceObserver(e=>{e.getEntries().forEach(e=>{(0,S.p)("browserPerformance.resource",[e],void 0,this.featureName,this.ee)})}).observe({type:"resource",buffered:!0})}}a.some(e=>e)?this.importAggregator(e,()=>r.e(478).then(r.bind(r,8019))):this.deregisterDrain()}}function kt(e){const t=e.body??e;return{blockedUrl:t.blockedURL??e.blockedURI,documentUrl:t.documentURL??e.documentURI,effectiveDirective:t.effectiveDirective,originalPolicy:t.originalPolicy,sourceFile:t.sourceFile,statusCode:t.statusCode,lineNumber:t.lineNumber,columnNumber:t.columnNumber,disposition:"reporting"===t.disposition?"report":t.disposition,sample:t.sample,referrer:t.referrer}}var Nt=r(2646);const Lt=new Map;function Mt(e,t,r,n,i=!0,s){if("object"!=typeof t||!t||"string"!=typeof r||!r||"function"!=typeof t[r])return(0,l.R)(29);const a=function(e){return(e||R.ee).get("logger")}(e),o=(0,Pe.YM)(a,void 0,s),c=new Nt.y(R.P);c.level=n.level,c.customAttributes=n.customAttributes,c.autoCaptured=i;const d=t[r]?.[Pe.Jt]||t[r];return Lt.set(d,c),o.inPlace(t,[r],"wrap-logger-",()=>Lt.get(d),void 0,!0),a}var Pt=r(1910);class It extends W{static featureName=se.TZ;constructor(e){var t;super(e,se.TZ),t=e,(0,N.Y)("log",(e,r)=>oe(e,r,t),t),function(e){(0,N.Y)(k.Wb,(t,r,{customAttributes:n={},level:i=se.p_.INFO}={})=>{Mt(e.ee,t,r,{customAttributes:n,level:i},!1,e)},e)}(e),Se(e);const n=this.ee;["log","error","warn","info","debug","trace"].forEach(t=>{(0,Pt.i)(g.gm.console[t]),Mt(n,g.gm.console,t,{level:"log"===t?"info":t},void 0,e)}),this.ee.on("wrap-logger-end",function([t],r,i,s=[e.runtime.v2Target]){const{level:a,customAttributes:o,autoCaptured:c}=this;s.forEach(e=>{(0,ae.R)(n,t,o,a,c,e)})}),this.importAggregator(e,()=>r.e(478).then(r.bind(r,5288)))}}new F({features:[nt,K,G,vt,Et,Y,Oe,_t,It,Rt],loaderType:"spa"})})()})();</script>
5
6<meta name="title" content="Customer Login"/>
7<meta name="description" content="We are Canada’s favourite chocolatier. We offer online shopping with quick delivery and in-shop experiences. We use premium ingredients and sustainable cocoa."/>
8<meta name="keywords" content="Chocolate Shop, Premium Chocolate, Purdys Chocolatier"/>
9<meta name="robots" content="NOINDEX, NOFOLLOW"/>
10<meta name="viewport" content="width=device-width, initial-scale=1"/>
11<title>Customer Login</title>
12<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/css/styles.css" />
13<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Amasty_Base/vendor/slick/amslick.min.css" />
14<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Amasty_Storelocator/vendor/chosen/chosen.min.css" />
15<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/FME_FreeShippingBar/css/fme.shipping.bar.css" />
16<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Squareup_Omni/css/loyalty-main.css" />
17<link  rel="stylesheet" type="text/css"  media="all" href="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Amasty_CustomTabs/css/source/mkcss/amtabs.css" />
18<script  type="text/javascript"  src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/MW2Consulting_Csr/js/custom.js"></script>
vendor: 1 bytes, line 18
18
19<script  type="text/javascript"  src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Purdys_CustomWeltPixelEvents/js/custom-weltpixel-utils.js"></script>
vendor: 1 bytes, line 19
19
20<script  type="text/javascript"  defer="defer" src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Hyva_MagentoDataServices/js/storefront-event-collector.js"></script>
vendor: 1 bytes, line 20
20
21<script  type="text/javascript"  defer="defer" src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Hyva_MagentoDataServices/js/storefront-events-sdk.js"></script>
vendor: 1 bytes, line 21
21
22<script  type="text/javascript"  defer="defer" src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Hyva_MagentoLiveSearch/js/sdk.js"></script>
22
23<link  rel="icon" type="image/x-icon" href="https://www.purdys.com/media/favicon/stores/1/favicon-1.png" />
24<link  rel="shortcut icon" type="image/x-icon" href="https://www.purdys.com/media/favicon/stores/1/favicon-1.png" />
25<!-- InApp Redirect script  -->
26<script
27  id="iar"
28  src="https://rum.auditzy.com/mhpFPEJo-www.purdys.com-iar.js"
29  async
30></script>
30
31 <!-- Cookie Banner A/B Testing -->
32<script> 
33if (posthog.getFeatureFlag('cookie-banner-overlay') === 'new-cookie-script-overlay') { 
34   // OPTION B - New Cookie-Script with overlay 
35   var geoScript = document.createElement('script'); 
36   geoScript.type = 'text/javascript'; 
37   geoScript.charset = 'UTF-8'; 
38   geoScript.src = '//geo.cookie-script.com/s/139842e979acded53b241b42b2d1563f.js?country=us'; 
39   
40   var cdnScript = document.createElement('script'); 
41   cdnScript.type = 'text/javascript'; 
42   cdnScript.charset = 'UTF-8'; 
43   cdnScript.src = '//cdn.cookie-script.com/s/a60af434dfb8b4ecd1abb4af42ea0c3e.js'; 
44   document.head.appendChild(geoScript); document.head.appendChild(cdnScript); 
45} else { 
46      //OPTION A - Current Cookie-Script 
47      //Default/control behaviour 
48      var geoScript = document.createElement('script'); 
49      geoScript.type = 'text/javascript'; 
50      geoScript.charset = 'UTF-8'; 
51      geoScript.src = '//geo.cookie-script.com/s/6b73d7e24bd549d182dfed45d6c65c4c.js?country=us'; 
52      var cdnScript = 
53      document.createElement('script'); 
54      cdnScript.type = 'text/javascript'; 
55      cdnScript.charset = 'UTF-8'; 
56      cdnScript.src = '//cdn.cookie-script.com/s/b13066c855c83cfcb1e83d6450f5d8b9.js'; 
57      document.head.appendChild(geoScript); document.head.appendChild(cdnScript); 
58} 
59</script>
59
60<!-- Start of Cookies Banner for purdys.com  -->
61<script type="text/javascript" charset="UTF-8" src="//geo.cookie-script.com/s/6b73d7e24bd549d182dfed45d6c65c4c.js?country=us"></script>
61 
61<script type="text/javascript" charset="UTF-8" src="//cdn.cookie-script.com/s/b13066c855c83cfcb1e83d6450f5d8b9.js"></script>
61
62<!-- End of Cookies Banner for purdys.com  -->
63<!-- FontAwesome -->
64<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" integrity="sha512-2SwdPD6INVrV/lHTZbO2nodKhrnDdJK9/kg2XD1r9uGqPo1cUbujc+IYdlYdEErWNu69gVcYgdxlmVmzTWnetw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
65<!-- Richmond Display Font -->
66<link rel="stylesheet" href="https://use.typekit.net/esu7mmm.css">
67<!--WKbyAfcH8dlUUeMcZ10DKLsSNGJNBU5u-->
68
69<script type="text/javascript" src="//script.crazyegg.com/pages/scripts/0125/3606.js" async="async" ></script>
69
70
71<style>
72/*Mega Menu */
73a.mega-menu-promo-img{
74margin-top:-40px;
75}
76/*Accessibility fixed */
77.sr-only{color: #fff;}
78.page-header .sr-only span{color: #000;}
79/* LOGO */
80.logo img {
81            max-height: 60px !important;
82}
83.logo {
84margin: auto !important;
85}
86@media only screen and (max-width: 1023px) {
87    #header .logo{
88        margin-left: 0px !important;
89    }
90   }
91/* ===== Blog ====== */
92#maincontent:has(.amblog-grid-list){
93max-width: 1660px;
94}
95.columns:has(.amblog-grid-list){
96max-width: 100%;
97padding: 0px;
98}
99.amblog-index-index .breadcrumbs, .amblog-index-category .breadcrumbs{
100max-width: 1660px !important;
101}
102.amblog-index-index h1.page-title {
103    font-size: 48px;
104    color: #141414;
105}
106.amblog-index-category h1.page-title {
107    font-size: 48px;
108    color: #141414;
109}
110.amblog-grid-list .amblog-title {
111    padding: 0px;
112    padding-bottom: 20px;
113}
114.amblog-grid-list .amblog-link{
115font-size: 28px;
116color: #141414;
117line-height: normal;
118text-decoration: none;
119}
120.amblog-grid-list a.amblog-link:hover{
121color: #532E91;
122}
123.amblog-grid-list a.amblog-link:active{
124color: #532E91;
125}
126.amblog-grid-list .amblog-date{
127    font-size: 16px;
128}
129.amblog-footer{
130    padding-bottom: 20px;
131}
132.amblog-footer .amblog-ref{
133color: #532E91 !important;
134}
135    /* ==========Yotpo Review ========= */
136   .yotpo-reviews-carousel-container .glide__slide::before{
137      display: none;
138   }
139   .yotpo-reviews-carousel-container .glide__slide .review-content{
140      text-align: left;
141   }
142   .yotpo-reviews-carousel-container .review-product {
143    height: auto;
144   }
145   .yotpo-reviews-carousel-container .review-product img{
146    width: 70px;
147    height: auto;
148   }
149/* -- Footer icon size error -- */
150.footer-location img {
151    width: 20px;
152}
153/* end */
154/* ---- Related Product under PDP  --- */
155
156.product-item .product-image-container {
157    margin: auto;
158}
159.block-content .products.grid .product-item {
160    margin: 0 10px;
161}
162.towishlist-wrap {
163    display: inline-block;
164}
165.block-actions {
166    padding-bottom: 30px;
167}
168@media only screen and (max-width: 849px) {
169.product-item>.product-item-info{
170padding: 0px;
171}
172}
173/* --- End --- */
174a#yotpo_testimonials_btn {
175    display: none;
176}
177.checkout-payment-method .payment-method-title > .label > img {
178    width: auto;
179}
180.amblog-list{
181padding-bottom: 40px;
182}
183.logo-section .logo-image {
184    max-width: 136px;
185    margin: auto;
186}
187.landingpage.sec-1 .image-content p a span img {
188    width: 24px;
189    display: inline;
190}
191.legend-thumb img {
192    width: initial;
193    display: inline;
194}
195.legend img {
196    width: auto;
197    display: inline-block;
198}
199.img-container img {
200    margin: auto;
201}
202
203/** Max Updated for yotpo review on Apr 7 2025 **/
204.yotpo-reviews-carousel-widget-container{
205    width: 100%;
206}
207#yotpo-reviews-star-ratings-widget {
208    margin: auto;
209    justify-content: center !important;
210}
211span.yotpo-sr-bottom-line-right-panel {
212    text-transform: capitalize;
213}
214button.yotpo-sr-bottom-line-summary.yotpo-sr-bottom-line-button {
215    max-width: 150px;
216    flex-wrap: wrap;
217    justify-content: center;
218}
219@media only screen and (max-width: 849px) {
220.yotpo-seo-page-layout{
221margin: 0px !important;
222}
223}
224 </style>
225 
225<script src="https://www.googleoptimize.com/optimize.js?id=OPT-M5XRBZB"></script>
225
226 
226<script type="text/javascript">
227	(function(c,l,a,r,i,t,y){
228	c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
229	t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
230	y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
231	})(window, document, "clarity", "script", "btt9ev0vns");
232 </script>
232
233
234<!-- TikTok Pixel Code Start --> 
234<script> !function (w, d, t) { w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for( var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(a,e){var n="https://gw.stape.ws/load/data.js";ttq._i=ttq._i||{},ttq._i[a]=[],ttq._i[a]._u=n,ttq._t=ttq._t||{},ttq._t[a]=+new Date,ttq._o=ttq._o||{},ttq._o[a]=e||{};e=document.createElement("script");e.type="text/javascript",e.async=!0,e.src=n+"?sdkid="+a+"&lib="+t,e.onerror=function(){var e=document.createElement("script");e.type="text/javascript", e.async=!0,e.src="https://analytics.tiktok.com/i18n/pixel/events.js?sdkid="+a+"&lib="+t;var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)}; ttq.load('C65B038U4DKUD0OQHOQG'); ttq.page(); }(window, document, 'ttq'); </script>
234 <!-- TikTok Pixel Code End -->
235
236<!-- Google tag (gtag.js) -->
vendor: 66 bytes, lines 236-237
236 
237<script async src="https://www.googletagmanager.com/gtag/js?id=
237AW-1068516049
vendor: 12 bytes, line 237
237"></script> 
237<script> 
vendor: 127 bytes, line 237
237window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '
237AW-1068516049
vendor: 4 bytes, line 237
237'); 
237</script>
237
238
239
240<!-- Event snippet for Purchase (Magento) conversion page -->
241<script>
242  gtag('event', 'conversion', {
243      'send_to': 'AW-1068516049/AxvUCLi6ho4DENGFwf0D',
244      'value': 1.0,
245      'currency': 'CAD',
246      'transaction_id': ''
247  });
248</script>
248
249
250
251<script id="cookieScript-cookieBlockScript">
252    (function () {
253        "use strict";
254
255        // Optimized configuration
256        const CONFIG = {
257            DELAY_MS: 1000,
258            EXPIRE_DATE: "expires=Thu, 01 Jan 1970 00:00:00 GMT",
259            CONSENT_COOKIE: "CookieConsent=",
260        };
261
262        // Pre-compiled cookie definitions for faster lookup
263        const cookieDefs = [
264            { name: "_sp_id.", hasVariations: true, category: "performance" },
265            { name: "_sp_ses.", hasVariations: true, category: "performance" },
266            { name: "_ce.s", hasVariations: false, category: "performance" },
267            { name: "_fbp", hasVariations: false, category: "targeting" },
268            { name: "ct23492", hasVariations: false, category: "targeting" },
269            { name: "_tt_enable_cookie", hasVariations: false, category: "marketing" },
270        ];
271
272        // Create lookup maps for O(1) access
273        const exactMatches = new Map();
274        const prefixMatches = new Map();
275        cookieDefs.forEach((def) => {
276            if (def.hasVariations) {
277                prefixMatches.set(def.name, def);
278            } else {
279                exactMatches.set(def.name, def);
280            }
281        });
282
283        // State management
284        const state = {
285            pendingCookies: [],
286            firstRun: true,
287            consentPreviouslySet: false,
288            previousConsentData: null,
289            isRemovingCookie: false,
290        };
291
292        // Optimized utility functions
293        const getCookieName = (str) => str.split("=")[0].trim();
294
295        const findCookieDef = (name) =>
296            exactMatches.get(name) ||
297            Array.from(prefixMatches.entries()).find(([prefix]) =>
298                name.startsWith(prefix)
299            )?.[1];
300
301        const checkOptionalOptin = (cookieScript) => {
302            return cookieScript?.responseMode === "optionaloptin" &&
303                cookieScript.consent?.stamp === '0';
304        };
305
306        const shouldBlockCookie = (name) => {
307            // First check if cookie name is in our block list
308            const isInBlockList = exactMatches.has(name) ||
309                Array.from(prefixMatches.keys()).some((prefix) =>
310                    name.startsWith(prefix)
311                );
312            
313            if (!isInBlockList) return false;
314            
315            // Only check optional opt-in for cookies that are in our block list
316            const cookieScript = window.CookieScript || {};
317            return !checkOptionalOptin(cookieScript);
318        };
319
320        const hasConsentForCategory = (category) => {
321            const cookieScript = window.CookieScript || {};
322            if (!cookieScript?.consent) return false;
323            if (checkOptionalOptin(cookieScript)) return true;
324            return cookieScript.consent[category] || false;
325        };
326
327        const removeCookie = (name) => {
328            const domain = window.location.hostname;
329            const expireDate = CONFIG.EXPIRE_DATE;
330            const baseCookie = `${name}=; ${expireDate}`;
331            
332            // Set flag to bypass proxy during cookie removal
333            state.isRemovingCookie = true;
334            
335            try {
336                // Remove with different domain/path combinations
337                document.cookie = `${baseCookie}; path=/`;
338                document.cookie = `${baseCookie}; path=/; domain=${domain}`;
339                document.cookie = `${baseCookie}; path=/; domain=.${domain}`;
340                
341                // Handle www and non-www variations
342                if (domain.startsWith('www.')) {
343                    const nonWwwDomain = domain.substring(4);
344                    document.cookie = `${baseCookie}; path=/; domain=${nonWwwDomain}`;
345                    document.cookie = `${baseCookie}; path=/; domain=.${nonWwwDomain}`;
346                } else {
347                    const wwwDomain = `www.${domain}`;
348                    document.cookie = `${baseCookie}; path=/; domain=${wwwDomain}`;
349                    document.cookie = `${baseCookie}; path=/; domain=.${wwwDomain}`;
350                }
351                
352                // Handle parent domain cookies (e.g., for newfundraising.purdys.com, also remove .purdys.com cookies)
353                const domainParts = domain.split('.');
354                if (domainParts.length > 2) {
355                    // For subdomains like newfundraising.purdys.com, also try to remove from parent domain
356                    const parentDomain = domainParts.slice(-2).join('.');
357                    const parentDomainWithDot = `.${parentDomain}`;
358                    document.cookie = `${baseCookie}; path=/; domain=${parentDomain}`;
359                    document.cookie = `${baseCookie}; path=/; domain=${parentDomainWithDot}`;
360                }
361                
362                // Additional secure and sameSite variations
363                document.cookie = `${baseCookie}; path=/; secure`;
364                document.cookie = `${baseCookie}; path=/; domain=${domain}; secure`;
365                document.cookie = `${baseCookie}; path=/; domain=.${domain}; secure`;
366                
367                // Secure variations for parent domain
368                if (domainParts.length > 2) {
369                    const parentDomain = domainParts.slice(-2).join('.');
370                    document.cookie = `${baseCookie}; path=/; domain=${parentDomain}; secure`;
371                    document.cookie = `${baseCookie}; path=/; domain=.${parentDomain}; secure`;
372                }
373            } catch (e) {
374                // Silent fail for cookie removal errors
375            } finally {
376                // Reset flag after removal attempts
377                state.isRemovingCookie = false;
378            }
379        };
380
381        // Optimized consent detection
382        const checkPreviousConsent = () => {
383            try {
384                // Check for CookieConsent cookie and parse its value
385                const cookieConsent = document.cookie
386                    .split(";")
387                    .find(cookie => cookie.trim().startsWith(CONFIG.CONSENT_COOKIE));
388                
389                if (cookieConsent) {
390                    // Extract the consent value (URL-encoded)
391                    const consentValue = cookieConsent.split("=")[1];
392                    if (consentValue && consentValue !== "") {
393                        try {
394                            // Decode the URL-encoded value
395                            const decodedValue = decodeURIComponent(consentValue);
396                            
397                            // Manually parse the consent data by extracting values
398                            const consentData = {};
399                            
400                            // Extract boolean values for CookieScript categories
401                            consentData.functionality = decodedValue.includes('functionality:true');
402                            consentData.statistics = decodedValue.includes('statistics:true');
403                            consentData.marketing = decodedValue.includes('marketing:true');
404                            consentData.necessary = decodedValue.includes('necessary:true');
405                            consentData.targeting = decodedValue.includes('targeting:true');
406                            consentData.performance = decodedValue.includes('performance:true');
407                            
408                            // Extract stamp if present
409                            const stampMatch = decodedValue.match(/stamp:'([^']*)'/);
410                            if (stampMatch) {
411                                consentData.stamp = stampMatch[1];
412                            }
413                            
414                            // Extract method if present
415                            const methodMatch = decodedValue.match(/method:'([^']*)'/);
416                            if (methodMatch) {
417                                consentData.method = methodMatch[1];
418                            }
419                            
420                            // Check if consent has been given (any category true or stamp exists)
421                            const hasConsent = consentData.functionality || 
422                                              consentData.statistics || 
423                                              consentData.marketing ||
424                                              consentData.targeting ||
425                                              consentData.performance ||
426                                              (consentData.stamp && consentData.stamp !== '0');
427                            
428                            if (hasConsent) {
429                                return consentData;
430                            }
431                        } catch (parseError) {
432                            // If we can't parse, but cookie exists, return a default consent object
433                            return { functionality: true, statistics: true, marketing: true, targeting: true, performance: true };
434                        }
435                    }
436                }
437                
438                return null;
439            } catch (e) {
440                return null;
441            }
442        };
443
444        // Optimized cookie processing
445        const processExistingCookies = () => {
446            const cookies = document.cookie
447                .split(";")
448                .map((c) => c.trim())
449                .filter(Boolean);
450            
451            cookies.forEach((cookieString) => {
452                const name = getCookieName(cookieString);
453                if (shouldBlockCookie(name)) {
454                    const def = findCookieDef(name);
455                    if (!def || !hasConsentForCategory(def.category)) {
456                        state.pendingCookies.push(cookieString);
457                        removeCookie(name);
458                    }
459                }
460            });
461        };
462
463        const processPendingCookies = () => {
464            const cookieScript = window.CookieScript;
465            if (!cookieScript?.consent || state.pendingCookies.length === 0) return;
466
467            const cookiesToSet = state.pendingCookies.filter((cookieString) => {
468                const name = getCookieName(cookieString);
469                const def = findCookieDef(name);
470                return def ? hasConsentForCategory(def.category) : false;
471            });
472
473            if (cookiesToSet.length > 0) {
474                cookiesToSet.forEach((cookie) => {
475                    try {
476                        document.cookie = cookie;
477                    } catch (e) {
478                        // Silent fail for cookie setting errors
479                    }
480                });
481
482                const toRemove = new Set(cookiesToSet);
483                state.pendingCookies = state.pendingCookies.filter(
484                    (cookie) => !toRemove.has(cookie)
485                );
486            }
487        };
488
489        // Optimized initialization
490        const initCookies = () => {
491            if (!state.firstRun) return;
492            state.firstRun = false;
493            
494            const previousConsentData = checkPreviousConsent();
495            state.consentPreviouslySet = previousConsentData !== null;
496            state.previousConsentData = previousConsentData;
497
498            if (state.consentPreviouslySet) {
499                setTimeout(processExistingCookies, CONFIG.DELAY_MS);
500            } else {
501                processExistingCookies();
502            }
503        };
504
505        // Optimized cookie proxy
506        const cookieProxy = new Proxy(Reflect.getPrototypeOf(document), {
507            set(target, key, value, thisArg) {
508                if (key === "cookie") {
509                    // Bypass proxy during cookie removal to prevent circular blocking
510                    if (state.isRemovingCookie) {
511                        return Reflect.set(...arguments);
512                    }
513                    
514                    const name = getCookieName(value);
515                    if (shouldBlockCookie(name)) {
516                        const def = findCookieDef(name);
517                        
518                        let hasConsent = false;
519                        if (state.previousConsentData && def) {
520                            hasConsent = state.previousConsentData[def.category] || false;
521                        } else if (def) {
522                            hasConsent = hasConsentForCategory(def.category);
523                        }
524                        
525                        if (hasConsent) {
526                            return Reflect.set(...arguments);
527                        } else {
528                            state.pendingCookies.push(value);
529                            return true;
530                        }
531                    }
532                }
533                return Reflect.set(...arguments);
534            },
535        });
536
537        // Optimized event handling
538        const setupEvents = () => {
539            const cookieScript = window.CookieScript;
540            
541            if (cookieScript?.consent) {
542                processPendingCookies();
543            } else {
544                window.addEventListener("CookieScriptLoaded", () => {
545                    if (window.CookieScript?.consent) {
546                        processPendingCookies();
547                    } else {
548                        window.addEventListener("CookieScriptAcceptAll", processPendingCookies);
549                        window.addEventListener("CookieScriptAccept", processPendingCookies);
550                    }
551                });
552            }
553
554            // CookieScript event listeners
555            window.addEventListener("CookieScriptAcceptAll", processPendingCookies);
556            window.addEventListener("CookieScriptAccept", processPendingCookies);
557            window.addEventListener("CookieScriptReject", processExistingCookies);
558            window.addEventListener("CookieScriptClose", processExistingCookies);
559            window.addEventListener("CookieScriptLoaded", processExistingCookies);
560
561            // Category-specific events
562            window.addEventListener("CookieScriptCategory-functionality", processPendingCookies);
563            window.addEventListener("CookieScriptCategory-strict", processPendingCookies);
564            window.addEventListener("CookieScriptCategory-targeting", processPendingCookies);
565            window.addEventListener("CookieScriptCategory-performance", processPendingCookies);
566            window.addEventListener("CookieScriptCategory-unclassified", processPendingCookies);
567
568            document.addEventListener("DOMContentLoaded", () => {
569                if (window.CookieScript?.consent) {
570                    processPendingCookies();
571                }
572            });
573        };
574
575        // Initialize
576        Reflect.setPrototypeOf(document, cookieProxy);
577        initCookies();
578        setupEvents();
579    })();
580</script>
580
581
582<!-- A/B testing script  -->
583<script>
584    !function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init ns hs wi ls ds rs os capture calculateEventProperties fs register register_once register_for_session unregister unregister_for_session bs getFeatureFlag getFeatureFlagPayload getFeatureFlagResult isFeatureEnabled reloadFeatureFlags updateFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey cancelPendingSurvey canRenderSurvey canRenderSurveyAsync identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException startExceptionAutocapture stopExceptionAutocapture loadToolbar get_property getSessionProperty gs cs createPersonProfile setInternalOrTestUser ts ys opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing vs debug M ps getPageViewId captureTraceFeedback captureTraceMetric Xr".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
585    posthog.init('phc_hJ4E8POShJYsN0nhtxizH2pnkCsN9w9i7uOW6sd2CXJ', {
586        api_host: 'https://us.i.posthog.com',
587        defaults: '2026-01-30',
588        person_profiles: 'identified_only', // or 'always' to create profiles for anonymous users as well
589    })
590</script>
590
591
592            
593<script>
594    window.addEventListener('load', function () {
595        window.magentoStorefrontEvents = magentoStorefrontEvents;
596        magentoStorefrontEvents.context.setStorefrontInstance(
597            {"storeUrl":"https:\/\/www.purdys.com\/","websiteId":1,"websiteCode":"base","storeId":1,"storeCode":"main_website_store","storeViewId":1,"storeViewCode":"default","websiteName":"Main Website","storeName":"Main Website Store","storeViewName":"Default Store View","baseCurrencyCode":"CAD","storeViewCurrencyCode":"CAD","catalogExtensionVersion":"103.4.10","environmentId":"2cc69165-2270-494c-893f-c00d0bb35bd7","environment":"Production","storefrontTemplate":"Hyva"}        );
598        magentoStorefrontEvents.context.setMagentoExtension({
599            magentoExtensionVersion: "7.7.0",
600        });
601        magentoStorefrontEvents.context.setDataServicesExtension({
602            version: "7.7.0",
603        });
604        magentoStorefrontEvents.context.setPage({
605            pageType: "Default"
606        });
607        magentoStorefrontEvents.context.setContext("pageExtended", {
608            action: "page-view"
609        });
610
611        let shopperId = "guest";
612        magentoStorefrontEvents.context.setShopper({ shopperId: shopperId });
613
614        
615        magentoStorefrontEvents.publish.pageView();
616    });
617
618    function getCustomerIdFromDataServices() {
619        let customerId = hyva.getCookie("dataservices_customer_id");
620        return customerId ? decodeURI(customerId).replace(/[^\w\s]/gi, "") : null;
621    }
622
623    function getCustomerGroupFromDataServices() {
624        try {
625            const decodedString = decodeURIComponent(hyva.getCookie("dataservices_customer_group"));
626            return decodedString ? JSON.parse(decodedString) : null;
627        } catch (error) {
628            console.error("Failed to parse customer group data:", error);
629            return null;
630        }
631    }
632</script>
632
633
634<script nonce="">
635    (function () {
636        // Don’t load twice
637        if (window.__MLS_SDK_LOADING__ || window.MagentoLiveSearch) return;
638        window.__MLS_SDK_LOADING__ = true;
639
640        // Temporarily disable AMD define to prevent “mismatched anonymous define()”
641        var savedDefine = window.define;
642        var savedDefineAmd = savedDefine && savedDefine.amd;
643        try { if (savedDefine) { savedDefine.amd = undefined; } } catch (e) {}
644
645        // Dynamically inject the SDK script
646        var script = document.createElement('script');
647        script.type = 'text/javascript';
648        script.async = true;
649        script.src = 'https\u003A\u002F\u002Fwww.purdys.com\u002Fstatic\u002Fversion1790083580\u002Ffrontend\u002FPurdys2\u002Fhyva\u002Fen_US\u002FHyva_MagentoLiveSearch\u002Fjs\u002Fsdk.js';
650
651        script.addEventListener('load', function () {
652            // restore AMD ASAP
653            if (savedDefine) {
654                window.define = savedDefine; window.define.amd = savedDefineAmd;
655            }
656        });
657
658        document.head.appendChild(script);
659    })();
660</script>
660
661
662<script  nonce="aHhkaGVuNDFoY2Y2eHhyZTY4bzN2c3BycmM3d3FoNnI=">
663    window.getWpGA4Cookie = function(name) {
664        match = document.cookie.match(new RegExp(name + '=([^;]+)'));
665        if (match) return decodeURIComponent(match[1].replace(/\+/g, ' ')) ;
666    };
667
668    window.ga4AllowServices = false;
669
670    var isCookieRestrictionModeEnabled = 0,
671        currentWebsiteId = 1,
672        cookieRestrictionName = 'user_allowed_save_cookie';
673
674    if (isCookieRestrictionModeEnabled) {
675        allowedCookies = window.getWpGA4Cookie(cookieRestrictionName);
676
677        if (allowedCookies !== undefined) {
678            allowedWebsites = JSON.parse(allowedCookies);
679
680            if (allowedWebsites[currentWebsiteId] === 1) {
681                window.ga4AllowServices = true;
682            }
683        }
684    } else {
685        window.ga4AllowServices = true;
686    }
687</script>
687
688        <!-- Google Tag Manager -->
689<script nonce="aHhkaGVuNDFoY2Y2eHhyZTY4bzN2c3BycmM3d3FoNnI="   > if (window.ga4AllowServices) {
vendor: 331 bytes, lines 689-693
689(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
690new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
691j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
692'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
693})(window,document,'script','dataLayer','
693GTM-W9VB8VD
vendor: 3 bytes, line 693
693');
693} </script>
693
694<!-- End Google Tag Manager -->
695        
695<script  nonce="aHhkaGVuNDFoY2Y2eHhyZTY4bzN2c3BycmM3d3FoNnI=">
696        if (window.ga4AllowServices) {
697            window.dataLayer = window.dataLayer || [];
698                        var dl4Objects = [{"event":"general","page_type":"other","store_view":"Default Store View","language":"English","locale":"en_US","user_login_state":"Logged out","user_id":null,"customer_email":"","customer_email_hash":"","function_source":"CustomWeltPixelEvents\/Plugin\/WeltPixel\/GA4\/Block\/Core::afterGetDataLayerAsJson"},{"pageName":"Customer Login","pageType":"other","google_tag_params":{"ecomm_pagetype":"other"}}];
699            for (var i in dl4Objects) {
700                window.dataLayer.push({ecommerce: null});
701                window.dataLayer.push(dl4Objects[i]);
702            }
703                        var wpGA4Cookies = ['wp_ga4_user_id','wp_ga4_customerGroup'];
704            wpGA4Cookies.map(function (cookieName) {
705                var cookieValue = window.getWpGA4Cookie(cookieName);
706                if (cookieValue) {
707                    var dl4Object = {};
708                    dl4Object[cookieName.replace('wp_ga4_', '')] = cookieValue;
709                    window.dataLayer.push(dl4Object);
710                }
711            });
712        }
713    </script>
713
714<!-- NO Pixel ID is configured, please goto Admin -->
715<script type="text&#x2F;javascript">    console.log('No Meta pixel is configured, please log in as a admin and then visit Stores -> Meta -> Setup -> Get Started');</script>
715<script  type="text/javascript"  data-routing="commerce=rum" defer="defer" src="https://rum.hlx.page/.rum/@adobe/helix-rum-js@^2/dist/rum-standalone.js"></script>
715
716
717
718
719
720
721<script>
722    var BASE_URL = 'https://www.purdys.com/';
723    var THEME_PATH = 'https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US';
724    var COOKIE_CONFIG = {
725        "expires": null,
726        "path": "\u002F",
727        "domain": ".purdys.com",
728        "secure": true,
729        "lifetime": "604800",
730        "cookie_restriction_enabled": false    };
731    var CURRENT_STORE_CODE = 'default';
732    var CURRENT_WEBSITE_ID = '1';
733
734    window.hyva = window.hyva || {}
735
736    window.cookie_consent_groups = window.cookie_consent_groups || {}
737    window.cookie_consent_groups['necessary'] = true;
738
739    window.cookie_consent_config = window.cookie_consent_config || {};
740    window.cookie_consent_config['necessary'] = [].concat(
741        window.cookie_consent_config['necessary'] || [],
742        [
743            'user_allowed_save_cookie',
744            'form_key',
745            'mage-messages',
746            'private_content_version',
747            'mage-cache-sessid',
748            'last_visited_store',
749            'section_data_ids'
750        ]
751    );
752</script>
vendor: 1 bytes, line 752
752
753<script>
754    'use strict';
755    (function( hyva, undefined ) {
756
757        function lifetimeToExpires(options, defaults) {
758
759            const lifetime = options.lifetime || defaults.lifetime;
760
761            if (lifetime) {
762                const date = new Date;
763                date.setTime(date.getTime() + lifetime * 1000);
764                return date;
765            }
766
767            return null;
768        }
769
770        function generateRandomString() {
771
772            const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
773                length = 16;
774
775            let formKey = '',
776                charactersLength = allowedCharacters.length;
777
778            for (let i = 0; i < length; i++) {
779                formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))]
780            }
781
782            return formKey;
783        }
784
785        const sessionCookieMarker = {noLifetime: true}
786
787        const cookieTempStorage = {};
788
789        const internalCookie = {
790            get(name) {
791                const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
792                return v ? v[2] : null;
793            },
794            set(name, value, days, skipSetDomain) {
795                let expires,
796                    path,
797                    domain,
798                    secure,
799                    samesite;
800
801                const defaultCookieConfig = {
802                    expires: null,
803                    path: '/',
804                    domain: null,
805                    secure: false,
806                    lifetime: null,
807                    samesite: 'lax'
808                };
809
810                const cookieConfig = window.COOKIE_CONFIG || {};
811
812                expires = days && days !== sessionCookieMarker
813                    ? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig)
814                    : lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires;
815
816                path = cookieConfig.path || defaultCookieConfig.path;
817                domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain);
818                secure = cookieConfig.secure || defaultCookieConfig.secure;
819                samesite = cookieConfig.samesite || defaultCookieConfig.samesite;
820
821                document.cookie = name + "=" + encodeURIComponent(value) +
822                    (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') +
823                    (path ? '; path=' + path : '') +
824                    (domain ? '; domain=' + domain : '') +
825                    (secure ? '; secure' : '') +
826                    (samesite ? '; samesite=' + samesite : 'lax');
827            },
828            isWebsiteAllowedToSaveCookie() {
829                const allowedCookies = this.get('user_allowed_save_cookie');
830                if (allowedCookies) {
831                    const allowedWebsites = JSON.parse(unescape(allowedCookies));
832
833                    return allowedWebsites[CURRENT_WEBSITE_ID] === 1;
834                }
835                return false;
836            },
837            getGroupByCookieName(name) {
838                const cookieConsentConfig = window.cookie_consent_config || {};
839                let group = null;
840                for (let prop in cookieConsentConfig) {
841                    if (!cookieConsentConfig.hasOwnProperty(prop)) continue;
842                    if (cookieConsentConfig[prop].includes(name)) {
843                        group = prop;
844                        break;
845                    }
846                }
847                return group;
848            },
849            isCookieAllowed(name) {
850                const cookieGroup = this.getGroupByCookieName(name);
851                return cookieGroup
852                    ? window.cookie_consent_groups[cookieGroup]
853                    : this.isWebsiteAllowedToSaveCookie();
854            },
855            saveTempStorageCookies() {
856                for (const [name, data] of Object.entries(cookieTempStorage)) {
857                    if (this.isCookieAllowed(name)) {
858                        this.set(name, data['value'], data['days'], data['skipSetDomain']);
859                        delete cookieTempStorage[name];
860                    }
861                }
862            }
863        };
864
865        hyva.getCookie = (name) => {
866            const cookieConfig = window.COOKIE_CONFIG || {};
867
868            if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
869                return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null;
870            }
871
872            return internalCookie.get(name);
873        }
874
875        hyva.setCookie = (name, value, days, skipSetDomain) => {
876            const cookieConfig = window.COOKIE_CONFIG || {};
877
878            if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
879                cookieTempStorage[name] = {value, days, skipSetDomain};
880                return;
881            }
882            return internalCookie.set(name, value, days, skipSetDomain);
883        }
884
885
886        hyva.setSessionCookie = (name, value, skipSetDomain) => {
887            return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain)
888        }
889
890        hyva.getBrowserStorage = () => {
891            const browserStorage = window.localStorage || window.sessionStorage;
892            if (!browserStorage) {
893                console.warn('Browser Storage is unavailable');
894                return false;
895            }
896            try {
897                browserStorage.setItem('storage_test', '1');
898                browserStorage.removeItem('storage_test');
899            } catch (error) {
900                console.warn('Browser Storage is not accessible', error);
901                return false;
902            }
903            return browserStorage;
904        }
905
906        hyva.postForm = (postParams) => {
907            const form = document.createElement("form");
908
909            let data = postParams.data;
910
911            if (! postParams.skipUenc && ! data.uenc) {
912                data.uenc = btoa(window.location.href);
913            }
914            form.method = "POST";
915            form.action = postParams.action;
916
917            Object.keys(postParams.data).map(key => {
918                const field = document.createElement("input");
919                field.type = 'hidden'
920                field.value = postParams.data[key];
921                field.name = key;
922                form.appendChild(field);
923            });
924
925            const form_key = document.createElement("input");
926            form_key.type = 'hidden';
927            form_key.value = hyva.getFormKey();
928            form_key.name="form_key";
929            form.appendChild(form_key);
930
931            document.body.appendChild(form);
932
933            form.submit();
934        }
935
936        hyva.getFormKey = function () {
937            let formKey = hyva.getCookie('form_key');
938
939            if (!formKey) {
940                formKey = generateRandomString();
941                hyva.setCookie('form_key', formKey);
942            }
943
944            return formKey;
945        }
946
947        hyva.formatPrice = (value, showSign, options = {}) => {
948            const groupSeparator = options.groupSeparator;
949            const decimalSeparator = options.decimalSeparator
950            delete options.groupSeparator;
951            delete options.decimalSeparator;
952            const formatter = new Intl.NumberFormat(
953                'en\u002DUS',
954                Object.assign({
955                    style: 'currency',
956                    currency: 'CAD',
957                    signDisplay: showSign ? 'always' : 'auto'
958                }, options)
959            );
960            return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ?
961                formatter.formatToParts(value).map(({type, value}) => {
962                    switch (type) {
963                        case 'currency':
964                            return '\u0024' || value;
965                        case 'minusSign':
966                            return '- ';
967                        case 'plusSign':
968                            return '+ ';
969                        case 'group':
970                            return groupSeparator !== undefined ? groupSeparator : value;
971                        case 'decimal':
972                            return decimalSeparator !== undefined ? decimalSeparator : value;
973                        default :
974                            return value;
975                    }
976                }).reduce((string, part) => string + part) :
977                formatter.format(value);
978        }
979
980        const formatStr = function (str, nStart) {
981            const args = Array.from(arguments).slice(2);
982
983            return str.replace(/(%+)([0-9]+)/g, (m, p, n) => {
984                const idx = parseInt(n) - nStart;
985
986                if (args[idx] === null || args[idx] === void 0) {
987                    return m;
988                }
989                return p.length % 2
990                    ? p.slice(0, -1).replace('%%', '%') + args[idx]
991                    : p.replace('%%', '%') + n;
992            })
993        }
994
995        hyva.str = function (string) {
996            const args = Array.from(arguments);
997            args.splice(1, 0, 1);
998
999            return formatStr.apply(undefined, args);
1000        }
1001
1002        hyva.strf = function () {
1003            const args = Array.from(arguments);
1004            args.splice(1, 0, 0);
1005
1006            return formatStr.apply(undefined, args);
1007        }
1008
1009        /**
1010         * Take a html string as `content` parameter and
1011         * extract an element from the DOM to replace in
1012         * the current page under the same selector,
1013         * defined by `targetSelector`
1014         */
1015        hyva.replaceDomElement = (targetSelector, content) => {
1016            // Parse the content and extract the DOM node using the `targetSelector`
1017            const parser = new DOMParser();
1018            const doc = parser.parseFromString(content, 'text/html');
1019            const contentNode = doc.querySelector(targetSelector);
1020
1021            // Bail if content or target can't be found
1022            if (!contentNode || !document.querySelector(targetSelector)) {
1023                return;
1024            }
1025
1026                        hyva.activateScripts(contentNode);
1027            
1028            // Replace the old DOM node with the new content
1029            document.querySelector(targetSelector).replaceWith(contentNode);
1030
1031            // Reload customerSectionData and display cookie-messages if present
1032            window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
1033            hyva.initMessages();
1034        }
1035
1036        hyva.removeScripts = (contentNode) => {
1037            const scripts = contentNode.getElementsByTagName('script');
1038            for (let i = 0; i < scripts.length; i++) {
1039                scripts[i].parentNode.removeChild(scripts[i]);
1040            }
1041            const templates = contentNode.getElementsByTagName('template');
1042            for (let i = 0; i < templates.length; i++) {
1043                const container = document.createElement('div');
1044                container.innerHTML = templates[i].innerHTML;
1045                hyva.removeScripts(container);
1046                templates[i].innerHTML = container.innerHTML;
1047            }
1048        }
1049
1050        hyva.activateScripts = (contentNode) => {
1051            // Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM.
1052            const scripts = Array.from(contentNode.getElementsByTagName('script'));
1053
1054            // Iterate over all script tags to duplicate+inject each into the head
1055            for (const original of scripts) {
1056                const script = document.createElement('script');
1057                original.type && (script.type = original.type);
1058                script.innerHTML = original.innerHTML;
1059
1060                // Remove the original (non-executing) script from the contentNode
1061                original.parentNode.removeChild(original)
1062
1063                // Add script to head
1064                document.head.appendChild(script);
1065            }
1066
1067            return contentNode;
1068        }
1069
1070        const replace = {['+']: '-', ['/']: '_', ['=']: ','};
1071        hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]);
1072
1073        let currentTrap;
1074
1075        const focusableElements = (rootElement) => {
1076            const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]';
1077            return Array.from(rootElement.querySelectorAll(selector))
1078                .filter(el => {
1079                    return el.style.display !== 'none'
1080                        && !el.disabled
1081                        && el.tabIndex !== -1
1082                        && (el.offsetWidth || el.offsetHeight || el.getClientRects().length)
1083                })
1084        }
1085
1086        const focusTrap = (e) => {
1087            const isTabPressed = e.key === 'Tab' || e.keyCode === 9;
1088            if (!isTabPressed) return;
1089
1090            const focusable = focusableElements(currentTrap)
1091            const firstFocusableElement = focusable[0]
1092            const lastFocusableElement = focusable[focusable.length - 1]
1093
1094            e.shiftKey
1095                ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault())
1096                : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault())
1097        };
1098
1099        hyva.releaseFocus = (rootElement) => {
1100            if (currentTrap && (!rootElement || rootElement === currentTrap)) {
1101                currentTrap.removeEventListener('keydown', focusTrap)
1102                currentTrap = null
1103            }
1104        }
1105        hyva.trapFocus = (rootElement) => {
1106            if (!rootElement) return;
1107            hyva.releaseFocus()
1108            currentTrap = rootElement
1109            rootElement.addEventListener('keydown', focusTrap)
1110            const firstElement = focusableElements(rootElement)[0]
1111            firstElement && firstElement.focus()
1112        }
1113
1114        hyva.safeParseNumber = (rawValue) => {
1115            const number = rawValue ? parseFloat(rawValue) : null;
1116
1117            return Array.isArray(number) || isNaN(number) ? rawValue : number;
1118        }
1119
1120        const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
1121        hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => {
1122
1123            const camelCase = toCamelCase(name);
1124            const key = '__hyva_bool_' + name
1125
1126            return new Proxy(Object.assign(
1127                additionalMethods,
1128                {
1129                    [key]: !!value,
1130                    [name]() {return !!this[key]},
1131                    ['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine
1132                    ['not' + camelCase]() {return !this[key]},
1133                    ['toggle' + camelCase]() {this[key] = !this[key]},
1134                    [`set${camelCase}True`]() {this[key] = true},
1135                    [`set${camelCase}False`]() {this[key] = false},
1136                }
1137            ), {
1138                set(target, prop, value) {
1139                    return prop === name
1140                        ? (target[key] = !!value)
1141                        : Reflect.set(...arguments);
1142                }
1143            })
1144        }
1145
1146                hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true})
1147        window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true});
1148                window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies())
1149
1150    }( window.hyva = window.hyva || {} ));
1151</script>
vendor: 1 bytes, line 1151
1151
1152<script>
1153    if (!window.IntersectionObserver) {
1154        window.IntersectionObserver = function (callback) {
1155            this.observe = el => el && callback(this.takeRecords());
1156            this.takeRecords = () => [{isIntersecting: true, intersectionRatio: 1}];
1157            this.disconnect = () => {};
1158            this.unobserve = () => {};
1159        }
1160    }
1161</script>
vendor: 1 bytes, line 1161
1161
1162<script>
1163    'use strict';
1164
1165    (function () {
1166        window.initAmAppendLabels = {
1167            selectors: {
1168                labelWrapper: '.amlabel-position-wrapper'
1169            },
1170            /**
1171             * We use approach from hyva.replaceDomElement method to replace labels and init components
1172             *
1173             * @param {HTMLElement} labelContainer
1174             * @param {string} labelHtml
1175             * @return {void}
1176             */
1177            appendLabels: function (labelContainer, labelHtml) {
1178                const parser = new DOMParser();
1179                const doc = parser.parseFromString(labelHtml, 'text/html');
1180                const nodes = doc.querySelectorAll(this.selectors.labelWrapper);
1181
1182                if (!nodes) {
1183                    return;
1184                }
1185
1186                // Extract all the script tags from the new content.
1187                // Script tags won't execute when inserted into a dom-element directly,
1188                // therefore we need to inject them to the head of the document.
1189                const tmpScripts = doc.getElementsByTagName('script');
1190
1191                if (tmpScripts.length > 0) {
1192                    // Push all script tags into an array
1193                    // (to prevent dom manipulation while iterating over dom nodes)
1194                    const scripts = [...tmpScripts];
1195
1196                    // Iterate over all script tags and duplicate+inject each into the head
1197                    scripts.forEach(script => {
1198                        let scriptNode = document.createElement('script');
1199                        scriptNode.innerHTML = script.innerHTML;
1200                        document.head.appendChild(scriptNode);
1201
1202                        // Remove the original (non-executing) node from the page
1203                        script.parentNode.removeChild(script);
1204                    });
1205                }
1206
1207                labelContainer.append(...nodes);
1208            }
1209        };
1210    })();
1211</script>
1211
1212
1213<script>
1214    window.addEventListener('DOMContentLoaded', () => {
1215        if (window._amSwiperLoaded) {
1216            return;
1217        }
1218
1219        // Load Swiper script asynchronously
1220        const script = document.createElement('script');
1221        script.src = 'https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Amasty_ShopByBrandHyvaCompatibility/js/swiper.min.js';
1222        script.async = true;
1223        document.body.appendChild(script);
1224
1225        window._amSwiperLoaded = true;
1226
1227        script.onload = () => {
1228            // Dispatch custom event when Swiper is loaded
1229            window.dispatchEvent(new CustomEvent('amSwiperLoaded', {}));
1230        }
1231
1232        // Load Swiper CSS file
1233        const styles = document.createElement('link');
1234        styles.rel = 'stylesheet';
1235        styles.href = 'https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Amasty_ShopByBrandHyvaCompatibility/css/swiper.min.css';
1236
1237        document.head.appendChild(styles);
1238    });
1239</script>
vendor: 1 bytes, line 1239
1239
1240<script>
1241function initDeviceTypeVariable() {
1242    const mobileMatchMedia = window.matchMedia("(max-width: 767px)");
1243    const tabletMatchMedia = window.matchMedia("(min-width: 768px) and (max-width: 1023px)");
1244    const desktopMatchMedia = window.matchMedia("(min-width: 1024px)");
1245
1246    function updateDeviceStore() {
1247        const isMobile = mobileMatchMedia.matches;
1248        const isTablet = tabletMatchMedia.matches;
1249        const isDesktop = desktopMatchMedia.matches;
1250
1251        window.isMobile = isMobile;
1252        window.isTablet = isTablet;
1253        window.isDesktop = isDesktop;
1254
1255        Alpine.store('device').isMobile = isMobile;
1256        Alpine.store('device').isTablet = isTablet;
1257        Alpine.store('device').isDesktop = isDesktop;
1258    }
1259
1260    // Initial check
1261    updateDeviceStore();
1262
1263    // Attach change listeners
1264    const matchMediaList = [mobileMatchMedia, tabletMatchMedia, desktopMatchMedia];
1265    matchMediaList.forEach((mediaQuery) => {
1266        if (typeof mediaQuery.onchange !== 'object') {
1267            mediaQuery.addListener(updateDeviceStore); // Legacy
1268        } else {
1269            mediaQuery.addEventListener("change", updateDeviceStore);
1270        }
1271    });
1272}
1273
1274document.addEventListener("alpine:init", () => {
1275    Alpine.store('device', {
1276        isMobile: window.isMobile,
1277        isTablet: window.isTablet,
1278        isDesktop: window.isDesktop
1279    });
1280
1281    initDeviceTypeVariable();
1282});
1283</script>
1283</head>
1284<body id="html-body" class="customer-account-login page-layout-1column">
1285<!-- Google Tag Manager (noscript) -->
vendor: 69 bytes, lines 1285-1286
1285
1286<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
1286GTM-W9VB8VD
vendor: 85 bytes, lines 1286-1287
1286"
1287height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
1288<!-- End Google Tag Manager (noscript) -->
1289    
1289<script>
1290        (function () {
1291            'use strict';
1292
1293            window.amRecaptchaModel = {
1294                formsToProtect: "form\u005Baction\u002A\u003D\u0022multishipping\u002Fcheckout\u002Foverview\u0022\u005D,form\u005Baction\u002A\u003D\u0022multishipping\u002Fcheckout\u002FoverviewPost\u0022\u005D,\u005Baction\u002A\u003D\u0022recpatcha\u002Dholder\u0022\u005D,form\u005Baction\u002A\u003D\u0022customer\u002Faccount\u002Fcreatepost\u0022\u005D,form\u005Baction\u002A\u003D\u0022customer\u002Faccount\u002FloginPost\u0022\u005D,form\u005Baction\u002A\u003D\u0022newsletter\u002Fsubscriber\u002Fnew\u0022\u005D,form\u005Baction\u002A\u003D\u0022contact\u002Findex\u002Fpost\u0022\u005D,form\u005Baction\u002A\u003D\u0022customer\u002Faccount\u002Fforgotpasswordpost\u0022\u005D,form\u005Bx\u002Ddata\u003D\u0022initReviewForm\u0028\u0029\u0022\u005D,form\u005Bx\u002Ddata\u003D\u0022initReviewForm\u0022\u005D,form\u005Baction\u002A\u003D\u0022checkout_payment_captcha\u0022\u005D",
1295                isEnabledOnPayments: "1",
1296                checkoutRecaptchaValidateUrl: "https://www.purdys.com/amcapthca/checkout/validate/",
1297                invisibleCaptchaCustomForm: "0",
1298                recaptchaConfig: {
1299                    lang: "hl\u003Den" || 'hl=en',
1300                    theme: "light",
1301                    badge: "bottomright",
1302                    sitekey: "6LfD4jsqAAAAAL0vSLeq92I6r50A87vMaCVUy2qB",
1303                    size: "invisible"
1304                },
1305                url: 'https://www.google.com/recaptcha/api.js',
1306                isCaptchaScriptLoaded: false,
1307                isInvisible: "invisible" === 'invisible',
1308
1309                /**
1310                 * Submit event
1311                 *
1312                 * @param {Object} $event
1313                 * @return {void}
1314                 */
1315                execute: function ($event) {
1316                    const eventTarget = $event?.target;
1317                    if (this.isCaptchaScriptLoaded) {
1318                        this.executeCaptcha(eventTarget);
1319                    } else {
1320                        window.addEventListener('amcaptcha-script-loaded', () => {
1321                            this.isCaptchaScriptLoaded = true;
1322                            this.executeCaptcha(eventTarget);
1323                            this.initAmcaptchaBadges();
1324                        });
1325
1326                        this.loadRecaptchaScript();
1327                    }
1328                },
1329
1330                /**
1331                 * Execute original submit
1332                 *
1333                 * @param {Object} $event
1334                 * @param {HTMLElement} $el
1335                 * @return {void}
1336                 */
1337                recaptchaCallback: function ($event, $el) {
1338                    this.shouldExecuteCallback($event, $el) && $el.dispatchEvent(new CustomEvent('amrecaptcha-executable-callback'));
1339                },
1340
1341                /**
1342                 * Reset captcha
1343                 *
1344                 * @param {Object} $event
1345                 * @param {HTMLElement} $el
1346                 */
1347                expiredCallback: function($event, $el) {
1348                    this.shouldExecuteCallback($event, $el) && grecaptcha.reset($event.detail.widgetId);
1349                },
1350
1351                /**
1352                 * Checks if event is fired on submitted element
1353                 *
1354                 * @param {Object} $event
1355                 * @param {HTMLElement} $el
1356                 * @return {boolean}
1357                 */
1358                shouldExecuteCallback: function($event, $el) {
1359                    const eventWidgetId = $event.detail.widgetId;
1360                    const elementWidgetId = $el.dataset.amCaptchaWidgetId || $el.closest('form')?.dataset.amCaptchaWidgetId;
1361
1362                    return eventWidgetId === elementWidgetId;
1363                },
1364
1365                /**
1366                 * Run captcha for widget by id
1367                 *
1368                 * @param {HTMLElement} eventTarget
1369                 * @return {void}
1370                 */
1371                executeCaptcha: function(eventTarget) {
1372                    if (!eventTarget.dataset.hasOwnProperty('amCaptchaRendered')) {
1373                        this.bindCaptchaGlobalCallbacks(eventTarget);
1374                        this.renderCaptcha(eventTarget);
1375                        eventTarget.dataset.amCaptchaRendered = '';
1376                    }
1377
1378                    const widgetId = this.getWidgetId(eventTarget);
1379
1380                    if (!widgetId) {
1381                        typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
1382                            {
1383                                type: "error",
1384                                text: 'Recaptcha\u0020cannot\u0020properly\u0020validate\u0020form.'
1385                            }
1386                        ]);
1387                        return;
1388                    }
1389
1390                    window.dispatchEvent(new CustomEvent('amcaptcha-loading-start'));
1391                    grecaptcha.reset(widgetId);
1392
1393                    if (!this.isInvisible) {
1394                        this.stopAmcaptchaLoading();
1395                        return;
1396                    }
1397
1398                    grecaptcha.execute(widgetId)
1399                        .then(() => this.stopAmcaptchaLoading())
1400                        .catch(() => this.stopAmcaptchaLoading());
1401                },
1402
1403                /**
1404                 * Add recaptcha script to page
1405                 *
1406                 * @return {void}
1407                 */
1408                loadRecaptchaScript: function () {
1409                    const lang = window.amRecaptchaModel.recaptchaConfig.lang;
1410                    const url = `${window.amRecaptchaModel.url}?onload=amRecaptchaLoadCallback&render=explicit&${lang}`;
1411                    const script = document.createElement('script');
1412
1413                    script.type = 'text/javascript';
1414                    script.src = url;
1415                    script.async = true;
1416                    document.head.appendChild(script);
1417                },
1418
1419                /**
1420                 * Stop loader on page
1421                 *
1422                 * @return {void}
1423                 */
1424                stopAmcaptchaLoading: function () {
1425                    window.dispatchEvent(new CustomEvent('amcaptcha-loading-stop'));
1426                },
1427
1428                /**
1429                 * Add attributes to hide captcha badge
1430                 *
1431                 * @return {void}
1432                 */
1433                initAmcaptchaBadges: function () {
1434                    if (!this.isInvisible) {
1435                        return;
1436                    }
1437
1438                    document.querySelectorAll('.grecaptcha-badge')?.forEach(captchaBadge => {
1439                        captchaBadge?.setAttribute('x-data', 'amGrecaptchaBadge');
1440                        captchaBadge?.setAttribute('x-on:amcaptcha-loading-start.window', 'loadingStart');
1441                        captchaBadge?.setAttribute('x-on:amcaptcha-loading-stop.window', 'loadingStop');
1442                        captchaBadge?.setAttribute(':class', 'getVisibility');
1443                    });
1444                },
1445
1446                /**
1447                 * Get form widgetId
1448                 *
1449                 * @param {HTMLElement} eventTarget
1450                 * @return {string}
1451                 */
1452                getWidgetId: function (eventTarget) {
1453                    return eventTarget.dataset.amCaptchaWidgetId
1454                        || eventTarget.closest('form')?.dataset.amCaptchaWidgetId;
1455                },
1456
1457                /**
1458                 * Add captcha badge or checkbox to protected form.
1459                 * Store widgetId in dataset to pass this info in callbacks
1460                 *
1461                 * @param {HTMLElement} eventTarget
1462                 * @return {void}
1463                 */
1464                renderCaptcha: function (eventTarget) {
1465                    const captchaElement = document.createElement('div');
1466                    const formContent = eventTarget.closest('form')?.querySelector('[data-element="form-content"]')
1467                        ?? eventTarget.closest('form');
1468                    formContent?.appendChild(captchaElement);
1469
1470                    eventTarget.dataset.amCaptchaWidgetId = grecaptcha.render(captchaElement, {
1471                        ...window.amRecaptchaModel?.recaptchaConfig,
1472                        callback: () => {
1473                            window.dispatchEvent(new CustomEvent(
1474                                'amrecaptcha-callback', {
1475                                    detail: this.getCaptchaCallbackDetail(eventTarget)
1476                                }));
1477                        },
1478                        'expired-callback': () => {
1479                            window.dispatchEvent(new CustomEvent(
1480                                'amrecaptcha-expired-callback', {
1481                                    detail: this.getCaptchaCallbackDetail(eventTarget)
1482                                }));
1483                        }
1484                    });
1485                },
1486
1487                /**
1488                 * Get detail property for callback event
1489                 *
1490                 * @param {HTMLElement} eventTarget
1491                 * @return {object}
1492                 */
1493                getCaptchaCallbackDetail: function (eventTarget) {
1494                    return {
1495                        widgetId: eventTarget.dataset.amCaptchaWidgetId,
1496                        form: eventTarget
1497                    }
1498                },
1499
1500                /**
1501                 * Add functions that will be called on the global state
1502                 *
1503                 * @param {HTMLElement} eventTarget
1504                 * @return {void}
1505                 */
1506                bindCaptchaGlobalCallbacks: function (eventTarget) {
1507                    eventTarget.setAttribute(
1508                        'x-on:amrecaptcha-callback.window',
1509                        `amRecaptchaModelRecaptchaCallback`
1510                    );
1511                    eventTarget.setAttribute(
1512                        'x-on:amrecaptcha-expired-callback.window',
1513                        'amRecaptchaModelExpiredCallback'
1514                    );
1515                }
1516            };
1517        })(window.amRecaptchaModel = window.amRecaptchaModel || {});
1518
1519        window.amRecaptchaLoadCallback = function () {
1520            window.dispatchEvent(new CustomEvent('amcaptcha-script-loaded'));
1521        }
1522
1523        function amGrecaptchaBadge() {
1524            return {
1525                visible: true,
1526
1527                loadingStart () {
1528                    this.visible = true;
1529                },
1530
1531                loadingStop () {
1532                    this.visible = false;
1533                },
1534
1535                getVisibility() {
1536                    return { 'invisible': !this.visible };
1537                }
1538            };
1539        }
1540
1541        window.addEventListener(
1542            'alpine:init', () => Alpine.data('amGrecaptchaBadge', amGrecaptchaBadge), {once: true}
1543        )
1544    </script>
1544
1545    
1546<div
1547            class="ambanners ambanner-10"
1548        data-position="10"
1549        data-bannerid=""
1550        data-role="amasty-banner-container"
1551></div>
1552
1553<script>
1554    const HOME_3_IMAGE_CTA_BLOCK_BREAKPOINT = {
1555        1: {
1556            enabled: true,
1557            slidesPerView: 1.3,
1558            spaceBetween: 16,
1559        },
1560        576: {
1561            enabled: true,
1562            slidesPerView: 2.2,
1563            spaceBetween: 16,
1564        },
1565        768: {
1566            enabled: true,
1567            slidesPerView: 2,
1568            spaceBetween: 20,
1569        },
1570        1024: {
1571            enabled: false,
1572            slidesPerView: 3,
1573            spaceBetween: 20,
1574        },
1575    };
1576    const EXPLORE_CATEGORIES_SLIDER_BREAKPOINT = {
1577        1: {
1578            slidesPerView: 2.6,
1579            allowTouchMove: true,
1580            spaceBetween: 16,
1581        },
1582        768: {
1583            allowTouchMove: true,
1584            slidesPerView: 4,
1585            spaceBetween: 20,
1586        },
1587        1024: {
1588            allowTouchMove: false,
1589            slidesPerView: 6,
1590            spaceBetween: 20,
1591        },
1592    };
1593    const FEATURE_SLIDER_BLOCK_BREAKPOINT = {
1594        1024: {
1595            slidesPerView: 5,
1596            spaceBetween: 20,
1597        },
1598        1650: {
1599            slidesPerView: 6.7,
1600            spaceBetween: 20,
1601        }
1602    };
1603    const INSTAGRAM_BLOCK = {
1604        1: {
1605            slidesPerView: 'auto',
1606            spaceBetween: 16,
1607            loop: false,
1608        },
1609        768: {
1610            slidesPerView: 4.6,
1611            spaceBetween: 20,
1612            centeredSlides: false,
1613            slidesOffsetBefore: 100,
1614            loop: false,
1615            grabCursor: true,
1616            initialSlide: 2,
1617        },
1618        1650: {
1619            slidesPerView: 'auto',
1620            spaceBetween: 20,
1621            slidesOffsetBefore: 20,
1622            loop: false,
1623            grabCursor: true,
1624            initialSlide: 1,
1625        },
1626        2000: {
1627            slidesPerView: 'auto',
1628            spaceBetween: 20,
1629            slidesOffsetBefore: 0,
1630            loop: false,
1631            grabCursor: true,
1632        },
1633    };
1634    window.swiperInitializing = false;
1635    window.swiperPromise = null;
1636
1637    function initSwiperSlider(swiperElement, options = {}) {
1638        const addSwiperJs = (callback) => {
1639            const script = document.createElement('script');
1640            script.type = 'text/javascript';
1641            script.addEventListener('load', callback);
1642            script.src = 'https\u003A\u002F\u002Fwww.purdys.com\u002Fstatic\u002Fversion1790083580\u002Ffrontend\u002FPurdys2\u002Fhyva\u002Fen_US\u002FScandiweb_ContentTypes\u002Fjs\u002Fswiper.min.js';
1643            document.head.appendChild(script);
1644        }
1645
1646        const addSwiperCss = () => {
1647            const link = document.createElement('link');
1648            link.type = 'text/css';
1649            link.rel = 'stylesheet';
1650            link.href = 'https\u003A\u002F\u002Fwww.purdys.com\u002Fstatic\u002Fversion1790083580\u002Ffrontend\u002FPurdys2\u002Fhyva\u002Fen_US\u002FScandiweb_ContentTypes\u002Fcss\u002Fswiper.min.css';
1651            document.head.appendChild(link);
1652        }
1653
1654        const initSlider = () => {
1655            let customOptions = {...options};
1656            if (swiperElement.closest('.home-3image-cta-block')) {
1657                customOptions.breakpoints = HOME_3_IMAGE_CTA_BLOCK_BREAKPOINT;
1658            }
1659            if (swiperElement.closest('.instagram-block')) {
1660                customOptions.breakpoints = INSTAGRAM_BLOCK;
1661            }
1662
1663            if (swiperElement.closest('.explore-categories-slider')) {
1664                // Start with base breakpoints and override slidesPerView only when custom values > 0
1665                customOptions.breakpoints = {...EXPLORE_CATEGORIES_SLIDER_BREAKPOINT};
1666
1667                if (options.breakpoints) {
1668                    Object.keys(options.breakpoints).forEach(breakpoint => {
1669                        const customBreakpoint = options.breakpoints[breakpoint];
1670                        if (customBreakpoint.slidesPerView && customBreakpoint.slidesPerView > 0) {
1671                            // If breakpoint exists in base, preserve its properties; if not, add default properties
1672                            const baseBreakpoint = customOptions.breakpoints[breakpoint] || {};
1673                            const defaultBreakpointProps = {
1674                                spaceBetween: 20, // Default spaceBetween for larger breakpoints
1675                                allowTouchMove: false // Default for larger breakpoints
1676                            };
1677                            
1678                            customOptions.breakpoints[breakpoint] = {
1679                                ...defaultBreakpointProps,
1680                                ...baseBreakpoint,
1681                                slidesPerView: customBreakpoint.slidesPerView
1682                            };
1683                        }
1684                    });
1685                }
1686            }
1687
1688            if (swiperElement.closest('[data-content-type="featured-products-slider"]')) {
1689                customOptions.breakpoints = FEATURE_SLIDER_BLOCK_BREAKPOINT;
1690            }
1691
1692            const swiperInstance = new Swiper(swiperElement, {
1693                slidesPerView: 'auto',
1694                spaceBetween: 16,
1695                mousewheel: {
1696                    forceToAxis: true
1697                },
1698                ...customOptions
1699            });
1700            return swiperInstance;
1701        }
1702
1703        if (!window.Swiper) {
1704            if (!window.swiperPromise) {
1705                window.swiperPromise = new Promise((resolve) => {
1706                    window.swiperInitializing = true;
1707                    addSwiperCss();
1708                    addSwiperJs(() => {
1709                        resolve();
1710                    });
1711                });
1712            }
1713
1714            return window.swiperPromise.then(() => {
1715                return initSlider();
1716            });
1717        } else {
1718            return initSlider();
1719        }
1720    }
1721</script>
1721
1722<input name="form_key" type="hidden" value="cbEPL7j02Kuo6BSa" />
1723    <noscript>
1724        <section class="message global noscript border-b-2 border-blue-500 bg-blue-50 shadow-none m-0 px-0 rounded-none font-normal">
1725            <div class="container text-center">
1726                <p>
1727                    <strong>JavaScript seems to be disabled in your browser.</strong>
1728                    <span>
1729                        For the best experience on our site, be sure to turn on Javascript in your browser.                    </span>
1730                </p>
1731            </div>
1732        </section>
1733    </noscript>
1734
1735
1736<script>
1737    document.body.addEventListener('touchstart', () => {}, {passive: true})
1738</script>
1738
1739
1740    
1740<script>
1741        window.amRecaptchaModel = window.amRecaptchaModel || {};
1742    </script>
1742
1743    
1743<script>
1744    'use strict';
1745
1746    (() => {
1747        window.addEventListener(
1748            'ga-initialized',
1749            () => {
1750                window.addEventListener('cart-item-added', (event) => {
1751                    let products = [];
1752
1753                    event.detail.forEach((item) => {
1754                        products.push({
1755                            id: item['product_sku'],
1756                            name: item['product_name'],
1757                            price: item['product_price_value'],
1758                            quantity: item['qty'],
1759                        });
1760                    });
1761
1762                    dataLayer.push({
1763                        event: 'addToCart',
1764                        ecommerce: {
1765                            currencyCode: 'CAD',
1766                            add: {
1767                                products: products,
1768                            },
1769                        },
1770                    });
1771                });
1772            },
1773            { once: true }
1774        );
1775    })();
1776</script>
vendor: 1 bytes, line 1776
1776
1777<script>
1778    'use strict';
1779
1780    (() => {
1781        window.addEventListener(
1782            'ga-initialized',
1783            () => {
1784                window.addEventListener('cart-item-removed', (event) => {
1785                    let products = [];
1786
1787                    event.detail.forEach((item) => {
1788                        products.push({
1789                            id: item['product_sku'],
1790                            name: item['product_name'],
1791                            price: item['product_price_value'],
1792                            quantity: item['qty'],
1793                        });
1794                    });
1795
1796                    dataLayer.push({
1797                        event: 'removeFromCart',
1798                        ecommerce: {
1799                            currencyCode: 'CAD',
1800                            remove: {
1801                                products: products,
1802                            },
1803                        },
1804                    });
1805                });
1806            },
1807            { once: true }
1808        );
1809    })();
1810</script>
vendor: 1 bytes, line 1810
1810
1811<script>
1812    'use strict';
1813
1814    (() => {
1815        window.addEventListener(
1816            'ga-initialized',
1817            () => {
1818                const banners = document.querySelectorAll('\u005Bdata\u002Dbanner\u002Did\u005D');
1819                let promotions = [];
1820
1821                banners.forEach((banner) => {
1822                    banner.addEventListener('click', () => {
1823                        window.dataLayer.push({
1824                            event: 'promotionClick',
1825                            ecommerce: {
1826                                promoClick: {
1827                                    promotions: [{
1828                                        id: banner.dataset.bannerId,
1829                                        name: banner.dataset.bannerName,
1830                                        creative: '',
1831                                        position: 'customer_account_login',
1832                                    }],
1833                                },
1834                            },
1835                        });
1836                    });
1837
1838                    promotions.push({
1839                        id: banner.dataset.bannerId,
1840                        name: banner.dataset.bannerName,
1841                        creative: '',
1842                        position: 'customer_account_login',
1843                    });
1844                });
1845
1846                if (promotions.length) {
1847                    window.dataLayer.push({
1848                        event: 'promotionView',
1849                        ecommerce: {
1850                            promoView: {
1851                                promotions: promotions,
1852                            },
1853                        },
1854                    });
1855                }
1856            },
1857            { once: true }
1858        );
1859    })();
1860</script>
1860
1861
1862<script>
1863    'use strict';
1864    (function(hyva) {
1865                const formValidationRules = {
1866            required(value, options, field, context) {
1867                const el = field.element.type === 'hidden' ? createTextInputFrom(field.element) : field.element,
1868                    msg = 'This\u0020is\u0020a\u0020required\u0020field.';
1869
1870                if (el.type === 'radio' || el.type === 'checkbox') {
1871                    return (value === undefined || value.length === 0) ? msg : true;
1872                }
1873
1874                el.setAttribute('required', '');
1875                el.checkValidity();
1876
1877                return el.validity.valueMissing ? msg : true;
1878            },
1879            maxlength(value, options, field, context) {
1880                const n = Number(options)
1881                if (value.length > n) {
1882                    return n === 1
1883                        ? hyva.strf('Please\u0020enter\u0020no\u0020more\u0020than\u00201\u0020character.')
1884                        : hyva.strf('Please\u0020enter\u0020no\u0020more\u0020than\u0020\u00250\u0020characters.', options)
1885                }
1886                return true;
1887            },
1888            minlength(value, options, field, context) {
1889                const n = Number(options)
1890                if (value.length > 0 && value.length < n) {
1891                    return n === 1
1892                        ? hyva.strf('Please\u0020enter\u0020at\u0020least\u00201\u0020character.')
1893                        : hyva.strf('Please\u0020enter\u0020at\u0020least\u0020\u00250\u0020characters.', options)
1894                }
1895                return true;
1896            },
1897            max(value, options, field, context) {
1898                field.element.setAttribute('max', options);
1899                field.element.checkValidity();
1900                if (field.element.validity.rangeOverflow) {
1901                    return hyva.strf('Please\u0020enter\u0020a\u0020value\u0020less\u0020than\u0020or\u0020equal\u0020to\u0020\u0022\u00250\u0022.', options);
1902                }
1903                return true;
1904            },
1905            min(value, options, field, context) {
1906                field.element.setAttribute('min', options);
1907                field.element.checkValidity();
1908                if (field.element.validity.rangeUnderflow) {
1909                    return hyva.strf('Please\u0020enter\u0020a\u0020value\u0020greater\u0020than\u0020or\u0020equal\u0020to\u0020\u0022\u00250\u0022.', options);
1910                }
1911                return true;
1912            },
1913            step(value, options, field, context) {
1914                field.element.setAttribute('step', options);
1915                field.element.checkValidity();
1916                if (field.element.validity.stepMismatch) {
1917                    const val = Number(value);
1918                    const step = Number(options);
1919                    const msg = 'Please\u0020enter\u0020a\u0020valid\u0020value.\u0020The\u0020two\u0020nearest\u0020valid\u0020values\u0020are\u0020\u0022\u00250\u0022\u0020and\u0020\u0022\u00251\u0022.';
1920                    return hyva.strf(msg, Math.floor(val / step) * step, Math.ceil(val / step) * step);
1921                }
1922                return true;
1923            },
1924            pattern(value, options, field, context) {
1925                field.element.setAttribute('pattern', options);
1926                field.element.checkValidity();
1927                if (field.element.validity.patternMismatch) {
1928                    return field.element.title
1929                        ? hyva.strf('Please\u0020match\u0020the\u0020requested\u0020format\u003A\u0020\u00250.', field.element.title)
1930                        : 'Please\u0020match\u0020the\u0020requested\u0020format.'
1931                }
1932                return true;
1933            },
1934            email(value, options, field, context) {
1935                                const rule = /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i;
1936                if (value.length > 0 && !rule.test(value)) {
1937                    return 'Please\u0020enter\u0020a\u0020valid\u0020email\u0020address.';
1938                }
1939                return true;
1940            },
1941            password(value, options, field, context) {
1942                const rule = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/;
1943                if (value.length > 0 && !rule.test(value)) {
1944                    return 'Please\u0020provide\u0020at\u0020least\u0020one\u0020upper\u0020case,\u0020one\u0020lower\u0020case,\u0020one\u0020digit\u0020and\u0020one\u0020special\u0020character\u0020\u0028\u0023\u003F\u0021\u0040\u0024\u0025\u005E\u0026\u002A\u002D\u0029';
1945                }
1946                return true;
1947            },
1948            equalTo(value, options, field, context) {
1949                const dependencyField = context.fields[options].element;
1950                if (value !== dependencyField.value) {
1951                    const dependencyFieldName =
1952                        dependencyField.label ||
1953                        dependencyField.title ||
1954                        (dependencyField.labels && dependencyField.labels[0] && dependencyField.labels[0].innerText) ||
1955                        dependencyField.name;
1956                    return hyva.strf('This\u0020field\u0020value\u0020must\u0020be\u0020the\u0020same\u0020as\u0020\u0022\u00250\u0022.', dependencyFieldName);
1957                }
1958                return true;
1959            }
1960        };
1961
1962                function raceSome(promises, pred) {
1963            return new Promise((resolve, reject) => {
1964
1965                if (promises.length === 0) {
1966                    return resolve();
1967                }
1968
1969                let settled = false, nDone = 0;
1970
1971                const resolveIf = v => {
1972                    if (!settled && (pred(v) || ++nDone === promises.length)) {
1973                        settled = true;
1974                        resolve(v);
1975                    }
1976                    return v;
1977                }
1978
1979                promises.map(promise => {
1980                    promise.then(resolveIf).catch(reason => {
1981                        settled = true;
1982                        reject(reason)
1983                    });
1984                    return promise;
1985                });
1986            });
1987        }
1988
1989        const INPUT_ATTRIBUTE_RULES = {min: 'min', max: 'max', required: 'required', minlength: 'minlength', maxlength: 'maxlength', step: 'step', pattern: 'pattern'}
1990        const INPUT_TYPE_RULES = {email: 'email'}
1991
1992        function getRules(element) {
1993            let rules = {};
1994            Object.keys(INPUT_ATTRIBUTE_RULES).forEach(attrName => {
1995                if (element.hasAttribute(attrName)) {
1996                    rules[INPUT_ATTRIBUTE_RULES[attrName]] = element.getAttribute(attrName);
1997                }
1998            })
1999            if (INPUT_TYPE_RULES[element.type]) {
2000                rules[INPUT_TYPE_RULES[element.type]] = true;
2001            }
2002
2003            if (element.dataset.validate) {
2004                try {
2005                    Object.assign(rules, JSON.parse(element.dataset.validate));
2006                } catch (error) {
2007                    console.error('Validator error. Cannot parse data-validate attribute of element:\n', element);
2008                }
2009            }
2010
2011            return rules;
2012        }
2013
2014        function isInvalidRuleResult(ruleState) {
2015            return typeof ruleState === 'string' || !ruleState || (ruleState.type && ruleState.content);
2016        }
2017
2018        async function runValidateFn(rule, options, value, field) {
2019            return formValidationRules[rule](value, options, field, this);
2020        }
2021
2022        function generateId() {
2023            let id;
2024            do {
2025                id = `${this.idPrefix}-${++this.idSeq}`;
2026            } while (document.getElementById(id));
2027            return id;
2028        }
2029
2030        function isVisible(element) {
2031            const el = element.type !== 'hidden' ? element : (element.parentElement || {});
2032            return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)
2033        }
2034
2035        function elementWillValidate(element) {
2036            return (element.willValidate || element.type === 'hidden')
2037                && element.tagName !== 'BUTTON'
2038                && element.disabled === false
2039                && !(element.tagName === 'INPUT' && element.type === 'submit')
2040                && (element.hasAttribute('data-validate-hidden') || isVisible(element))
2041        }
2042
2043        function createMessageContainer(el, fieldWrapperClassName) {
2044            if (! el.parentElement) {
2045                return;
2046            }
2047            const refocus = document.activeElement === el;
2048            const wrapper = document.createElement('div');
2049            wrapper.classList.add.apply(wrapper.classList, fieldWrapperClassName.split(' '));
2050            el.parentElement.insertBefore(wrapper, el);
2051            wrapper.appendChild(el);
2052            refocus && document.activeElement !== el && el.focus();
2053            return wrapper;
2054        }
2055
2056        function containerNotFound(selector, el) {
2057            const msg = `Cannot find message container element ${selector} of ${el.name}`;
2058            console.error(msg, el);
2059            throw msg;
2060        }
2061
2062        function createTextInputFrom(el) {
2063            const text = document.createElement('INPUT');
2064            text.type = 'text';
2065            text.value = el.value;
2066            return text;
2067        }
2068
2069        function classNamesToSelector(classNames) {
2070            return classNames.split(' ')
2071                .filter(className => className.length > 0)
2072                .map(className => `.${className}`)
2073                .join('')
2074        }
2075
2076        function hasMessagesWrapper(field, messagesWrapperClassName) {
2077            return this.getMessageContainer(field).querySelector(classNamesToSelector(messagesWrapperClassName));
2078        }
2079
2080        function getMessagesWrapper(field, messagesWrapperClassName) {
2081            if (hasMessagesWrapper.call(this, field, messagesWrapperClassName)) {
2082                return this.getMessageContainer(field).querySelector(classNamesToSelector(messagesWrapperClassName));
2083            }
2084
2085            const msgWrapper = document.createElement('ul');
2086            const msgId = generateId.call(this);
2087            msgWrapper.id = msgId;
2088            field.element.setAttribute('aria-errormessage', msgId);
2089            field.element.setAttribute('aria-describedby', msgId);
2090            msgWrapper.classList.add.apply(msgWrapper.classList, messagesWrapperClassName.split(' '));
2091            if (field.validateOnChange) {
2092                msgWrapper.setAttribute('aria-live', 'polite');
2093            }
2094            this.getMessageContainer(field).appendChild(msgWrapper);
2095
2096            return msgWrapper;
2097        }
2098
2099        function getCheckedValues(field) {
2100            const name = field.element.name.replace(/([\\"])/g, '\\$1');
2101            const elements = field.element.form.querySelectorAll('input[name="' + name + '"]:checked');
2102            return Array.from(elements).map(el => el.value);
2103        }
2104
2105        function escapeHtml(s) {
2106            const div = document.createElement('div')
2107            div.innerText = s;
2108            return div.innerHTML;
2109        }
2110
2111        
2112        function formValidation(form, options = {}) {
2113            const formElement = form || this.$el;
2114
2115            if (formElement.dataset && formElement.dataset.options) {
2116                try {
2117                    options = Object.assign(options, JSON.parse(formElement.dataset.options || '{}'));
2118                } catch (e) {
2119                    throw new Error('Cannot read the form options from the data-options attribute: not val
2119id JSON');
2120                }
2121            }
2122
2123            // Disable browser default validation
2124            if (formElement.tagName === 'FORM') {
2125                formElement.setAttribute('novalidate', '');
2126            } else {
2127                console.error('formValidation can be initialized only on FORM element', formElement);
2128                return;
2129            }
2130
2131            options = Object.assign({
2132                fieldWrapperClassName: 'field field-reserved',
2133                messagesWrapperClassName: 'messages',
2134                validClassName: 'field-success',
2135                invalidClassName: 'field-error',
2136                pageMessagesWrapperSelector: null,
2137                scrollToFirstError: true,
2138            }, options || {});
2139
2140            return {
2141                state: {
2142                    valid: false,
2143                },
2144                fields: {},
2145                idSeq: 0,
2146                idPrefix: formElement.id || 'vld-msg',
2147                setupFields(elements) {
2148                    this.fields = {};
2149                    Array.from(elements).forEach(element => {
2150                        if (elementWillValidate(element)) {
2151                            this.setupField(element);
2152                        }
2153                    });
2154                },
2155                setupField(element) {
2156                    if (! element) return;
2157                    const onChange = !!element.dataset.onChange;
2158                    if (elementWillValidate(element)) {
2159                        const rules = getRules(element);
2160                        if (Object.keys(rules).length > 0) {
2161                            if (this.fields[element.name]) {
2162                                Object.assign(this.fields[element.name].rules, rules);
2163                            } else {
2164                                this.fields[element.name] = {
2165                                    element,
2166                                    rules: rules,
2167                                    validateOnChange: onChange,
2168                                    state: {
2169                                        valid: null,
2170                                        rules: {}
2171                                    }
2172                                }
2173                            }
2174                        }
2175                    } else {
2176                        console.error('Element will not validate', element);
2177                    }
2178                },
2179                onSubmit(event) {
2180                    if (event.target.tagName === 'FORM') {
2181                        event.preventDefault();
2182
2183                        this.validate()
2184                            .then(() => event.target.submit())
2185                            .catch(invalidElements => {});
2186                    }
2187                },
2188                onChange(event) {
2189                    event.target.dataset.onChange = 'true';
2190                    if (!Object.keys(this.fields).length) {
2191                        this.setupFields(formElement.elements);
2192                    }
2193                    if (!Object.keys(this.fields).includes(event.target.name)) {
2194                        this.setupField(event.target);
2195                    }
2196                    const field = this.fields[event.target.name];
2197
2198                    this.validateField(field);
2199                    field && field.element.removeAttribute('data-on-change')
2200                },
2201                validateSafe() {
2202                    return new Promise(resolve => this.validate().then(() => resolve(true)).catch(() => {}))
2203                },
2204                validate() {
2205                    if (!Object.keys(this.fields).length || !Object.keys(this.fields).length !== formElement.elements.length) {
2206                        this.setupFields(formElement.elements);
2207                    }
2208                    return new Promise(async (resolve, reject) => {
2209                        if (formElement.elements) {
2210                                                        await raceSome(this.validateFields(), result => result !== true)
2211                            const invalidFields = Object.values(this.fields).filter(field => !field.state.valid);
2212                            this.state.valid = invalidFields.length === 0;
2213                            if (this.state.valid) {
2214                                resolve();
2215                            } else {
2216                                if (options.scrollToFirstError && invalidFields.length > 0) {
2217                                    invalidFields[0].element.focus()
2218                                    invalidFields[0].element.select && invalidFields[0].element.select();
2219                                }
2220                                reject(invalidFields.map(field => field.element));
2221                            }
2222                        }
2223                    });
2224                },
2225                                validateFields() {
2226                    const fields = Object.values(this.fields);
2227
2228                                        fields.forEach(field => {
2229                        this.getMessageContainer(field).classList.remove(options.validClassName, options.invalidClassName)
2230                    });
2231                                        return fields.map(field => this.validateField(field))
2232                },
2233                                validateField(field) {
2234                                        if (! field || ! elementWillValidate(field.element)) {
2235                        return new Promise(resolve => resolve(true))
2236                    }
2237
2238                    let value;
2239                    if (field.element.type === 'checkbox') {
2240                        value = getCheckedValues(field);
2241                    } else if (field.element.type === 'radio') {
2242                        value = getCheckedValues(field)[0] || undefined;
2243                    } else if (field.element.tagName === 'SELECT' && field.element.multiple) {
2244                        value = Array.from(field.element.selectedOptions).map(opt => opt.value);
2245                    } else {
2246                        value = field.element.value;
2247                    }
2248
2249                    const rules = field.rules || {};
2250
2251                                        field.state.valid = true;
2252                    this.showFieldState(field);
2253
2254                
2255                                        const fieldValidations = Object.keys(rules).filter(rule => formValidationRules[rule]).map(async rule => {
2256                        return runValidateFn.call(this, rule, rules[rule], value, field).then(result => {
2257                            field.state.rules[rule] = result;
2258                            return result;
2259                        })
2260                    });
2261
2262                    return new Promise(resolve => {
2263                                                Promise.all(fieldValidations).then(results => {
2264                                                                                    field.state.valid = !elementWillValidate(field.element) || rules.length === 0 || !results.some(isInvalidRuleResult)
2265                            this.showFieldState(field);
2266                            resolve(field.state.valid);
2267                        })
2268                    });
2269                },
2270                                getMessagesByField(field) {
2271                    const messages = [];
2272                    const invalidRules = Object.keys(field.state.rules).filter(rule => isInvalidRuleResult(field.state.rules[rule]));
2273
2274                    field.rules && Object.keys(field.rules).forEach((rule) => {
2275                        if (invalidRules.includes(rule)) {
2276                            const customMessage = field.element.getAttribute('data-msg-' + rule);
2277                            const message = customMessage ? customMessage : field.state.rules[rule];
2278                            const ruleOptions = JSON.parse(JSON.stringify(field.rules[rule]));
2279
2280                            if (typeof message === 'undefined' || message === null || (typeof message !== 'string' && ! message.type)) {
2281                                messages.push(hyva.strf('Validation rule "%0" failed.', rule));
2282                            } else if (Array.isArray(ruleOptions)) {
2283                                ruleOptions.unshift(message.type ? message.content : message);
2284                                const content = hyva.strf.apply(null, ruleOptions);
2285                                messages.push(message.type ? {type: message.type, content} : content);
2286                            } else {
2287                                const content = hyva.strf(message.type ? message.content : message, ruleOptions)
2288                                messages.push(message.type ? {type: message.type, content} : content);
2289                            }
2290                        }
2291                    });
2292                    return messages;
2293                },
2294                /** @deprecated */
2295                getFieldWrapper(field) {
2296                                        return this.getMessageContainer(field)
2297                },
2298                getMessageContainer(field) {
2299                    let container;
2300                    const pageSelector = field.element.getAttribute('data-validation-container') || options.pageMessagesContainerSelector;
2301                    if (pageSelector) {
2302                        container = document.querySelector(pageSelector)
2303                            || containerNotFound(pageSelector, field.element)
2304                    } else {
2305                        const containerSelector = classNamesToSelector(options.fieldWrapperClassName);
2306                        container = field.element.closest(containerSelector)
2307                            || createMessageContainer(field.element, options.fieldWrapperClassName)
2308                            || containerNotFound(containerSelector, field.element);
2309                    }
2310
2311                    return container;
2312                },
2313                showFieldState(field) {
2314                    const container = this.getMessageContainer(field),
2315                        hasErrorMessages = hasMessagesWrapper.call(this, field, options.messagesWrapperClassName),
2316                        messages = this.getMessagesByField(field).map(m => {
2317                            return m.type !== 'html' ? escapeHtml(m.type ? m.content : m) : m.content;
2318                        });
2319                    container.classList.toggle(options.validClassName, field.state.valid && ! hasErrorMessages);
2320                    container.classList.toggle(options.invalidClassName, !field.state.valid || hasErrorMessages);
2321                    this.createHtmlErrorMessage(field, messages);
2322
2323                    if (field.state.valid) {
2324                        field.element.removeAttribute('aria-invalid');
2325                    } else {
2326                        field.element.setAttribute('aria-invalid', 'true');
2327                        if (! document.activeElement) {
2328                            field.element.focus();
2329                        }
2330                    }
2331                },
2332                removeMessages(field, messagesClass) {
2333                    if (! hasMessagesWrapper.call(this, field, messagesClass || options.messagesWrapperClassName)) {
2334                        return;
2335                    }
2336
2337                    const msgWrapper = getMessagesWrapper.call(this, field, messagesClass || options.messagesWrapperClassName);
2338                    const messages = msgWrapper.querySelectorAll(`[data-msg-field='${field.element.name}']`);
2339                    Array.from(messages).forEach(msg => msg.remove());
2340                    if (msgWrapper && msgWrapper.childElementCount === 0) {
2341                        field.element.removeAttribute('aria-errormessage');
2342                        field.element.removeAttribute('aria-describedby');
2343                        msgWrapper.remove();
2344                    }
2345                },
2346                createErrorMessage(field, messages) {
2347                    const htmlMessages = (Array.isArray(messages) ? messages : [messages]).map(escapeHtml)
2348                    this.createHtmlErrorMessage(field, htmlMessages);
2349                },
2350                createHtmlErrorMessage(field, messages) {
2351                    this.removeMessages(field, options.messagesWrapperClassName);
2352                    field.element.removeAttribute('aria-errormessage');
2353                    field.element.removeAttribute('aria-describedby');
2354
2355                    if (!field.state.valid) {
2356                        const msgWrapper = this.addHtmlMessages(field, options.messagesWrapperClassName, messages);
2357                        field.element.setAttribute('aria-errormessage', msgWrapper.id);
2358                        field.element.setAttribute('aria-describedby', msgWrapper.id);
2359                    }
2360                },
2361                /** @deprecated */
2362                createMessage(field, message) {
2363                                        return this.addMessages(field, options.messagesWrapperClassName, message);
2364                },
2365                addMessages(field, messagesClass, messages) {
2366                    const htmlMessages = (Array.isArray(messages) ? messages : [messages]).map(escapeHtml)
2367                    return this.addHtmlMessages(field, messagesClass, htmlMessages);
2368                },
2369                addHtmlMessages(field, messagesClass, htmlMessages) {
2370                    const msgWrapper = getMessagesWrapper.call(this, field, messagesClass);
2371
2372                    (Array.isArray(htmlMessages) ? htmlMessages : [htmlMessages]).forEach((htmlMessage) => {
2373                        const li = document.createElement('li');
2374                        li.innerHTML = htmlMessage;
2375                        li.setAttribute('data-msg-field', field.element.name);
2376                        msgWrapper.appendChild(li);
2377                    });
2378
2379                    return msgWrapper;
2380                },
2381                setField(name, value) {
2382                    this.fields[name].element.value = value;
2383                    this.fields[name].element.dispatchEvent((new Event('input')));
2384                    this.validateField(this.fields[name]);
2385                }
2386            }
2387        }
2388
2389        hyva.formValidation = formValidation;
2390        hyva.formValidation.rules = formValidationRules;
2391        hyva.formValidation.setInputAttributeRuleName = (attrName, ruleName) => INPUT_ATTRIBUTE_RULES[attrName] = ruleName || attrName;
2392        hyva.formValidation.setInputTypeRuleName = (typeName, ruleName) => INPUT_TYPE_RULES[typeName] = ruleName || typeName;
2393        hyva.formValidation.addRule = (name, validator) => formValidationRules[name] = validator;
2394    }(window.hyva = window.hyva || {}));
2395
2396    window.addEventListener('alpine:init', () => {
2397        Alpine.data('hyva.formValidation', hyva.formValidation);
2398        Alpine.data('hyva.formValidation($el)', hyva.formValidation);
2399    }, {once: true});
2400</script>
2400
2401<div class="page-wrapper"><header class="page-header"><a class="action skip sr-only focus:not-sr-only focus:absolute focus:z-40 focus:bg-white
2402   contentarea"
2403   href="#contentarea">
2404    <span>
2405        Skip to Content    </span>
2406</a>
2407    
2407<script type="application/javascript" async
2408            src="https://static.klaviyo.com/onsite/js/TzSV8X/klaviyo.js"></script>
2408
2409
2410    <div x-data="initKlaviyoCustomerTracking()"
2411         @private-content-loaded.window="sendCustomerDataToKlaviyo(event.detail.data)"></div>
2412    
2412<script>
2413        !function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}();
2414
2415        function initKlaviyoCustomerTracking() {
2416            return {
2417                sendCustomerDataToKlaviyo(data) {
2418                    window.klaviyo = window.klaviyo || [];
2419                    const customer = data.customer;
2420
2421                    window.klaviyo.isIdentified().then((identified)=> {
2422                        if(customer && customer.email && !identified) {
2423                            window.klaviyo.identify({
2424                                '$email': customer.email,
2425                                '$first_name': customer.firstname ? customer.firstname : '',
2426                                '$last_name':  customer.lastname ? customer.lastname : ''
2427                            });
2428                        }
2429                    });
2430                }
2431            }
2432        }
2433    </script>
vendor: 1 bytes, line 2433
2433
2434<script>
2435    function initHeader() {
2436        return {
2437            searchOpen: false,
2438            cart: {},
2439            isCartOpen: false,
2440            isMobile: true,
2441            // Defined in px
2442            downScrollThreshold: 300,
2443            upScrollThreshold: 150,
2444            headerTagElement: undefined,
2445            lastScrollPosition: window.scrollY,
2446            lastScrollDirection: undefined,
2447
2448            init() {
2449                this.headerTagElement = document.querySelector('header.page-header');
2450
2451                this.onChangeMedia(this.$store.device.isDesktop);
2452                this.handleNotificationHeight();
2453
2454                this.$watch('$store.device.isDesktop', (isDesktop) => {
2455                    this.onChangeMedia(isDesktop);
2456                    this.handleNotificationHeight();
2457                })
2458
2459            },
2460            handleNotificationHeight() {
2461                this.headerTagElement.style.setProperty('--header-notification-height', `${this.$refs.headerNotification.offsetHeight}px`);
2462            },
2463            handleScrollThreshold() {
2464                const {
2465                    scrollY
2466                } = window;
2467
2468                // Determine if we are scrolling up or down
2469                const isScrollingDown = this.lastScrollPosition < scrollY;
2470                const isScrollingUp = this.lastScrollPosition > scrollY;
2471
2472                if (isScrollingDown && this.lastScrollDirection !== 'down') {
2473                    this.lastScrollDirection = 'down';
2474                    this.scrollUpDistance = 0;
2475                }
2476
2477                if (isScrollingUp && this.lastScrollDirection !== 'up') {
2478                    this.lastScrollDirection = 'up';
2479                    this.scrollDownDistance = 0;
2480                }
2481
2482                // If scrolling down and exceeding the down scroll threshold, hide notification
2483                if (isScrollingDown && scrollY > this.downScrollThreshold && !this.isNotificationHidden) {
2484                    this.handleHideNotification(true, scrollY);
2485                    this.lastScrollPosition = scrollY;
2486                    return;
2487                }
2488
2489                // If scrolling up and exceeding the up scroll threshold (100px), show notification again
2490                if (isScrollingUp && (scrollY < this.lastScrollPosition - this.upScrollThreshold)) {
2491                    this.handleHideNotification(false, scrollY);
2492                    this.lastScrollPosition = scrollY;
2493                    return;
2494                }
2495
2496                // Handle the scrolling up or down thresholds with reset behavior
2497                if (isScrollingDown) {
2498                    this.scrollDownDistance += scrollY - this.lastScrollPosition;
2499                    if (this.scrollDownDistance > this.downScrollThreshold) {
2500                        this.handleHideNotification(true, scrollY);
2501                    }
2502                }
2503
2504                if (isScrollingUp) {
2505                    this.scrollUpDistance += this.lastScrollPosition - scrollY;
2506                    if (this.scrollUpDistance > 100) {
2507                        this.handleHideNotification(false, scrollY);
2508                    }
2509                }
2510
2511                // Update the last scroll position
2512                this.lastScrollPosition = scrollY;
2513            },
2514            handleHideNotification(isHidden, scrollPosition) {
2515                if (isHidden) {
2516                    this.headerTagElement.classList.add('page-header-hidden-notification');
2517                } else {
2518                    this.headerTagElement.classList.remove('page-header-hidden-notification');
2519                }
2520
2521                this.isNotificationHidden = isHidden;
2522                this.lastScrollPosition = scrollPosition;
2523            },
2524            getData(data) {
2525                if (data.cart) {
2526                    this.cart = data.cart
2527                }
2528            },
2529            isCartEmpty() {
2530                return !this.cart.summary_count
2531            },
2532            toggleCart(event) {
2533                if (event.detail && event.detail.isOpen !== undefined) {
2534                    this.isCartOpen = event.detail.isOpen
2535                    if (!this.isCartOpen && this.$refs && this.$refs.cartButton) {
2536                        this.$refs.cartButton.focus()
2537                    }
2538                } else {
2539                                        this.isCartOpen = true
2540                }
2541            },
2542            onChangeMedia(isDesktop) {
2543                if (!isDesktop) {
2544                    this.$refs.searchContainerMobile.appendChild(this.$refs.searchForm);
2545                } else {
2546                    const desktopSearchContainer = this.$refs.searchContainerDesktop;
2547                    if (desktopSearchContainer.firstElementChild) {
2548                        desktopSearchContainer.replaceChild(this.$refs.searchForm, desktopSearchContainer.firstElementChild);
2549                    } else {
2550                        desktopSearchContainer.appendChild(this.$refs.searchForm);
2551                    }
2552                }
2553            },
2554            toggleSearch() {
2555                this.searchOpen = !this.searchOpen;
2556                if (this.searchOpen) {
2557
2558                    this.$dispatch('open-search-popup', {});
2559
2560                    // Focus on search input when opened
2561                    setTimeout(() => {
2562                        const searchInput = this.$refs.searchContainerMobile.querySelector('input[type="text"]');
2563                        if (searchInput) {
2564                            searchInput.focus();
2565                        }
2566                    }, 100);
2567                }
2568            },
2569            closeSearch() {
2570                this.searchOpen = false;
2571            }
2572        }
2573    }
2574
2575    function initCompareHeader() {
2576        return {
2577            compareProducts: null,
2578            itemCount: 0,
2579            receiveCompareData(data) {
2580                if (data['compare-products']) {
2581                    this.compareProducts = data['compare-products'];
2582                    this.itemCount = this.compareProducts.count;
2583                }
2584            }
2585        }
2586    }
2587</script>
2587
2588<div id="header"
2589     x-data="initHeader()"
2590     @scroll.window="handleScrollThreshold"
2591     @private-content-loaded.window="getData(event.detail.data)"
2592>
2593        <div class="w-full h-full" x-ref="headerNotification">
2594        <div class="relative">
2595            <div class="header-notification [&_*]:!max-h-[50px] [&_*]:md:!max-h-10 [&_.pagebuilder-overlay-wrapper]:flex
2596                [&_.pagebuilder-overlay-wrapper]:justify-center [&_.pagebuilder-overlay-wrapper_*]:!flex
2597                [&_.pagebuilder-overlay-wrapper_*]:max-md:flex-wrap [&_.pagebuilder-overlay-wrapper_*]:!gap-x-1
2598                [&_.pagebuilder-overlay-wrapper_*]:!items-center [&_.pagebuilder-overlay-wrapper_*]:justify-center
2599                [&_.pagebuilder-poster-content>div]:w-full [&_.pagebuilder-poster-content>div]:justify-center"
2600            >
2601                <style>#html-body [data-pb-style=WLJFXII]{justify-content:center;display:flex;flex-direction:column;background-color:#532e91;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;text-align:center}#html-body [data-pb-style=VM4HDKS]{text-align:center;min-height:40px}#html-body [data-pb-style=EEQ7T1Q]{background-position:left top;background-size:cover;background-repeat:no-repeat;text-align:center;min-height:40px}#html-body [data-pb-style=S71GEM0]{min-height:40px;padding:0;background-color:transparent}#html-body [data-pb-style=SRABRMM]{background-position:left top;background-size:cover;background-repeat:no-repeat;text-align:center;min-height:40px}#html-body [data-pb-style=UH6V9IJ]{min-height:40px;padding:0;background-color:transparent}</style><div data-content-type="row" data-appearance="full-bleed" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="WLJFXII"><div class="pagebuilder-slider" data-content-type="slider" data-appearance="default" data-autoplay="true" data-autoplay-speed="4000" data-fade="true" data-infinite-loop="true" data-show-arrows="false" data-show-dots="false" data-element="main" data-pb-style="VM4HDKS"><div data-content-type="slide" data-slide-name="" data-appearance="poster" data-show-button="never" data-show-overlay="never" data-element="main"><div data-element="empty_link"><div class="pagebuilder-slide-wrapper" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="wrapper" data-pb-style="EEQ7T1Q"><div class="pagebuilder-overlay-wrapper"><div class="pagebuilder-overlay pagebuilder-poster-overlay" data-overlay-color="" aria-label="" title="" data-element="overlay" data-pb-style="S71GEM0"><div class="pagebuilder-poster-content"><div data-element="content"><p style="text-align: center;"><span style="color: rgb(0, 0, 0); font-size: 15px;"><strong><span style="color: rgb(255, 255, 255); font-size: 14px;"><span data-teams="true">Get Free Shipping for Canadian deliveries on orders above </span>$99! <span style="color: rgb(255, 255, 255); text-decoration: underline;">Shop now</span></span></strong></span></p></div></div></div></div></div></div></div><div data-content-type="slide" data-slide-name="" data-appearance="poster" data-show-button="never" data-show-overlay="never" data-element="main"><div data-element="empty_link"><div class="pagebuilder-slide-wrapper" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="wrapper" data-pb-style="SRABRMM"><div class="pagebuilder-overlay-wrapper"><div class="pagebuilder-overlay pagebuilder-poster-overlay" data-overlay-color="" aria-label="" title="" data-element="overlay" data-pb-style="UH6V9IJ"><div class="pagebuilder-poster-content"><div data-element="content"><p style="text-align: center;"><span style="font-size: 14px; color: rgb(255, 255, 255);"><strong>Canada&rsquo;s Chocolatier since 1907. <a style="color: rgb(255, 255, 255);" tabindex="0" href="https://www.purdys.com/purdys-heritage" target="_blank" rel="noopener">LEARN MORE</a></strong></span></p></div></div></div></div></div></div></div></div></div>            </div>
2602                    </div>
2603    </div>
2604
2605    <div class="bg-white lg:relative py-3 md:py-4 border-b border-primary-lightest lg:border-b-0" :class="{ 'border-transparent': searchOpen }">
2606        <div class="px-4 flex gap-5 md:px-5 2xl:px-10 lg:gap-10 justify-between items-center m-auto min-[1660px]:!max-w-[1740px]">
2607            <div
2608                class="header-left-links text-sm flex-1 hidden lg:block [&_ul]:ml-0 [&_ul]:gap-x-5 [&_ul]:flex [&_li]:before:content-['']
2609                       [&_li]:pl-0 [&_li]:m-0 [&_a]:no-underline [&_a]:font-normal [&_a]:text-primary-dark"
2610            >
2611                <div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><ul id="nav-top">
2612    <li><a href="/corporate-gifts"><b>CORPORATE GIFTS</b></a></li>
2613    <li><a href="https://fundraising.purdys.com/"><b>FUNDRAISING</b></a></li>
2614    <li><a href="https://group.purdys.com/"><b>GROUP SAVINGS</b></a></li>
2615    <!--<li><a href="/doordash-redirect?utm_source=purdys&amp;utm_medium=website&amp;utm_campaign=doordashlink"><b>DOORDASH</b></a></li>-->
2616</ul>
2617</div>            </div>
2618
2619            <!--Logo-->
2620            <a class="logo block !m-0" href="https://www.purdys.com/"
2621   aria-label="Go&#x20;to&#x20;Home&#x20;page">
2622    <img src="https://www.purdys.com/media/logo/stores/1/purdys-chocolatier-logo.png"
2623         alt="Purdys&#x20;Chocolatier&#x20;Logo"
2624         class="!h-[60px]"
2625         style="width: auto"
2626            width="auto"    />
2627    </a>
2628
2629            <div class="flex gap-6 lg:gap-5 items-center lg:flex-1">
2630
2631                <!--Search desktop-->
2632                <div x-ref="searchContainerDesktop" class="header-search-container hidden lg:block lg:flex-1">
2633                    <div>
2634                        <div x-data="initLiveSearch"
2635     x-init="initPopover"
2636     @close-search.window="closePopover"
2637     @open-search.window="openPopover"
2638     @keydown.escape="closePopover"
2639     class="relative"
2640>
2641    <search role="search">
2642        <form class="form minisearch w-full flex md:relative lg:max-w-80 ml-auto"
2643              id="search_mini_form"
2644              action="https://www.purdys.com/catalogsearch/result/"
2645              method="get"
2646        >
2647            <div class="relative w-full">
2648                <label class="hidden" for="search" data-role="minisearch-label">
2649                    <span>Search</span>
2650                </label>
2651                <input id="search"
2652                       class="form-input flex-1 px-3 py-2 rounded-sm outline-none w-full min-h-12 hover:border-primary focus:border-primary focus:shadow-none"
2653                       type="text"
2654                       x-ref="searchRef"
2655                       :value="queryPhrase"
2656                       name="q"
2657                       value=""
2658                       placeholder="Type&#x20;to&#x20;search..."
2659                       maxlength="128"
2660                       role="combobox"
2661                       aria-haspopup="false"
2662                       aria-autocomplete="both"
2663                       autocomplete="off"
2664                       aria-expanded="false"
2665                       @input="handleInput"
2666                       @click.away="closePopover"
2667                />
2668                <button type='submit'
2669                        title="Search"
2670                        x-show="queryPhrase === ''"
2671                        class='bg-primary text-white rounded-e-sm px-3 outline-none absolute end-0 top-0 h-full
2672                               rounded-r border-0 hover:bg-primary hover:border-0'
2673                        aria-label="Search">
2674                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
2675<path fill-rule="evenodd" clip-rule="evenodd" d="M8.75049 1.49969C4.74642 1.49969 1.50049 4.74563 1.50049 8.74969C1.50049 12.7538 4.74642 15.9997 8.75049 15.9997C12.7546 15.9997 16.0005 12.7538 16.0005 8.74969C16.0005 4.74563 12.7546 1.49969 8.75049 1.49969ZM0.000488281 8.74969C0.000488281 3.9172 3.918 -0.000305176 8.75049 -0.000305176C13.583 -0.000305176 17.5005 3.9172 17.5005 8.74969C17.5005 13.5822 13.583 17.4997 8.75049 17.4997C3.918 17.4997 0.000488281 13.5822 0.000488281 8.74969Z" fill="white"/>
2676<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4001 14.3993C14.7108 14.0887 15.2144 14.0887 15.5251 14.3993L19.7675 18.6418C20.0781 18.9524 20.0781 19.4561 19.7675 19.7667C19.4569 20.0774 18.9532 20.0774 18.6426 19.7667L14.4001 15.5243C14.0895 15.2136 14.0895 14.71 14.4001 14.3993Z" fill="white"/>
2677</svg>
2678                </button>
2679                <button
2680                    @click.prevent="queryString = ''; clearInput()"
2681                    x-cloak
2682                    x-show="queryPhrase !== ''"
2683                    title="Clear"
2684                    class="bg-primary text-white rounded-e-sm px-3 outline-none absolute
2685                           end-0 top-0 h-full rounded-r border-0 hover:bg-primary hover:border-0 hover:text-white"
2686                    aria-label="Clear">
2687                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
2688<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2689<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2690</svg>
2691                </button>
2692                <template x-if="queryPhrase != ''">
2693                    <a id="clearInput" class="absolute right-[60px] top-[11px] hover:text-primary" @click.prevent="clearInput" href="#">Clear</a>
2694                </template>
2695            </div>
2696        </form>
2697    </search>
2698    <div x-show="searchOpen"
2699         class="bg-black opacity-[0.6] fixed w-[100vw] h-[100vh] left-0 mt-[18px]"
2700         style="display: none;"
2701         @click="closePopup"></div>
2702    <section
2703        x-show="searchOpen"
2704        class="livesearch-overlay search-autocomplete overflow-y-scroll !h-[calc(100dvh-var(--height-header))] md:!h-auto md:overflow-y-auto"
2705        :class="getSearchClasses"
2706        style="display: none;"
2707        aria-label="Search&#x20;Suggestions"
2708        x-transition:enter='transition-all duration-300 ease-out'
2709        x-transition:enter-start='opacity-0'
2710        x-transition:enter-end='opacity-100'
2711        x-transition:leave='transition-all duration-200 ease-in'
2712        x-transition:leave-start='opacity-100'
2713        x-transition:leave-end='opacity-0'
2714    >
2715        <!-- No Results Header -->
2716        <template x-if="showResults && !liveSearchTotalCount && !isLoading">
2717            <div class="max-w-[1660px] mx-auto px-4 md:px-0">
2718                <div class="flex items-center justify-between">
2719                    <h3 class="font-bold text-xl md:text-3xl"
2720                        x-text="'No\u0020results\u0020found\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
2721                    <a href="#" @click.prevent='closePopup'>
2722                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
2723<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2724<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2725<title>x</title></svg>
2726                    </a>
2727                </div>
2728                <p class="pt-3">
2728We can't find any item matching your search. Please try another search.</p>
2729            </div>
2730        </template>
2731        <!-- Results Header -->
2732        <template x-if="showResults">
2733            <div class="flex items-center justify-between max-w-[1660px] mx-auto px-4 md:px-0">
2734                <h3 class="font-bold text-xl md:text-3xl !m-0" x-text="'Search\u0020results\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
2735                <a href="#" @click.prevent='closePopup'>
2736                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
2737<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2738<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
2739<title>x</title></svg>
2740                </a>
2741            </div>
2742        </template>
2743        <div x-show="liveSearchTotalCount && !isLoading" class="livesearch-overlay-content"
2744             x-transition:enter='transition-all duration-300 ease-out'
2745             x-transition:enter-start='opacity-0'
2746             x-transition:enter-end='opacity-100'
2747             x-transition:leave='transition-all duration-200 ease-in'
2748             x-transition:leave-start='opacity-100'
2749             x-transition:leave-end='opacity-0'>
2750            <template x-if="showSuggestions">
2751                <div class="flex flex-col md:max-h-[393px]">
2752                    <p class="text-lg pb-[10px] border-b border-grey-muted">
2753                        <strong>
2754                            Suggestions                        </strong>
2755                    </p>
2756                    <ul class="-mx-2 space-y-1 !border-0 pl-[8px]" role="list">
2757                        <template x-for="suggestion in liveSearchSuggestions">
2758                            <li class="before:hidden !border-0 !p-0 pl-0 hover:!bg-transparent">
2759                                <button
2760                                    x-html="getSuggestionText(suggestion)"
2761                                    @click="searchSuggestion"
2762                                    @mouseenter="onSuggestionHover(suggestion)"
2763                                    type="button"
2764                                    class="w-full p-2 text-left capitalize border-0 pl-0
2765                                           hover:text-primary-hover hover:underline
2766                                           hover:cursor-pointer hover:bg-transparent hover:border-0"
2767                                ></button>
2768                            </li>
2769                        </template>
2770                    </ul>
2771                    <div class="pt-3 md:pt-5 mt-auto pb-2.5 md:pb-0">
2772                        <a href='#' @click.prevent="redirectToSearchPage()" class='flex gap-1 items-center !text-primary'>
2773                            <span x-text="getSeeResultsText()"></span>
2774                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
2775  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
2776</svg>
2777                        </a>
2778                    </div>
2779                </div>
2780            </template>
2781            <template x-if="showResults">
2782                <div class="lg:col-span-2">
2783                    <p class="text-lg pb-[10px] border-b-[1px] border-grey-muted">
2784                        <strong>
2785                            Product Suggestions                        </strong>
2786                    </p>
2787                    <ul class="livesearch-overlay-content-products !border-0" role="list">
2788                        <template x-for="product in liveSearchProducts">
2789                            <li class="before:hidden pl-0 !p-0 !border-0 hover:!bg-transparent">
2790                                <button
2791                                    class="w-full flex gap-4 text-left cursor-pointer
2792                                           product-suggestion-button border-0 hover:bg-transparent hover:border-0"
2793                                    @click="handleProductClick"
2794                                >
2795                                    <img
2796                                        :src="product.image"
2797                                        :alt="product.name"
2798                                        width="80"
2799                                        height="80"
2800                                        class="w-[80px] h-[80px] shrink-0 object-contain"
2801                                    >
2802                                    <div class="flex flex-col justify-center w-full">
2803                                        <div class="flex flex-row justify-between gap-6">
2804                                            <p><strong class="product-name max-w-[287px]" x-text="product.name"></strong></p>
2805                                            <template x-if="product.price">
2806                                                <p class="font-bold" x-text="showProductPrice"></p>
2807                                            </template>
2808                                        </div>
2809                                    </div>
2810                                </button>
2811                            </li>
2812                        </template>
2813                    </ul>
2814                    <div class="py-5 md:pb-0">
2815                        <a href="#" @click.prevent="redirectToSearchPage(true)" class="flex gap-1 items-center !text-primary">
2816                            <span x-text="getSeeResultsText(true)"></span>
2817                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
2818  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
2819</svg>
2820                        </a>
2821                    </div>
2822                </div>
2823            </template>
2824        </div>
2825    </section>
2826</div>
2827
2828<script>
2829    'use strict';
2830    
2831    // Global search instance storage to persist across Alpine re-initializations
2832    window.liveSearchInstance = null;
2833    window.liveSearchInitialized = false;
2834    
2835    window.addEventListener(
2836        'alpine:init',
2837        () => Alpine.data('initLiveSearch', () => ({
2838            queryPhrase: '',
2839            liveSearchProducts: [],
2840            liveSearchSuggestions: [],
2841            liveSearchTotalCount: 0,
2842            isLoading: false,
2843            minQueryLength: 3,
2844            pageSize: 8,
2845            searchOpen: false,
2846            search: null,
2847            searchInitialized: false,
2848            isSuggestionHoverMode: false,
2849            suggestionHover: '',
2850            searchId: "2cc69165-2270-494c-893f-c00d0bb35bd7_" +
2851                "base_" +
2852                "main_website_store_" +
2853                "default",
2854
2855            initPopover() {
2856                this.initSearch();
2857                this.initTogglePopover();
2858
2859                const self = this;
2860
2861                window.addEventListener('open-search-popup', function (event) {
2862                    if (self.liveSearchTotalCount > 0) {
2863                        self.openPopover();
2864                    }
2865                });
2866
2867            },
2868
2869            async initSearch() {
2870                // Check if we already have a global instance
2871                if (window.liveSearchInitialized && window.liveSearchInstance) {
2872                    this.search = window.liveSearchInstance;
2873                    this.searchInitialized = true;
2874                    return;
2875                }
2876
2877                if (this.searchInitialized || this.searchInitializing) {
2878                    return;
2879                }
2880
2881                this.searchInitializing = true;
2882
2883                try {
2884                    // Set up storefront events
2885                    if (window.magentoStorefrontEvents) {
2886                        window.magentoStorefrontEvents.context.setSearchExtension({
2887                            version: "4.4.1"
2888                        });
2889                    }
2890
2891                    // Wait for MagentoLiveSearch to be available (with shorter timeout)
2892                    await this.waitForMagentoLiveSearch();
2893
2894                    if (!window.MagentoLiveSearch || typeof window.MagentoLiveSearch !== 'function') {
2895                        throw new Error('MagentoLiveSearch is not available');
2896                    }
2897
2898                    this.search = new window.MagentoLiveSearch({
2899                        environmentId: "2cc69165-2270-494c-893f-c00d0bb35bd7",
2900                        websiteCode: "base",
2901                        storeCode: "main_website_store",
2902                        storeViewCode: "default",
2903                        apiKey: "search_gql",
2904                    });
2905                    
2906                    if (!this.search) {
2907                        throw new Error('MagentoLiveSearch constructor returned null/undefined');
2908                    }
2909                    
2910                    // Store globally to persist across Alpine re-initializations
2911                    window.liveSearchInstance = this.search;
2912                    window.liveSearchInitialized = true;
2913                    this.searchInitialized = true;
2914                } catch (error) {
2915                    console.error('MagentoLiveSearch could not be initialized:', error);
2916                    this.searchInitialized = false;
2917                    this.search = null;
2918                } finally {
2919                    this.searchInitializing = false;
2920                }
2921            },
2922
2923            waitForMagentoLiveSearch() {
2924                return new Promise((resolve) => {
2925                    // If already available, resolve immediately
2926                    if (window.MagentoLiveSearch) {
2927                        resolve();
2928                        return;
2929                    }
2930
2931                    // Otherwise set up a watcher with faster polling
2932                    const checkInterval = setInterval(() => {
2933                        if (window.MagentoLiveSearch) {
2934                            clearInterval(checkInterval);
2935                            resolve();
2936                        }
2937                    }, 50); // Faster polling - 50ms instead of 100ms
2938
2939                    // Shorter timeout - 3 seconds instead of 10
2940                    setTimeout(() => {
2941                        clearInterval(checkInterval);
2942                        resolve();
2943                    }, 3000);
2944                });
2945            },
2946
2947            clearInput() {
2948                this.$refs.searchRef.value = '';
2949                this.liveSearchProducts = [];
2950                this.liveSearchSuggestions = [];
2951                this.liveSearchTotalCount = 0;
2952                this.queryPhrase = '';
2953
2954                this.closePopover();
2955            },
2956
2957            redirectToSearchPage(isSuggestion = false) {
2958                let searchTerm = this.queryPhrase;
2959                
2960                if (isSuggestion) {
2961                    // Use suggestionHover if available, otherwise fall back to queryPhrase
2962                    searchTerm = this.suggestionHover || this.queryPhrase;
2963                }
2964
2965                window.location.href = '/catalogsearch/result/?q=' + encodeURIComponent(searchTerm);
2966            },
2967
2968            buildSearch() {
2969                window.magentoStorefrontEvents.context.setSearchExtension({
2970                    version: "4.4.1"
2971                });
2972
2973                // Wait for MagentoLiveSearch to be available
2974                return new Promise((resolve) => {
2975                    const checkForMagentoLiveSearch = () => {
2976                        if (window.MagentoLiveSearch) {
2977                            resolve(new MagentoLiveSearch({
2978                                environmentId: "2cc69165-2270-494c-893f-c00d0bb35bd7",
2979                                websiteCode: "base",
2980                                storeCode: "main_website_store",
2981                                storeViewCode: "default",
2982                                apiKey: "search_gql",
2983                            }));
2984                        } else {
2985                            setTimeout(checkForMagentoLiveSearch, 100);
2986                        }
2987                    };
2988
2989                    checkForMagentoLiveSearch();
2990                });
2991
2992            },
2993
2994            // this will open the popover, whenever the search-input has focus
2995            initTogglePopover() {
2996                const popover = document.getElementById('search');
2997
2998                popover.addEventListener('focus', () => {
2999                    if (this.isQueryLengthValid()) {
3000                        this.openPopover();
3001                    } else {
3002                        this.closePopover();
3003                    }
3004                });
3005            },
3006
3007            closePopover() {
3008                this.searchOpen = false;
3009                // Restore body scroll when closing search overlay
3010                document.body.style.overflow = '';
3011            },
3012
3013            closePopup() {
3014                this.searchOpen = false;
3015                // Restore body scroll when closing search overlay
3016                document.body.style.overflow = '';
3017            },
3018
3019            openPopover() {
3020                this.searchOpen = true;
3021
3022                if (window.innerWidth <= 768) {
3023                    // Lock body scroll when opening search overlay
3024                    document.body.style.overflow = 'hidden';
3025                }
3026            },
3027
3028            handleInput() {
3029                this.queryPhrase = this.$el.value;
3030                this.suggestionHover = '';
3031                this.isSuggestionHoverMode = false;
3032
3033                if (!this.isQueryLengthValid()) {
3034                    if (this.searchOpen){
3035                        this.closePopover();
3036                    }
3037                    return;
3038                }
3039
3040                this.getProducts();
3041                this.$nextTick(() => {
3042                    this.openPopover();
3043                });
3044            },
3045
3046            showProductPrice(){
3047                return this.product.price ? hyva.formatPrice(this.product.price) : '';
3048            },
3049
3050            handleProductClick() {
3051                window.magentoStorefrontEvents.context.setSearchResults(
3052                    window.magentoStorefrontEvents.context.getSearchResults()
3053                );
3054
3055                window.magentoStorefrontEvents.publish.searchProductClick("search-bar", `${this.product.sku}`);
3056
3057                // Timeout to prevent submission before event has fired.
3058                setTimeout(() => window.location.href = this.product.url, 500);
3059            },
3060
3061            // this will submit the form with the clicked suggestion as the search-phrase
3062            searchSuggestion() {
3063                document.getElementById('search').value = this.suggestion;
3064                document.getElementById('search_mini_form').submit();
3065            },
3066
3067            showResults(){
3068                return this.liveSearchProducts.length >= 1 && this.isQueryLengthValid() || this.isSuggestionHoverMode;
3069            },
3070
3071            showSuggestions(){
3072                return this.liveSearchSuggestions.length >= 1 && this.isQueryLengthValid();
3073            },
3074
3075            isQueryLengthValid() {
3076                return this.queryPhrase.length >= this.minQueryLength;
3077            },
3078
3079            getSearchClasses() {
3080                return this.searchOpen ? 'block' : 'hidden';
3081            },
3082            getSuggestionText(suggestion) {
3083                const matches = suggestion.match(new RegExp(this.queryPhrase, 'gmi'));
3084
3085                matches.map((match) => {
3086                    suggestion = suggestion.replaceAll(match, '<b>' + match + '</b>')
3087                });
3088
3089                return suggestion;
3090            },
3091            async onSuggestionHover(suggestion) {
3092                this.isSuggestionHoverMode = true;
3093                this.suggestionHover = suggestion;
3094
3095                await this.getProducts();
3096
3097                this.queryPhrase = suggestion;
3098            },
3099            onSuggestionUnhover() {
3100                this.isSuggestionHoverMode = false;
3101                this.suggestionHover = '';
3102            },
3103            getSeeResultsText(isSuggestion = false) {
3104                const text = 'See\u0020\u0025total\u0020results\u0020for\u0020\u0022\u0025term\u0022';
3105
3106                if (isSuggestion && this.isSuggestionHoverMode) {
3107                    return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.suggestionHover);
3108                }
3109
3110                return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.queryPhrase);
3111            },
3112
3113            // get products from fetch-request and update liveSearchProducts and liveSearchSuggestions
3114            async getProducts() {
3115                this.searchOpen = true;
3116
3117                if (!this.isSuggestionHoverMode) {
3118                    this.isLoading = true;
3119                }
3120
3121                // Make sure search is initialized
3122                if (!this.searchInitialized && !this.searchInitializing) {
3123                    await this.initSearch();
3124                } else if (this.searchInitializing) {
3125                    // Wait for ongoing initialization to complete (reduced timeout)
3126                    let attempts = 0;
3127                    while (this.searchInitializing && attempts < 20) { // 2 seconds max instead of 5
3128                        await new Promise(resolve => setTimeout(resolve, 100));
3129                        attempts++;
3130                    }
3131                }
3132
3133                // If still not initialized, try to use global instance as fallback
3134                if (!this.search) {
3135                    if (window.liveSearchInstance) {
3136                        this.search = window.liveSearchInstance;
3137                        this.searchInitialized = true;
3138                    } else {
3139                        console.error('MagentoLiveSearch could not be initialized');
3140                        this.isLoading = false;
3141                        return;
3142                    }
3143                }
3144
3145                const result = await this.getLiveSearchProducts();
3146                this.isLoading = false;
3147
3148                this.liveSearchProducts = result.data.productSearch.items.map(item => ({
3149                    name: item.product.name,
3150                    price: item.product.price_range.maximum_price.regular_price.value,
3151                    currency: item.product.price_range.maximum_price.regular_price.currency,
3152                    image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
3153                    url: item.product.canonical_url,
3154                    id: item.product.id,
3155                    sku: item.product.sku
3156                }));
3157
3158                this.liveSearchSuggestions = result.data.productSearch.suggestions
3159                this.liveSearchTotalCount = result.data.productSearch.total_count;
3160
3161                //search-results-view
3162            },
3163
3164            // retrieve products from magento live search service
3165            async getLiveSearchProducts() {
3166                this.searchRequestId = Math.random().toString(16).slice(2);
3167
3168                if (!this.search) {
3169                    return {
3170                        data: {
3171                            productSearch: {
3172                                items: [],
3173                                suggestions: [],
3174                                total_count: 0,
3175                                page_info: {
3176                                    current_page: 1,
3177                                    page_size: this.pageSize
3178                                },
3179                                facets: []
3180                            }
3181                        }
3182                    };
3183                }
3184
3185                const searchQuery = this.isSuggestionHoverMode ? this.suggestionHover : this.queryPhrase;
3186
3187                const searchCtx = {
3188                    units: [{
3189                        searchUnitId: "search-bar",
3190                        queryTypes: ["products"],
3191                        phrase: searchQuery,
3192                        currentPage: 1,
3193                        pageSize: this.pageSize,
3194                        filter:[
3195                            {attribute:"visibility",in:["Search","Catalog, Search"]},
3196                            {attribute:"inStock",eq:"true"}
3197                        ],
3198                        sort: [{attribute: "relevance", direction: "DESC"}],
3199                        searchRequestId: this.searchRequestId
3200                    }]
3201                };
3202
3203                window.magentoStorefrontEvents.context.setSearchInput(searchCtx);
3204                window.magentoStorefrontEvents.publish.searchRequestSent("search-bar");
3205                const before = Date.now();
3206                let result;
3207
3208                try {
3209                    // Here we call the actual search method
3210                    result = await this.search.productSearch({
3211                        phrase: searchQuery,
3212                        page_size: this.pageSize,
3213                        sort: [{attribute: "relevance", direction: "DESC"}],
3214                        filter: [
3215                            {attribute: "visibility", in: ["Search", "Catalog, Search"]},
3216                            {attribute: "inStock", eq: "true"}
3217                        ],
3218                        current_page: 1,
3219                        data: {
3220                            products: true,
3221                            facets: true,
3222                            suggestions: true
3223                        },
3224                        context: {
3225                            customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"
3226                        }
3227                    });
3228                } catch (error) {
3229                    return { data: { productSearch: { items: [], suggestions: [], total_count: 0, page_info: { current_page: 1, page_size: this.pageSize } } } };
3230                }
3231
3232                const after = Date.now();
3233
3234                const productItems = result.data.productSearch.items || [];
3235                const suggestions = result.data.productSearch.suggestions || [];
3236                const facets = result.data.productSearch.facets || [];
3237
3238                const formattedProductItems = productItems.map((item, key) => ({
3239                    name: item.product.name,
3240                    sku: item.product.sku,
3241                    url: item.product.canonical_url,
3242                    imageUrl: item.product.image ? item.product.image.url : 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
3243                    price: item.product.price_range.minimum_price.final_price.value,
3244                    rank: key,
3245                }));
3246
3247                const formattedSuggestions = suggestions.map((item, key) => ({
3248                    suggestion: item,
3249                    rank: key,
3250                }));
3251
3252                const formattedFacets = facets.map((facet) => ({
3253                    attribute: facet.attribute,
3254                    title: facet.title,
3255                    type: facet.type || "PINNED",
3256                    buckets: facet.buckets.map((bucket) => bucket),
3257                }));
3258
3259                const searchCtxUpdated = {
3260                    units: [{
3261                        searchUnitId: "search-bar",
3262                        searchRequestId: this.searchRequestId,
3263                        executionTime: after - before,
3264                        products: formattedProductItems,
3265                        categories: [],
3266                        suggestions: this.isSuggestionHoverMode ? this.suggestions : formattedSuggestions,
3267                        page: result.data.productSearch.page_info.current_page,
3268                        perPage: result.data.productSearch.page_info.page_size,
3269                        facets: formattedFacets
3270                    }]
3271                };
3272
3273                if (this.isSuggestionHoverMode) {
3274                    this.liveSearchProducts = result.data.productSearch.items.map(item => ({
3275                        name: item.product.name,
3276                        price: item.product.price_range.maximum_price.regular_price.value,
3277                        currency: item.product.price_range.maximum_price.regular_price.currency,
3278                        image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
3279                        url: item.product.canonical_url,
3280                        id: item.product.id,
3281                        sku: item.product.sku
3282                    }));
3283                }
3284
3285                window.magentoStorefrontEvents.context.setSearchResults(searchCtxUpdated);
3286                window.magentoStorefrontEvents.publish.searchResponseReceived("search-bar");
3287
3288                return result;
3289            }
3290        })),
3291        {once: true}
3292    )
3293</script>
3293
3294                    </div>
3295                </div>
3296
3297                <a href="https://www.purdys.com/shops/" class="header-shops items-center gap-x-2 no-underline text-primary-dark hidden lg:flex hover:no-underline hover:text-primary-dark">
3298                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 24" fill="none" aria-hidden="true">
3299<path fill-rule="evenodd" clip-rule="evenodd" d="M19.847 11.7852C19.9882 10.9933 19.9999 10.4413 19.9999 10.1893V10.0453C20.0235 3.23 13.2696 -2.00149 6.10395 0.746241C2.37403 2.1861 0.00900526 5.97774 0.00900526 10.0453C-0.00276104 10.1533 -0.0380599 10.8733 0.197266 12.0132C0.199722 12.0207 0.202178 12.0277 0.204526 12.0343C0.213431 12.0597 0.220799 12.0807 0.220799 12.1091C0.267864 12.3491 0.326695 12.5771 0.397293 12.8171C0.467891 13.0571 0.550255 13.321 0.644385 13.597C1.62099 16.3327 4.05661 20.2564 9.98682 24H9.99859C15.6464 20.4363 18.1056 16.7167 19.1881 14.005C19.1881 13.981 19.1998 13.957 19.2116 13.945C19.494 13.261 19.7176 12.5411 19.847 11.7852ZM17.4037 13.0815C17.6191 12.5433 17.7811 11.9997 17.8757 11.4476L17.878 11.4341C17.9934 10.7868 17.9999 10.3569 17.9999 10.1893V10.0384C18.0188 4.58613 12.6344 0.385611 6.82215 2.61284C3.9457 3.7243 2.00901 6.71462 2.00901 10.0453V10.154L2.00075 10.2298C2.0012 10.2338 1.99618 10.3343 2.00725 10.5286C2.02013 10.755 2.05389 11.0886 2.13639 11.5113C2.15876 11.5893 2.18143 11.6842 2.19764 11.7939C2.22774 11.9356 2.26584 12.0822 2.31599 12.2526C2.37873 12.4659 2.45103 12.6977 2.53268 12.9378C3.29637 15.0685 5.20582 18.3241 9.9929 21.6102C14.464 18.5417 16.4117 15.5032 17.286 13.3736C17.3182 13.2724 17.3577 13.1748 17.4037 13.0815Z" fill="#2E1950"/>
3300<path fill-rule="evenodd" clip-rule="evenodd" d="M10 12C11.1046 12 12 11.1046 12 10C12 8.89543 11.1046 8 10 8C8.89543 8 8 8.89543 8 10C8 11.1046 8.89543 12 10 12ZM10 14C12.2091 14 14 12.2091 14 10C14 7.79086 12.2091 6 10 6C7.79086 6 6 7.79086 6 10C6 12.2091 7.79086 14 10 14Z" fill="#2E1950"/>
3301</svg>
3302                    <span class="text-sm font-bold uppercase text-primary-dark hidden xl:block">
3303                        Shops                    </span>
3304                </a>
3305
3306                <!--Customer Icon & Dropdown-->
3307                
3308<div
3309        class="header-customer relative hidden lg:inline-block"
3310        x-data="{
3311        open: false,
3312        isLoggedIn: false,
3313        customerName: ''
3314    }"
3315        @keyup.escape="open = false"
3316        @click.outside="open = false"
3317        @private-content-loaded.window="
3318        if (event.detail.data.customer && event.detail.data.customer.signin_token) {
3319            isLoggedIn = true;
3320            customerName = event.detail.data.customer.firstname || '';
3321        } else {
3322            isLoggedIn = false;
3323            customerName = '';
3324        }
3325    "
3326>
3327    <button
3328            type="button"
3329            id="customer-menu"
3330            class="block rounded !border-0 m-0 !bg-transparent !shadow-none"
3331            @click="open = !open"
3332            :aria-expanded="open ? 'true' : 'false'"
3333            aria-label="My&#x20;Account"
3334            aria-haspopup="true"
3335    >
3336        <div class="flex items-center gap-x-2">
3337            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
3338<path fill-rule="evenodd" clip-rule="evenodd" d="M12 10C14.2091 10 16 8.20914 16 6C16 3.79086 14.2091 2 12 2C9.79086 2 8 3.79086 8 6C8 8.20914 9.79086 10 12 10ZM12 12C15.3137 12 18 9.31371 18 6C18 2.68629 15.3137 0 12 0C8.68629 0 6 2.68629 6 6C6 9.31371 8.68629 12 12 12Z" fill="#2E1950"/>
3339<path fill-rule="evenodd" clip-rule="evenodd" d="M15 16H9C5.68629 16 3 18.6863 3 22H21C21 18.6863 18.3137 16 15 16ZM9 14C4.58172 14 1 17.5817 1 22V24H23V22C23 17.5817 19.4183 14 15 14H9Z" fill="#2E1950"/>
3340</svg>
3341            <span class="text-sm font-bold uppercase text-primary-dark hidden xl:block">
3342                <template x-if="isLoggedIn">
3343                    <span x-text="'Hi ' + customerName"></span>
3344                </template>
3345                <template x-if="!isLoggedIn">
3346                    <span>Sign in</span>
3347                </template>
3348            </span>
3349        </div>
3350    </button>
3351    <nav
3352            class="absolute top-full mt-2.5 max-2xl:end-0 ltr:start-1/2 rtl:end-1/2 -translate-x-1/2 z-30 w-fit"
3353            x-cloak
3354            x-show="open"
3355            x-transition:enter="transition ease-out"
3356            x-transition:enter-start="opacity-0"
3357            x-transition:enter-end="opacity-100"
3358            x-transition:leave="transition ease-in"
3359            x-transition:leave-start="opacity-100"
3360            x-transition:leave-end="opacity-0"
3361            aria-labelledby="customer-menu"
3362    >
3363        <div class="bg-transparent w-full flex justify-center">
3364            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="12" viewBox="0 0 18 12" fill="none" class="text-white" role="img">
3365    <path d="M9.98882 0.503861C9.52814 -0.167954 8.3657 -0.167954 7.90503 0.503861L0 12H18L9.98882 0.503861Z" fill="currentColor"/>
3366<title>tooltip-indicator</title></svg>
3367        </div>
3368        <div class="relative">
3369            <div class="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-full w-0 h-0 border-l-[9px] border-l-transparent border-r-[9px] border-r-transparent border-b-[12px] border-b-primary"></div>
3370            <div class="customer-popup bg-white border-t border-primary shadow-[0_8px_24px_-8px_rgba(20,20,20,0.25)] py-2">
3371                                    
3372<a id="customer.header.sign.in.link"
3373   x-data="{}"
3374   @click="$store.device.isDesktop ? ($event.preventDefault(), $dispatch('open-auth-modal', { tab: 'login' })) : null"
3375   :href="$store.device.isDesktop ? '#' : 'https://www.purdys.com/customer/account/login/'"
3376   title="Sign&#x20;In"
3377>
3378    Sign In</a>
3379
3380    <a id="customer.header.register.link"
3381       x-data="{}"
3382       @click="$store.device.isDesktop ? ($event.preventDefault(), $dispatch('open-auth-modal', { tab: 'register' })) : null"
3383       :href="$store.device.isDesktop ? '#' : 'https://www.purdys.com/customer/account/create/'"
3384       title="Create&#x20;an&#x20;Account"
3385    >
3386        Create an Account    </a>
3387                            </div>
3388
3389        </div>
3390    </nav>
3391</div>
3392                <button
3393                        class="lg:hidden relative outline-none border-0 bg-transparent hover:bg-transparent hover:border-0"
3394                        @click="toggleSearch()"
3395                        title="Search"
3396                        :aria-expanded="searchOpen"
3397                        aria-haspopup="dialog">
3398                    <span class="sr-only label">
3399                        Toggle search                    </span>
3400                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="[&amp;_path]:fill-primary-dark" aria-hidden="true">
3401<path fill-rule="evenodd" clip-rule="evenodd" d="M8.75049 1.49969C4.74642 1.49969 1.50049 4.74563 1.50049 8.74969C1.50049 12.7538 4.74642 15.9997 8.75049 15.9997C12.7546 15.9997 16.0005 12.7538 16.0005 8.74969C16.0005 4.74563 12.7546 1.49969 8.75049 1.49969ZM0.000488281 8.74969C0.000488281 3.9172 3.918 -0.000305176 8.75049 -0.000305176C13.583 -0.000305176 17.5005 3.9172 17.5005 8.74969C17.5005 13.5822 13.583 17.4997 8.75049 17.4997C3.918 17.4997 0.000488281 13.5822 0.000488281 8.74969Z" fill="white"/>
3402<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4001 14.3993C14.7108 14.0887 15.2144 14.0887 15.5251 14.3993L19.7675 18.6418C20.0781 18.9524 20.0781 19.4561 19.7675 19.7667C19.4569 20.0774 18.9532 20.0774 18.6426 19.7667L14.4001 15.5243C14.0895 15.2136 14.0895 14.71 14.4001 14.3993Z" fill="white"/>
3403</svg>
3404                </button>
3405
3406                
3407                <!--Cart Icon-->
3408                                    <button
3409                                        id="menu-cart-icon"
3410                        class="relative outline-none border-0 hover:bg-transparent hover:border-0 focus:bg-transparent focus:border-0"
3411                        x-ref="cartButton"
3412                        :aria-disabled="isCartEmpty()"
3413                        title="Cart"
3414                                            @click.prevent.stop="() => {
3415                        $dispatch('toggle-cart', { isOpen: true })
3416                    }"
3417                        @toggle-cart.window="toggleCart($event)"
3418                        :aria-expanded="isCartOpen"
3419                        aria-haspopup="dialog"
3420                    >
3421                        <span
3422                                class="sr-only label"
3423                                x-text="`
3424                        Toggle minicart,
3425                        ${isCartEmpty() ?
3426                        'Cart is empty' :
3427                        hyva.str(
3428                            'You\u0020have\u0020\u00251\u0020product\u00252\u0020in\u0020your\u0020cart.',
3429                            cart.summary_count,
3430                            cart.summary_count === 1 ? '' : 's'
3431                        )}`
3432                    ">
3433                        </span>
3434
3435                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" role="img">
3436<path fill-rule="evenodd" clip-rule="evenodd" d="M2 8V20C2 21.1046 2.89543 22 4 22H20C21.1046 22 22 21.1046 22 20V8H2ZM1 6C0.447715 6 0 6.44772 0 7V20C0 22.2091 1.79086 24 4 24H20C22.2091 24 24 22.2091 24 20V7C24 6.44771 23.5523 6 23 6H1Z" fill="#2E1950"/>
3437<path fill-rule="evenodd" clip-rule="evenodd" d="M16 11C15.4477 11 15 10.5523 15 10L15 5C15 3.34314 13.6569 2 12 2C10.3431 2 9 3.34315 9 5L9 10C9 10.5523 8.55229 11 8 11C7.44772 11 7 10.5523 7 10L7 5C7 2.23858 9.23857 2.41411e-07 12 0C14.7614 -2.41411e-07 17 2.23858 17 5V10C17 10.5523 16.5523 11 16 11Z" fill="#2E1950"/>
3438<title>bag</title></svg>
3439
3440                    <span
3441                            x-text="cart.summary_count"
3442                            x-show="!isCartEmpty()"
3443                            x-cloak
3444                            class="
3445                                absolute top-0 end-0 px-0.5 h-6 w-6 -mt-5 -mr-3 flex justify-center items-center text-xs font-bold
3446                                leading-none text-center text-white uppercase transform
3447                                translate-y-1/2 rounded-full bg-primary-dark
3448                                border-2 border-white
3449                            "
3450                            aria-hidden="true"></span>
3451                                            </button>
3452                    
3453                <!-- Mobile menu -->
3454                <div class="min-w-6 z-30 lg:hidden">
3455                    
3456    
3456<script>
3457        'use strict';
3458    </script>
3458
3459        
3459<script>
3460        const menuData_6ab638176cfc6 = [{"id":"2263","title":"Fall","url":"https:\/\/www.purdys.com\/fall","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2331","title":"Discover Thanksgiving","url":"https:\/\/www.purdys.com\/fall-gift-ideas","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"3773","title":"Discover Halloween","url":"https:\/\/www.purdys.com\/halloween-gift-ideas","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"3769","title":"Maritimes Collection","url":"https:\/\/www.purdys.com\/share-joy-share-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"3752","title":"Ice Cream & Ice Cream Bars","url":"https:\/\/www.purdys.com\/ice-cream","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2266","title":"Canadian Souvenirs","url":"https:\/\/www.purdys.com\/gifts\/canadian-collection","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2281","title":"Product Type","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2284","title":"Boxed Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/boxed-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2287","title":"Gift Baskets and Sets","url":"https:\/\/www.purdys.com\/gifts\/gift-baskets-and-sets","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2290","title":"Mix and Match Chocolates","url":"https:\/\/www.purdys.com\/chocolate\/mix-and-match-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"2293","title":"By Price","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2296","title":"under $20","url":"https:\/\/www.purdys.com\/fall\/fall-low","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2299","title":"$20 to $50","url":"https:\/\/www.purdys.com\/fall\/fall-medium","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2302","title":"Over $50","url":"https:\/\/www.purdys.com\/fall\/over-50","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"2305","title":"Others","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2308","title":"Build-a-box","url":"https:\/\/www.purdys.com\/build-a-box","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2311","title":"Shipping and Delivery","url":"https:\/\/www.purdys.com\/shipping-gift-guarantee","classes":null,"hasChildren":false,"image":null,"children":[]}]}]},{"id":"1811","title":"Chocolate","url":"https:\/\/www.purdys.com\/chocolate","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2155","title":"Canadian Souvenirs","url":"https:\/\/www.purdys.com\/gifts\/canadian-collection","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1817","title":"Boxed Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/boxed-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2066","title":"Gift Baskets","url":"https:\/\/www.purdys.com\/gifts\/gift-baskets-and-sets","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1820","title":"Build-a-Box","url":"https:\/\/www.purdys.com\/build-a-box","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1829","title":"Free Shipping ","url":"https:\/\/www.purdys.com\/chocolate\/send-chocolates-free-shipping","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1832","title":"Online Exclusive","url":"https:\/\/www.purdys.com\/chocolate\/online-exclusive-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1838","title":"Bestsellers","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1841","title":"All Bestsellers","url":"https:\/\/www.purdys.com\/chocolate\/bestsellers","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1844","title":"Sweet Georgia Browns","url":"https:\/\/www.purdys.com\/chocolate\/chocolate-sweet-georgia-browns","classes":null,"hasChildren":false,"image":null,"children":[]}
3460,{"id":"1847","title":"Hedgehogs","url":"https:\/\/www.purdys.com\/chocolate\/chocolate-hedgehogs","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1850","title":"Himalayan Pink Salt Caramels","url":"https:\/\/www.purdys.com\/chocolate\/salted-caramel-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1853","title":"CHOCOLATE TYPE","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1856","title":"Plant-based Chocolate","url":"https:\/\/www.purdys.com\/plant-based-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1865","title":"Dark Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/dark-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1868","title":"Milk Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/milk-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1871","title":"White Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/white-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1862","title":"No Sugar Added","url":"https:\/\/www.purdys.com\/chocolate\/no-sugar-added","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1859","title":"Fruit Flavours","url":"https:\/\/www.purdys.com\/chocolate\/fruit-flavoured-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1874","title":"COLLECTIONS","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1877","title":"Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/see-all","classes":"menu-second-column","hasChildren":false,"image":null,"children":[]},{"id":"1880","title":"Bars and Snacks","url":"https:\/\/www.purdys.com\/chocolate\/chocolate-bars-snacks","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1883","title":"Mint Chocolates","url":"https:\/\/www.purdys.com\/chocolate\/mint-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1886","title":"Nuts and Caramels","url":"https:\/\/www.purdys.com\/chocolate\/nuts-and-caramels","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1889","title":"Assorted Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/assorted-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1892","title":"Peanut Butter","url":"https:\/\/www.purdys.com\/chocolate\/peanut-butter","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1895","title":"Fruits, Ginger and Spices","url":"https:\/\/www.purdys.com\/chocolate\/fruits-ginger-and-spices","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1898","title":"Chocolate Truffles","url":"https:\/\/www.purdys.com\/chocolate\/chocolate-truffles","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1901","title":"Chocolate Bark, Brittle and Toffee","url":"https:\/\/www.purdys.com\/chocolate\/brittle-bark-and-toffee","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1904","title":"From The Chocolate Kitchen","url":"https:\/\/www.purdys.com\/chocolate\/from-the-chocolate-kitchen","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1907","title":"Chocolate Favours","url":"https:\/\/www.purdys.com\/gifts\/chocolate-favours","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1913","title":"Kosher Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/kosher","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1916","title":"SALE & SPECIALS","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1919","title":"Special Offers","url":"https:\/\/www.purdys.com\/chocolate\/special-offers","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1922","title":"Bulk Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/bulk-chocolate","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1925","title":"Mix and Match 3 for $11.75","url":"https:\/\/www.purdys.com\/chocolate\/mix-match-low","classes":null,"hasChildren":false,"image":null,"children":[]}
3460,{"id":"1928","title":"Mix and Match 3 for $12.50","url":"https:\/\/www.purdys.com\/chocolate\/mix-match-medium","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1931","title":"Mix and Match 3 for $23","url":"https:\/\/www.purdys.com\/chocolate\/mix-match-high","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1934","title":"OTHER","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2343","title":"Ice Cream","url":"https:\/\/www.purdys.com\/ice-cream","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1937","title":"Chocolate Legend ","url":"https:\/\/www.purdys.com\/chocolate-legend","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1940","title":"New","url":"https:\/\/www.purdys.com\/chocolate\/new","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1943","title":"Shipping Deadlines","url":"https:\/\/www.purdys.com\/shipping-gift-guarantee","classes":null,"hasChildren":false,"image":null,"children":[]}]}]},{"id":"1301","title":"Gifts","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2158","title":"Thanksgiving Gifts Ideas","url":"https:\/\/www.purdys.com\/fall-gift-ideas","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"3776","title":"Halloween Gift Ideas","url":"https:\/\/www.purdys.com\/halloween-gift-ideas","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1322","title":"Canadian Souvenirs","url":"https:\/\/www.purdys.com\/canadian-souvenirs","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1539","title":"Build-a-Box","url":"https:\/\/www.purdys.com\/build-a-box","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"2078","title":"Chocolate Covered Dates","url":"https:\/\/www.purdys.com\/chocolate-covered-dates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1334","title":"By Occasion","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1337","title":"Birthday Gifts","url":"https:\/\/www.purdys.com\/gifts\/birthday","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1340","title":"Thank You Gifts","url":"https:\/\/www.purdys.com\/gifts\/thank-you","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1343","title":"See All Gifts","url":"https:\/\/www.purdys.com\/gifts\/see-all-gifts","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1346","title":"Anniversary Gifts","url":"https:\/\/www.purdys.com\/gifts\/anniversary","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1352","title":"Guide to Purdys Wedding Favours","url":"https:\/\/www.purdys.com\/discover\/wedding-bridal-favours","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1361","title":"Product Type","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1364","title":"Gift Baskets and Sets","url":"https:\/\/www.purdys.com\/gifts\/gift-baskets-and-sets","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1367","title":"Gift Boxes","url":"https:\/\/www.purdys.com\/chocolate\/boxed-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1370","title":"Gift Card ","url":"https:\/\/www.purdys.com\/gift-cards","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1373","title":"Vegan Gifts","url":"https:\/\/www.purdys.com\/vegan","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1519","title":"Kosher Chocolate","url":"https:\/\/www.purdys.com\/chocolate\/kosher","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1376","title":"Corporate Gifts ","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1379","title":"Corporate Gifts","url":"https:\/\/www.purdys.com\/corporate-gifts","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1382","title":"Employee Gifts and Snacks","url":"https:\/\/www.purdys.com\/gifts\/employee-gifts","classes":null,"hasChildren":false,"image":null,"children":[]}
3460,{"id":"1991","title":"Branded Corporate Gifts","url":"https:\/\/www.purdys.com\/corporate-gifting","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1385","title":"By Price","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1388","title":"Gift Under 20","url":"https:\/\/www.purdys.com\/gifts\/gifts-low","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1391","title":"Gifts $20 to $50","url":"https:\/\/www.purdys.com\/gifts\/gifts-medium","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1394","title":"Gifts Over $50","url":"https:\/\/www.purdys.com\/gifts\/gifts-high","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1397","title":"Other","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2346","title":"Ice Cream","url":"https:\/\/www.purdys.com\/ice-cream","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1400","title":"Online Exclusive","url":"https:\/\/www.purdys.com\/chocolate\/online-exclusive-chocolates","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1403","title":"Chocolate Legend ","url":"https:\/\/www.purdys.com\/chocolate-legend","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1406","title":"Shipping and Delivery","url":"#","classes":null,"hasChildren":false,"image":null,"children":[]}]}]},{"id":"1199","title":"Custom","url":"https:\/\/www.purdys.com\/custom","classes":"custom","hasChildren":true,"image":null,"children":[{"id":"1542","title":"Build-a-Box","url":"https:\/\/www.purdys.com\/build-a-box","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1205","title":"Custom Corporate Gifts ","url":"https:\/\/www.purdys.com\/corporate-gifting","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1208","title":"Wedding & Anniversaries","url":"https:\/\/www.purdys.com\/wedding-and-bridal-favours","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1220","title":"Discover","url":"https:\/\/www.purdys.com\/discover","classes":null,"hasChildren":true,"image":null,"children":[{"id":"2349","title":"Ice Cream","url":"https:\/\/www.purdys.com\/ice-cream","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1223","title":"Purdys Blog","url":"https:\/\/www.purdys.com\/blog.html","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1226","title":"Purple Partnerships","url":"https:\/\/www.purdys.com\/discover\/purple-partnerships","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1229","title":"Shipping Deadlines","url":"https:\/\/www.purdys.com\/shipping-gift-guarantee","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1232","title":"Sustainability","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1235","title":"Purdys' Sustainable Cocoa Program","url":"https:\/\/www.purdys.com\/sustainable-cocoa","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1238","title":"Sustainable Farms","url":"https:\/\/www.purdys.com\/sustainable-farms","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1241","title":"Sustainable Living","url":"https:\/\/www.purdys.com\/sustainable-living","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1244","title":"Clean Water Project","url":"https:\/\/www.purdys.com\/clean-water-project","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1247","title":"Corporate Gifts ","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1250","title":"Corporate Gifts Guides","url":"https:\/\/www.purdys.com\/corporate-gifts","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1253","title":"Branded Corporate Gifts","url":"https:\/\/www.purdys.com\/corporate-gifting","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1256","title":"Our Stories","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1259","title":"About Us","url":"https:\/\/www.purdys.com\/discover\/about-us","classes":null,"hasChildren":false,"image":null,"children":[]}
3460,{"id":"1262","title":"Purdys Heritage","url":"https:\/\/www.purdys.com\/discover\/purdys-heritage","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1265","title":"Tips & Guides","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1268","title":"Is Chocolate Vegan","url":"https:\/\/www.purdys.com\/blog\/is-chocolate-vegan-your-guide-to-vegan-chocolate.html","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1271","title":"The Tasty Art of Giving","url":"https:\/\/www.purdys.com\/blog\/celebrate-with-the-perfect-chocolate-gifts.html","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1274","title":"Guide to Purdys Wedding Favours","url":"https:\/\/www.purdys.com\/wedding-and-bridal-favours","classes":null,"hasChildren":false,"image":null,"children":[]}]},{"id":"1277","title":"Marketing & Tasting","url":"#","classes":null,"hasChildren":true,"image":null,"children":[{"id":"1280","title":"Chocolate Legend","url":"https:\/\/www.purdys.com\/discover\/chocolate-legend","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1283","title":"Wine and Chocolate Pairings","url":"https:\/\/www.purdys.com\/discover\/wine-and-chocolate-pairings","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1286","title":"Recipes","url":"https:\/\/www.purdys.com\/discover\/recipes","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1289","title":"Gift Ideas","url":"https:\/\/www.purdys.com\/discover\/gift-ideas","classes":null,"hasChildren":false,"image":null,"children":[]},{"id":"1292","title":"Blog","url":"https:\/\/www.purdys.com\/blog.html","classes":null,"hasChildren":false,"image":null,"children":[]}]}]}];
3461        const initSlidingMenu_6ab638176cfc6 = () => ({
3462            open: false,
3463            stack: [{ title: '', nodes: menuData_6ab638176cfc6 }],
3464            openMenu() {
3465                this.open = true;
3466                this.stack = [{ title: '', nodes: menuData_6ab638176cfc6 }];
3467                this.$nextTick(() => hyva.trapFocus(this.$refs['menu-dialog']));
3468                document.body.classList.add('fixed', 'w-full');
3469            },
3470            closeMenu() {
3471                document.body.classList.remove('fixed', 'w-full');
3472                this.open = false;
3473                this.$nextTick(() => this.$refs['open-menu-button'].focus() || hyva.releaseFocus());
3474            },
3475            goTo(node) {
3476                this.stack.push({ title: node.title, nodes: node.children });
3477            },
3478            goBack() {
3479                if (this.stack.length > 1) this.stack.pop();
3480            },
3481            getLeafNodes(nodes) {
3482                return nodes.filter(n => !n.hasChildren);
3483            },
3484            getParentNodes(nodes) {
3485                return nodes.filter(n => n.hasChildren);
3486            }
3487        });
3488    </script>
3488
3489
3490    <nav
3491            class="snowdog-topmenu-mobile z-20 order-2 text-primary-dark sm:order-1 navigation bg-transparent lg:hidden"
3492            x-data="initSlidingMenu_6ab638176cfc6()"
3493            @keydown.escape="open && closeMenu()"
3494            @click.outside="open && closeMenu()"
3495            aria-label="Main&#x20;menu"
3496            role="navigation"
3497    >
3498        <button x-ref="open-menu-button"
3499                @click="openMenu()"
3500                type="button"
3501                aria-label="Open&#x20;menu"
3502                class="bg-transparent border-0 hover:border-0 hover:bg-transparent focus:bg-transparent focus:border-0
3503                       active:bg-transparent active:border-0"
3504                :aria-expanded="open"
3505                aria-haspopup="menu"
3506        >
3507            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
3508<path d="M1 4H23" stroke="#2E1950" stroke-width="2" stroke-linecap="round"/>
3509<path d="M1 20H23" stroke="#2E1950" stroke-width="2" stroke-linecap="round"/>
3510<path d="M1 12H23" stroke="#2E1950" stroke-width="2" stroke-linecap="round"/>
3511</svg>
3512        </button>
3513        <div class="fixed inset-0 bg-black/50 z-40" x-show="open" x-transition.opacity @click="closeMenu()" x-cloak></div>
3514        <div
3515                class="fixed z-50 top-0 left-0 w-full h-full shadow-2xl overflow-hidden transition-transform duration-300 bg-black bg-opacity-25"
3516                :class="{ '-translate-x-full': !open, 'translate-x-0': open }"
3517                x-cloak
3518                x-ref="menu-dialog"
3519                role="dialog"
3520                aria-modal="true"
3521                aria-label="Main&#x20;menu"
3522                :aria-hidden="open ? 'false' : 'true'"
3523        >
3524            <template x-for="(panel, idx) in stack" :key="idx">
3525                <div
3526                        class="absolute top-0 left-0 w-full bg-white transition-transform duration-300 flex flex-col h-full"
3527                        :class="{ 'translate-x-0': idx === stack.length - 1, 'translate-x-full': idx < stack.length - 1 }"
3528                        x-show="idx === stack.length - 1"
3529                >
3530                    <div class="flex items-center justify-between px-4 py-[15p
3530x] bg-white flex-shrink-0 h-[52px]">
3531                        <template x-if="stack.length > 1">
3532                            <button @click="goBack()" aria-label="Back" class="border-0">
3533                                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20 20" fill="none" class="rotate-90" aria-hidden="true">
3534<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3535</svg>
3536                            </button>
3537                        </template>
3538                        <template x-if="stack.length === 1">
3539                            <div class="flex-1 flex justify-center">
3540                                <!-- Search bar from header.phtml -->
3541                                <div class="w-full">
3542                                    <div x-data="initMobileLiveSearch()"
3543     x-init="initPopover"
3544     @close-search.window="closePopover"
3545     @open-search.window="openPopover"
3546     @keydown.escape="closePopover"
3547>
3548    <form
3549        class="form minisearch w-full flex items-center"
3550        id="search_mini_form_menu"
3551        action="https://www.purdys.com/catalogsearch/result/"
3552        method="get"
3553        role="search">
3554        <label class="sr-only" for="search-menu" data-role="minisearch-label">
3555            <span>Search</span>
3556        </label>
3557        <div class="flex items-center flex-1">
3558            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" class="mr-3 [&amp;&gt;path]:fill-black" aria-hidden="true">
3559<path fill-rule="evenodd" clip-rule="evenodd" d="M8.75049 1.49969C4.74642 1.49969 1.50049 4.74563 1.50049 8.74969C1.50049 12.7538 4.74642 15.9997 8.75049 15.9997C12.7546 15.9997 16.0005 12.7538 16.0005 8.74969C16.0005 4.74563 12.7546 1.49969 8.75049 1.49969ZM0.000488281 8.74969C0.000488281 3.9172 3.918 -0.000305176 8.75049 -0.000305176C13.583 -0.000305176 17.5005 3.9172 17.5005 8.74969C17.5005 13.5822 13.583 17.4997 8.75049 17.4997C3.918 17.4997 0.000488281 13.5822 0.000488281 8.74969Z" fill="white"/>
3560<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4001 14.3993C14.7108 14.0887 15.2144 14.0887 15.5251 14.3993L19.7675 18.6418C20.0781 18.9524 20.0781 19.4561 19.7675 19.7667C19.4569 20.0774 18.9532 20.0774 18.6426 19.7667L14.4001 15.5243C14.0895 15.2136 14.0895 14.71 14.4001 14.3993Z" fill="white"/>
3561</svg>
3562            <input id="search-menu"
3563                type="search"
3564                autocomplete="off"
3565                name="q"
3566                :value="queryPhrase"
3567                value=""
3568                placeholder="Search..."
3569                maxlength="128"
3570                class="flex-1 bg-transparent !border-0 outline-none !text-base text-gray-900 placeholder-gray-400 !p-0"
3571                role="combobox"
3572                aria-haspopup="false"
3573                aria-autocomplete="both"
3574                aria-expanded="false"
3575                x-ref="searchRef"
3576                @input="handleInput"
3577                @click.away="closePopover" />
3578        </div>
3579        <button
3580            @click.prevent="clearInput"
3581            x-cloak
3582            x-show="queryPhrase !== ''"
3583            title="Clear"
3584            class="flex items-center justify-center w-6 h-6 body-1 text-primary font-bold underline mr-3 !border-0"
3585            aria-label="Clear">
3586            <span>Clear</span>
3587        </button>
3588    </form>
3589
3590    <div x-show="searchOpen"
3591         class="bg-black opacity-[0.6] fixed w-[100vw] h-[100vh] left-0 mt-[18px] z-20"
3592         style="display: none;"
3593         @click="closePopup"></div>
3594    <section
3595      x-show="searchOpen"
3596      class="livesearch-overlay search-autocomplete overflow-y-scroll !h-[calc(100dvh-52px)] !top-[52px] !mt-0 !left-0"
3597      :class="getSearchClasses"
3598      style="display: none;"
3599      aria-label="Search&#x20;Suggestions"
3600      x-transition:enter='transition-all duration-300 ease-out'
3601      x-transition:enter-start='opacity-0'
3602      x-transition:enter-end='opacity-100'
3603      x-transition:leave='transition-all duration-200 ease-in'
3604      x-transition:leave-start='opacity-100'
3605      x-transition:leave-end='opacity-0'
3606    >
3607        <!-- No Results Header -->
3608        <template x-if="showResults && !liveSearchTotalCount && !isLoading">
3609            <div class="max-w-[1660px] mx-auto px-4 md:px-0">
3610                <div class="flex items-center justify-between">
3611                    <h3 class="font-bold text-xl md:text-3xl !m-0"
3612                        x-text="'No\u0020results\u0020found\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
3613                    <a href="#" @click.prevent='closePopup'>
3614                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
3615<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
3616<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
3617<title>x</title></svg>
3618                    </a>
3619                </div>
3620                <p class="pt-3">
3620We can't find any item matching your search. Please try another search.</p>
3621            </div>
3622        </template>
3623        <!-- Results Header -->
3624        <template x-if="showResults">
3625            <div class="flex items-center px-4 md:px-0 justify-between max-w-[1660px] mx-auto ">
3626                <h3 class="font-bold text-xl md:text-3xl !m-0" x-text="'Search\u0020results\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
3627                <a href="#" @click.prevent='closePopup'>
3628                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
3629<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
3630<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
3631<title>x</title></svg>
3632                </a>
3633            </div>
3634        </template>
3635        <div x-show="liveSearchTotalCount && !isLoading" class="livesearch-overlay-content"
3636             x-transition:enter='transition-all duration-300 ease-out'
3637             x-transition:enter-start='opacity-0'
3638             x-transition:enter-end='opacity-100'
3639             x-transition:leave='transition-all duration-200 ease-in'
3640             x-transition:leave-start='opacity-100'
3641             x-transition:leave-end='opacity-0'>
3642            <template x-if="showSuggestions">
3643                <div class="flex flex-col md:max-h-[393px]">
3644                    <p class="text-lg pb-[10px] border-b border-grey-muted">
3645                        <strong>
3646                            Suggestions                        </strong>
3647                    </p>
3648                    <ul class="m-0 space-y-1" role="list">
3649                        <template x-for="suggestion in liveSearchSuggestions">
3650                            <li class="before:hidden pl-0">
3651                                <button
3652                                  x-html="getSuggestionText(suggestion)"
3653                                  @click="searchSuggestion"
3654                                  @mouseenter="onSuggestionHover(suggestion)"
3655                                  type="button"
3656                                  class="w-full py-2 text-left hover:text-primary-hover hover:underline hover:cursor-pointer capitalize"
3657                                ></button>
3658                            </li>
3659                        </template>
3660                    </ul>
3661                    <div class="pt-3 md:pt-5 mt-auto pb-2.5 md:pb-0">
3662                        <a href='#' @click.prevent="redirectToSearchPage()" class='flex gap-1 items-center !text-primary !underline'>
3663                            <span x-text="getSeeResultsText()"></span>
3664                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
3665  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
3666</svg>
3667                        </a>
3668                    </div>
3669                </div>
3670            </template>
3671            <template x-if="showResults">
3672                <div class="lg:col-span-2">
3673                    <p class="text-lg pb-[10px] border-b-[1px] border-grey-muted">
3674                        <strong>
3675                            Product Suggestions                        </strong>
3676                    </p>
3677                    <ul class="livesearch-overlay-content-products" role="list">
3678                        <template x-for="product in liveSearchProducts">
3679                            <li class="before:hidden pl-0">
3680                                <button
3681                                  class="w-full flex gap-4 text-left cursor-pointer product-suggestion-button"
3682                                  @click="handleProductClick"
3683                                >
3684                                    <img
3685                                      :src="product.image"
3686                                      :alt="product.name"
3687                                      width="80"
3688                                      height="80"
3689                                      class="w-[80px] h-[80px] shrink-0 object-contain"
3690                                    >
3691                                    <div class="flex flex-col justify-center w-full">
3692                                        <div class="flex flex-row justify-between gap-6">
3693                                            <p><strong class="product-name max-w-[287px]" x-text="product.name"></strong></p>
3694                                            <template x-if="product.price">
3695                                                <p class="font-bold" x-text="showProductPrice"></p>
3696                                            </template>
3697                                        </div>
3698                                    </div>
3699                                </button>
3700                            </li>
3701                        </template>
3702                    </ul>
3703                    <div class="pt-5">
3704                        <a href="#" @click="redirectToSearchPage(true)" class="flex gap-1 items-center !text-primary !underline">
3705                            <span x-text="getSeeResultsText(true)"></span>
3706                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
3707  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
3708</svg>
3709                        </a>
3710                    </div>
3711                </div>
3712            </template>
3713        </div>
3714    </section>
3715</div>
3716
3717<script>
3718    'use strict';
3719    
3720    function initMobileLiveSearch() {
3721        return {
3722            queryPhrase: '',
3723            liveSearchProducts: [],
3724            liveSearchSuggestions: [],
3725            liveSearchTotalCount: 0,
3726            isLoading: false,
3727            minQueryLength: 3,
3728            pageSize: 8,
3729            searchOpen: false,
3730            search: null,
3731            isSuggestionHoverMode: false,
3732            suggestionHover: '',
3733            searchRequestId: null,
3734            searchId: "2cc69165-2270-494c-893f-c00d0bb35bd7_" +
3735              "base_" +
3736              "main_website_store_" +
3737              "default",
3738
3739            initPopover() {
3740                this.search = this.buildSearch();
3741                this.initTogglePopover();
3742
3743                const self = this;
3744
3745                window.addEventListener('open-search-popup', function (event) {
3746                    if (self.liveSearchTotalCount > 0) {
3747                        self.openPopover();
3748                    }
3749                });
3750            },
3751
3752            clearInput() {
3753                this.$refs.searchRef.value = '';
3754                this.liveSearchProducts = [];
3755                this.liveSearchSuggestions = [];
3756                this.liveSearchTotalCount = 0;
3757                this.queryPhrase = '';
3758
3759                this.closePopover();
3760            },
3761
3762            redirectToSearchPage(isSuggestion = false) {
3763                window.location.href = '/catalogsearch/result/?q=' + (isSuggestion ? this.suggestionHover.replaceAll(' ', '+') : this.queryPhrase);
3764            },
3765
3766            buildSearch() {
3767                window.magentoStorefrontEvents.context.setSearchExtension({
3768                    version: "4.4.1"
3769                });
3770                return new MagentoLiveSearch({
3771                    environmentId: "2cc69165-2270-494c-893f-c00d0bb35bd7",
3772                    websiteCode: "base",
3773                    storeCode: "main_website_store",
3774                    storeViewCode: "default",
3775                    apiKey: "search_gql",
3776                });
3777            },
3778
3779            // this will open the popover, whenever the search-input has focus
3780            initTogglePopover() {
3781                const popover = document.getElementById('search-menu');
3782
3783                if (popover) {
3784                    popover.addEventListener('focus', () => {
3785                        if (this.isQueryLengthValid()) {
3786                            this.openPopover();
3787                        } else {
3788                            this.closePopover();
3789                        }
3790                    });
3791                }
3792            },
3793
3794            closePopover() {
3795                this.searchOpen = false;
3796                // Restore body scroll when closing search overlay
3797                document.body.style.overflow = '';
3798            },
3799
3800            closePopup() {
3801                this.searchOpen = false;
3802                // Restore body scroll when closing search overlay
3803                document.body.style.overflow = '';
3804            },
3805
3806            openPopover() {
3807                this.searchOpen = true;
3808                // Lock body scroll when opening search overlay
3809                document.body.style.overflow = 'hidden';
3810            },
3811
3812            handleInput() {
3813                this.queryPhrase = this.$refs.searchRef.value;
3814                this.suggestionHover = '';
3815                this.isSuggestionHoverMode = false;
3816
3817                if (!this.isQueryLengthValid()) {
3818                    if (this.searchOpen){
3819                        this.closePopover();
3820                    }
3821                    return;
3822                }
3823
3824                this.getProducts();
3825                this.$nextTick(() => {
3826                    this.openPopover();
3827                });
3828            },
3829
3830            showProductPrice(){
3831                return this.product.price ? hyva.formatPrice(this.product.price) : '';
3832            },
3833
3834            handleProductClick() {
3835                window.magentoStorefrontEvents.context.setSearchResults(
3836                  window.magentoStorefrontEvents.context.getSearchResults()
3837                );
3838
3839                window.magentoStorefrontEvents.publish.searchProductClick("search-bar", `${this.product.sku}`);
3840
3841                // Timeout to prevent submission before event has fired.
3842                setTimeout(() => window.location.href = this.product.url, 500);
3843            },
3844
3845            // this will submit the form with the clicked suggestion as the search-phrase
3846            searchSuggestion() {
3847                document.getElementById('search-menu').value = this.suggestion;
3848                document.getElementById('search_mini_form_menu').submit();
3849            },
3850
3851            showResults(){
3852                return this.liveSearchProducts.length >= 1 && this.isQueryLengthValid() || this.isSuggestionHoverMode;
3853            },
3854
3855            showSuggestions(){
3856                return this.liveSearchSuggestions.length >= 1 && this.isQueryLengthValid();
3857            },
3858
3859            isQueryLengthValid() {
3860                return this.queryPhrase.length >= this.minQueryLength;
3861            },
3862
3863            getSearchClasses() {
3864                return this.searchOpen ? 'block' : 'hidden';
3865            },
3866            
3867            getSuggestionText(suggestion) {
3868                const matches = suggestion.match(new RegExp(this.queryPhrase, 'gmi'));
3869
3870                if (matches) {
3871                    matches.map((match) => {
3872                        suggestion = suggestion.replaceAll(match, '<b>' + match + '</b>')
3873                    });
3874                }
3875
3876                return suggestion;
3877            },
3878            
3879            async onSuggestionHover(suggestion) {
3880                  this.isSuggestionHoverMode = true;
3881                  this.suggestionHover = suggestion;
3882
3883                  await this.getProducts();
3884
3885                  this.queryPhrase = suggestion;
3886            },
3887            
3888            onSuggestionUnhover() {
3889                this.isSuggestionHoverMode = false;
3890                this.suggestionHover = '';
3891            },
3892            
3893            getSeeResultsText(isSuggestion = false) {
3894                const text = 'See\u0020\u0025total\u0020results\u0020for\u0020\u0022\u0025term\u0022';
3895
3896                if (isSuggestion && this.isSuggestionHoverMode) {
3897                    return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.suggestionHover);
3898                }
3899
3900                return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.queryPhrase);
3901            },
3902
3903            // get products from fetch-request and update liveSearchProducts and liveSearchSuggestions
3904            async getProducts() {
3905                this.searchOpen = true;
3906
3907                if (!this.isSuggestionHoverMode) {
3908                    this.isLoading = true;
3909                }
3910
3911                const result = await this.getLiveSearchProducts();
3912
3913                this.isLoading = false;
3914
3915                this.liveSearchProducts = result.data.productSearch.items.map(item => ({
3916                    name: item.product.name,
3917                    price: item.product.price_range.maximum_price.regular_price.value,
3918                    currency: item.product.price_range.maximum_price.regular_price.currency,
3919                    image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
3920                    url: item.product.canonical_url,
3921                    id: item.product.id,
3922                    sku: item.product.sku
3923                }));
3924
3925                this.liveSearchSuggestions = result.data.productSearch.suggestions
3926                this.liveSearchTotalCount = result.data.productSearch.total_count;
3927
3928                //search-results-view
3929            },
3930
3931            // retrieve products from magento live search service
3932            async getLiveSearchProducts() {
3933                this.searchRequestId = Math.random().toString(16).slice(2);
3934
3935                if (!this.search) {
3936                    return {
3937                        data: {
3938                            productSearch: {
3939                                items: [],
3940                                suggestions: [],
3941                                total_count: 0,
3942                                page_info: {
3943                                    current_page: 1,
3944                                    page_size: this.pageSize
3945                                },
3946                                facets: []
3947                            }
3948                        }
3949                    };
3950                }
3951
3952                const searchQuery = this.isSuggestionHoverMode ? this.suggestionHover : this.queryPhrase;
3953
3954                const searchCtx = {
3955                    units: [{
3956                        searchUnitId: "search-bar",
3957                        queryTypes: ["products"],
3958                        phrase: searchQuery,
3959                        currentPage: 1,
3960                        pageSize: this.pageSize,
3961                        filter:[
3962                            {attribute:"visibility",in:["Search","Catalog, Search"]},
3963                            {attribute:"inStock",eq:"true"}
3964                        ],
3965                        sort: [{attribute: "relevance", direction: "DESC"}],
3966                        searchRequestId: this.searchRequestId
3967                    }]
3968                };
3969
3970                window.magentoStorefrontEvents.context.setSearchInput(searchCtx);
3971                window.magentoStorefrontEvents.publish.searchRequestSent("search-bar");
3972
3973                const before = Date.now();
3974
3975                const result = await this.search.productSearch({
3976                    phrase: searchQuery,
3977                    page_size: this.pageSize,
3978                    sort: [{attribute: "relevance", direction: "DESC"}],
3979                    filter:[
3980                        {attribute:"visibility",in:["Search","Catalog, Search"]},
3981                        {attribute:"inStock",eq:"true"}
3982                    ],
3983                    current_page: 1,
3984                    data: {
3985                        products: true,
3986                        facets: true,
3987                        suggestions: true
3988                    },
3989                    context: {
3990                        customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"
3991                    }
3992                });
3993
3994                const after = Date.now();
3995
3996                const productItems = result.data.productSearch.items || [];
3997                const suggestions = result.data.productSearch.suggestions || [];
3998                const facets = result.data.productSearch.facets || [];
3999
4000                const formattedProductItems = productItems.map((item, key) => ({
4001                    name: item.product.name,
4002                    sku: item.product.sku,
4003                    url: item.product.canonical_url,
4004                    imageUrl: item.product.image ? item.product.image.url : 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
4005                    price: item.product.price_range.minimum_price.final_price.value,
4006                    rank: key,
4007                }));
4008
4009                const formattedSuggestions = suggestions.map((item, key) => ({
4010                    suggestion: item,
4011                    rank: key,
4012                }));
4013
4014                const formattedFacets = facets.map((facet) => ({
4015                    attribute: facet.attribute,
4016                    title: facet.title,
4017                    type: facet.type || "PINNED",
4018                    buckets: facet.buckets.map((bucket) => bucket),
4019                }));
4020
4021                const searchCtxUpdated = {
4022                    units: [{
4023                        searchUnitId: "search-bar",
4024                        searchRequestId: this.searchRequestId,
4025                        executionTime: after - before,
4026                        products: formattedProductItems,
4027                        categories: [],
4028                        suggestions: this.isSuggestionHoverMode ? this.suggestions : formattedSuggestions,
4029                        page: result.data.productSearch.page_info.current_page,
4030                        perPage: result.data.productSearch.page_info.page_size,
4031                        facets: formattedFacets
4032                    }]
4033                };
4034
4035                if (this.isSuggestionHoverMode) {
4036                    this.liveSearchProducts = result.data.productSearch.items.map(item => ({
4037                        name: item.product.name,
4038                        price: item.product.price_range.maximum_price.regular_price.value,
4039                        currency: item.product.price_range.maximum_price.regular_price.currency,
4040                        image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
4041                        url: item.product.canonical_url,
4042                        id: item.product.id,
4043                        sku: item.product.sku
4044                    }));
4045                }
4046
4047                window.magentoStorefrontEvents.context.setSearchResults(searchCtxUpdated);
4048                window.magentoStorefrontEvents.publish.searchResponseReceived("search-bar");
4049
4050                return result;
4051            }
4052        }
4053    }
4054</script>
4054
4055                                </div>
4056                            </div>
4057                        </template>
4058                        <template x-if="stack.length > 1">
4059                            <span class="body-1 font-bold flex-1 text-center uppercase" x-text="panel.title"></span>
4060                        </template>
4061                        <button @click="closeMenu()" aria-label="Close" class="ml-3 border-0 hover:border-0 hover:bg-transparent">
4062                            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" class="text-black" aria-hidden="true">
4063<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4064<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4065</svg>
4066                        </button>
4067                    </div>
4068                    <div class="overflow-y-auto min-h-0" style="flex-grow: 1; max-height: calc(100dvh - 52px - env(safe-area-inset-bottom)); -webkit-overflow-scrolling: touch;">
4069                        <ul :class="{ 'ml-0': true,'!pt-3': stack.length <= 1}" class="!pb-10 pb-safe">
4070                            <!-- All menu items in natural order -->
4071                            <template x-for="node in panel.nodes" :key="'menu-' + node.id">
4072                                <li class="before:content-[''] pl-0 border-b border-primary-lightest flex items-center justify-between" :class="node.classes">
4073                                    <a :href="node.url" class="!flex items-center !px-4 !py-[15px] no-underline uppercase font-bold text-left">
4074                                        <!-- Menu item image -->
4075                                        <template x-if="node.image">
4076                                            <img :src="node.image" :alt="node.title" class="mr-2 w-5 h-5 object-cover">
4077                                        </template>
4078                                        <span x-text="node.title" class="text-primary-dark"></span>
4079                                    </a>
4080                                    <template x-if="node.hasChildren">
4081                                        <button @click="goTo(node)"
4082                                                class="flex flex-1 items-center justify-end px-4 py-[15p
4082x] w-6/12 border-0
4083                                                       hover:border-0 hover:bg-transparent"
4084                                                aria-label="Open&#x20;submenu">
4085                                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20 20" fill="none" class="text-primary-dark" aria-hidden="true" style="transform: rotate(-90deg);">
4086<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4087</svg>
4088                                        </button>
4089                                    </template>
4090                                </li>
4091                            </template>
4092
4093                            <!-- Hardcoded Shops and Account items (only on first level) -->
4094                            <template x-if="idx === 0">
4095                                <div>
4096
4097                                    <!-- Account item -->
4098                                    <li class="before:content-[''] pl-0 border-b border-primary-lightest flex items-center">
4099                                        <button
4100                                                @click="goTo({ title: 'Sign\u0020in', children: [] })"
4101                                                class="flex items-center flex-1 px-4 py-[15p
4101x] no-underline uppercase font-bold
4102                                                       text-left text-primary-dark bg-transparent border-0 cursor-pointer
4103                                                       hover:bg-transparent hover:border-0"
4104                                        >
4105                                    <span class="mr-2 text-primary-dark">
4106                                        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" class="inline-block" aria-hidden="true">
4107<path fill-rule="evenodd" clip-rule="evenodd" d="M12 10C14.2091 10 16 8.20914 16 6C16 3.79086 14.2091 2 12 2C9.79086 2 8 3.79086 8 6C8 8.20914 9.79086 10 12 10ZM12 12C15.3137 12 18 9.31371 18 6C18 2.68629 15.3137 0 12 0C8.68629 0 6 2.68629 6 6C6 9.31371 8.68629 12 12 12Z" fill="#2E1950"/>
4108<path fill-rule="evenodd" clip-rule="evenodd" d="M15 16H9C5.68629 16 3 18.6863 3 22H21C21 18.6863 18.3137 16 15 16ZM9 14C4.58172 14 1 17.5817 1 22V24H23V22C23 17.5817 19.4183 14 15 14H9Z" fill="#2E1950"/>
4109</svg>
4110                                    </span>
4111                                            <span>Sign in</span>
4112                                        </button>
4113                                        <button @click="goTo({ title: 'Sign\u0020in', children: [] }
4113)" class="flex items-center justify-end px-4 py-[15px] w-6/12 bg-transparent border-0 hover:bg-transparent hover:border-0 cursor-pointer" aria-label="Open&#x20;account&#x20;menu">
4114                                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20 20" fill="none" aria-hidden="true" style="transform: rotate(-90deg);">
4115<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4116</svg>
4117                                        </button>
4118                                    </li>
4119                                </div>
4120                            </template>
4121                            <template x-if="idx === 0">
4122                                <div
4123                                        class="[&_ul]:ml-0 [&_ul]:gap-y-6 [&_ul]:flex [&_ul]:flex-col [&_ul]:px-4 [&_ul]:pt-6 [&_li]:before:content-['']
4124                                [&_li]:pl-0 [&_a]:no-underline [&_a]:font-normal [&_a]:text-left [&_a]:!text-primary-dark [&_a]:!p-0"
4125                                >
4126                                    <div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><ul id="nav-top">
4127    <li><a href="/corporate-gifts"><b>CORPORATE GIFTS</b></a></li>
4128    <li><a href="https://fundraising.purdys.com/"><b>FUNDRAISING</b></a></li>
4129    <li><a href="https://group.purdys.com/"><b>GROUP SAVINGS</b></a></li>
4130    <!--<li><a href="/doordash-redirect?utm_source=purdys&amp;utm_medium=website&amp;utm_campaign=doordashlink"><b>DOORDASH</b></a></li>-->
4131</ul>
4132</div>                                </div>
4133                            </template>
4134
4135                            <!-- Customer links for account menu layer -->
4136                            <template x-if="panel.title === 'Sign\u0020in' || panel.title === 'Account'">
4137                                <div class="py-3 border-y border-primary-lightest">
4138                                                                            <!-- Logged out customer links -->
4139                                        <div class="[&_a]:block [&_a]:px-4 [&_a]:py-3 [&_a]:no-underline [&_a]:text-primary-dark [&_a]:hover:bg-transparent">
4140                                            
4141<a id="customer.header.sign.in.link"
4142   x-data="{}"
4143   @click="$store.device.isDesktop ? ($event.preventDefault(), $dispatch('open-auth-modal', { tab: 'login' })) : null"
4144   :href="$store.device.isDesktop ? '#' : 'https://www.purdys.com/customer/account/login/'"
4145   title="Sign&#x20;In"
4146>
4147    Sign In</a>
4148
4149    <a id="customer.header.register.link"
4150       x-data="{}"
4151       @click="$store.device.isDesktop ? ($event.preventDefault(), $dispatch('open-auth-modal', { tab: 'register' })) : null"
4152       :href="$store.device.isDesktop ? '#' : 'https://www.purdys.com/customer/account/create/'"
4153       title="Create&#x20;an&#x20;Account"
4154    >
4155        Create an Account    </a>
4156                                        </div>
4157                                                                    </div>
4158                            </template>
4159                        </ul>
4160                    </div>
4161                </div>
4162            </template>
4163        </div>
4164    </nav>
4165                </div>
4166            </div>
4167        </div>
4168    </div>
4169
4170    <div class="bg-container-darker">
4171            </div>
4172
4173    <!--Search mobile-->
4174    <div
4175            x-ref="searchContainerMobile"
4176            class="absolute w-full bg-white border-b border-primary-lightest lg:hidden pb-4 px-4 md:px-5 transition-all duration-300 ease-in-out"
4177            x-show="searchOpen"
4178            x-transition:enter="transition ease-out duration-300"
4179            x-transition:enter-start="opacity-0 transform -translate-y-2"
4180            x-transition:enter-end="opacity-100 transform translate-y-0"
4181            x-transition:leave="transition ease-in duration-200"
4182            x-transition:leave-start="opacity-100 transform translate-y-0"
4183            x-transition:leave-end="opacity-0 transform -translate-y-2"
4184            @click.away="closeSearch()"
4185            x-cloak>
4186        <div x-ref="searchForm">
4187            <div x-data="initLiveSearch"
4188     x-init="initPopover"
4189     @close-search.window="closePopover"
4190     @open-search.window="openPopover"
4191     @keydown.escape="closePopover"
4192     class="relative"
4193>
4194    <search role="search">
4195        <form class="form minisearch w-full flex md:relative lg:max-w-80 ml-auto"
4196              id="search_mini_form"
4197              action="https://www.purdys.com/catalogsearch/result/"
4198              method="get"
4199        >
4200            <div class="relative w-full">
4201                <label class="hidden" for="search" data-role="minisearch-label">
4202                    <span>Search</span>
4203                </label>
4204                <input id="search"
4205                       class="form-input flex-1 px-3 py-2 rounded-sm outline-none w-full min-h-12 hover:border-primary focus:border-primary focus:shadow-none"
4206                       type="text"
4207                       x-ref="searchRef"
4208                       :value="queryPhrase"
4209                       name="q"
4210                       value=""
4211                       placeholder="Type&#x20;to&#x20;search..."
4212                       maxlength="128"
4213                       role="combobox"
4214                       aria-haspopup="false"
4215                       aria-autocomplete="both"
4216                       autocomplete="off"
4217                       aria-expanded="false"
4218                       @input="handleInput"
4219                       @click.away="closePopover"
4220                />
4221                <button type='submit'
4222                        title="Search"
4223                        x-show="queryPhrase === ''"
4224                        class='bg-primary text-white rounded-e-sm px-3 outline-none absolute end-0 top-0 h-full
4225                               rounded-r border-0 hover:bg-primary hover:border-0'
4226                        aria-label="Search">
4227                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
4228<path fill-rule="evenodd" clip-rule="evenodd" d="M8.75049 1.49969C4.74642 1.49969 1.50049 4.74563 1.50049 8.74969C1.50049 12.7538 4.74642 15.9997 8.75049 15.9997C12.7546 15.9997 16.0005 12.7538 16.0005 8.74969C16.0005 4.74563 12.7546 1.49969 8.75049 1.49969ZM0.000488281 8.74969C0.000488281 3.9172 3.918 -0.000305176 8.75049 -0.000305176C13.583 -0.000305176 17.5005 3.9172 17.5005 8.74969C17.5005 13.5822 13.583 17.4997 8.75049 17.4997C3.918 17.4997 0.000488281 13.5822 0.000488281 8.74969Z" fill="white"/>
4229<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4001 14.3993C14.7108 14.0887 15.2144 14.0887 15.5251 14.3993L19.7675 18.6418C20.0781 18.9524 20.0781 19.4561 19.7675 19.7667C19.4569 20.0774 18.9532 20.0774 18.6426 19.7667L14.4001 15.5243C14.0895 15.2136 14.0895 14.71 14.4001 14.3993Z" fill="white"/>
4230</svg>
4231                </button>
4232                <button
4233                    @click.prevent="queryString = ''; clearInput()"
4234                    x-cloak
4235                    x-show="queryPhrase !== ''"
4236                    title="Clear"
4237                    class="bg-primary text-white rounded-e-sm px-3 outline-none absolute
4238                           end-0 top-0 h-full rounded-r border-0 hover:bg-primary hover:border-0 hover:text-white"
4239                    aria-label="Clear">
4240                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
4241<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4242<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4243</svg>
4244                </button>
4245                <template x-if="queryPhrase != ''">
4246                    <a id="clearInput" class="absolute right-[60px] top-[11px] hover:text-primary" @click.prevent="clearInput" href="#">Clear</a>
4247                </template>
4248            </div>
4249        </form>
4250    </search>
4251    <div x-show="searchOpen"
4252         class="bg-black opacity-[0.6] fixed w-[100vw] h-[100vh] left-0 mt-[18px]"
4253         style="display: none;"
4254         @click="closePopup"></div>
4255    <section
4256        x-show="searchOpen"
4257        class="livesearch-overlay search-autocomplete overflow-y-scroll !h-[calc(100dvh-var(--height-header))] md:!h-auto md:overflow-y-auto"
4258        :class="getSearchClasses"
4259        style="display: none;"
4260        aria-label="Search&#x20;Suggestions"
4261        x-transition:enter='transition-all duration-300 ease-out'
4262        x-transition:enter-start='opacity-0'
4263        x-transition:enter-end='opacity-100'
4264        x-transition:leave='transition-all duration-200 ease-in'
4265        x-transition:leave-start='opacity-100'
4266        x-transition:leave-end='opacity-0'
4267    >
4268        <!-- No Results Header -->
4269        <template x-if="showResults && !liveSearchTotalCount && !isLoading">
4270            <div class="max-w-[1660px] mx-auto px-4 md:px-0">
4271                <div class="flex items-center justify-between">
4272                    <h3 class="font-bold text-xl md:text-3xl"
4273                        x-text="'No\u0020results\u0020found\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
4274                    <a href="#" @click.prevent='closePopup'>
4275                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
4276<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4277<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4278<title>x</title></svg>
4279                    </a>
4280                </div>
4281                <p class="pt-3">
4281We can't find any item matching your search. Please try another search.</p>
4282            </div>
4283        </template>
4284        <!-- Results Header -->
4285        <template x-if="showResults">
4286            <div class="flex items-center justify-between max-w-[1660px] mx-auto px-4 md:px-0">
4287                <h3 class="font-bold text-xl md:text-3xl !m-0" x-text="'Search\u0020results\u0020for\u003A ' + '\'' + queryPhrase + '\''"></h3>
4288                <a href="#" @click.prevent='closePopup'>
4289                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="text-black" role="img">
4290<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4291<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
4292<title>x</title></svg>
4293                </a>
4294            </div>
4295        </template>
4296        <div x-show="liveSearchTotalCount && !isLoading" class="livesearch-overlay-content"
4297             x-transition:enter='transition-all duration-300 ease-out'
4298             x-transition:enter-start='opacity-0'
4299             x-transition:enter-end='opacity-100'
4300             x-transition:leave='transition-all duration-200 ease-in'
4301             x-transition:leave-start='opacity-100'
4302             x-transition:leave-end='opacity-0'>
4303            <template x-if="showSuggestions">
4304                <div class="flex flex-col md:max-h-[393px]">
4305                    <p class="text-lg pb-[10px] border-b border-grey-muted">
4306                        <strong>
4307                            Suggestions                        </strong>
4308                    </p>
4309                    <ul class="-mx-2 space-y-1 !border-0 pl-[8px]" role="list">
4310                        <template x-for="suggestion in liveSearchSuggestions">
4311                            <li class="before:hidden !border-0 !p-0 pl-0 hover:!bg-transparent">
4312                                <button
4313                                    x-html="getSuggestionText(suggestion)"
4314                                    @click="searchSuggestion"
4315                                    @mouseenter="onSuggestionHover(suggestion)"
4316                                    type="button"
4317                                    class="w-full p-2 text-left capitalize border-0 pl-0
4318                                           hover:text-primary-hover hover:underline
4319                                           hover:cursor-pointer hover:bg-transparent hover:border-0"
4320                                ></button>
4321                            </li>
4322                        </template>
4323                    </ul>
4324                    <div class="pt-3 md:pt-5 mt-auto pb-2.5 md:pb-0">
4325                        <a href='#' @click.prevent="redirectToSearchPage()" class='flex gap-1 items-center !text-primary'>
4326                            <span x-text="getSeeResultsText()"></span>
4327                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
4328  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
4329</svg>
4330                        </a>
4331                    </div>
4332                </div>
4333            </template>
4334            <template x-if="showResults">
4335                <div class="lg:col-span-2">
4336                    <p class="text-lg pb-[10px] border-b-[1px] border-grey-muted">
4337                        <strong>
4338                            Product Suggestions                        </strong>
4339                    </p>
4340                    <ul class="livesearch-overlay-content-products !border-0" role="list">
4341                        <template x-for="product in liveSearchProducts">
4342                            <li class="before:hidden pl-0 !p-0 !border-0 hover:!bg-transparent">
4343                                <button
4344                                    class="w-full flex gap-4 text-left cursor-pointer
4345                                           product-suggestion-button border-0 hover:bg-transparent hover:border-0"
4346                                    @click="handleProductClick"
4347                                >
4348                                    <img
4349                                        :src="product.image"
4350                                        :alt="product.name"
4351                                        width="80"
4352                                        height="80"
4353                                        class="w-[80px] h-[80px] shrink-0 object-contain"
4354                                    >
4355                                    <div class="flex flex-col justify-center w-full">
4356                                        <div class="flex flex-row justify-between gap-6">
4357                                            <p><strong class="product-name max-w-[287px]" x-text="product.name"></strong></p>
4358                                            <template x-if="product.price">
4359                                                <p class="font-bold" x-text="showProductPrice"></p>
4360                                            </template>
4361                                        </div>
4362                                    </div>
4363                                </button>
4364                            </li>
4365                        </template>
4366                    </ul>
4367                    <div class="py-5 md:pb-0">
4368                        <a href="#" @click.prevent="redirectToSearchPage(true)" class="flex gap-1 items-center !text-primary">
4369                            <span x-text="getSeeResultsText(true)"></span>
4370                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="rtl:rotate-180" width="20" height="20" aria-hidden="true">
4371  <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
4372</svg>
4373                        </a>
4374                    </div>
4375                </div>
4376            </template>
4377        </div>
4378    </section>
4379</div>
4380
4381<script>
4382    'use strict';
4383    
4384    // Global search instance storage to persist across Alpine re-initializations
4385    window.liveSearchInstance = null;
4386    window.liveSearchInitialized = false;
4387    
4388    window.addEventListener(
4389        'alpine:init',
4390        () => Alpine.data('initLiveSearch', () => ({
4391            queryPhrase: '',
4392            liveSearchProducts: [],
4393            liveSearchSuggestions: [],
4394            liveSearchTotalCount: 0,
4395            isLoading: false,
4396            minQueryLength: 3,
4397            pageSize: 8,
4398            searchOpen: false,
4399            search: null,
4400            searchInitialized: false,
4401            isSuggestionHoverMode: false,
4402            suggestionHover: '',
4403            searchId: "2cc69165-2270-494c-893f-c00d0bb35bd7_" +
4404                "base_" +
4405                "main_website_store_" +
4406                "default",
4407
4408            initPopover() {
4409                this.initSearch();
4410                this.initTogglePopover();
4411
4412                const self = this;
4413
4414                window.addEventListener('open-search-popup', function (event) {
4415                    if (self.liveSearchTotalCount > 0) {
4416                        self.openPopover();
4417                    }
4418                });
4419
4420            },
4421
4422            async initSearch() {
4423                // Check if we already have a global instance
4424                if (window.liveSearchInitialized && window.liveSearchInstance) {
4425                    this.search = window.liveSearchInstance;
4426                    this.searchInitialized = true;
4427                    return;
4428                }
4429
4430                if (this.searchInitialized || this.searchInitializing) {
4431                    return;
4432                }
4433
4434                this.searchInitializing = true;
4435
4436                try {
4437                    // Set up storefront events
4438                    if (window.magentoStorefrontEvents) {
4439                        window.magentoStorefrontEvents.context.setSearchExtension({
4440                            version: "4.4.1"
4441                        });
4442                    }
4443
4444                    // Wait for MagentoLiveSearch to be available (with shorter timeout)
4445                    await this.waitForMagentoLiveSearch();
4446
4447                    if (!window.MagentoLiveSearch || typeof window.MagentoLiveSearch !== 'function') {
4448                        throw new Error('MagentoLiveSearch is not available');
4449                    }
4450
4451                    this.search = new window.MagentoLiveSearch({
4452                        environmentId: "2cc69165-2270-494c-893f-c00d0bb35bd7",
4453                        websiteCode: "base",
4454                        storeCode: "main_website_store",
4455                        storeViewCode: "default",
4456                        apiKey: "search_gql",
4457                    });
4458                    
4459                    if (!this.search) {
4460                        throw new Error('MagentoLiveSearch constructor returned null/undefined');
4461                    }
4462                    
4463                    // Store globally to persist across Alpine re-initializations
4464                    window.liveSearchInstance = this.search;
4465                    window.liveSearchInitialized = true;
4466                    this.searchInitialized = true;
4467                } catch (error) {
4468                    console.error('MagentoLiveSearch could not be initialized:', error);
4469                    this.searchInitialized = false;
4470                    this.search = null;
4471                } finally {
4472                    this.searchInitializing = false;
4473                }
4474            },
4475
4476            waitForMagentoLiveSearch() {
4477                return new Promise((resolve) => {
4478                    // If already available, resolve immediately
4479                    if (window.MagentoLiveSearch) {
4480                        resolve();
4481                        return;
4482                    }
4483
4484                    // Otherwise set up a watcher with faster polling
4485                    const checkInterval = setInterval(() => {
4486                        if (window.MagentoLiveSearch) {
4487                            clearInterval(checkInterval);
4488                            resolve();
4489                        }
4490                    }, 50); // Faster polling - 50ms instead of 100ms
4491
4492                    // Shorter timeout - 3 seconds instead of 10
4493                    setTimeout(() => {
4494                        clearInterval(checkInterval);
4495                        resolve();
4496                    }, 3000);
4497                });
4498            },
4499
4500            clearInput() {
4501                this.$refs.searchRef.value = '';
4502                this.liveSearchProducts = [];
4503                this.liveSearchSuggestions = [];
4504                this.liveSearchTotalCount = 0;
4505                this.queryPhrase = '';
4506
4507                this.closePopover();
4508            },
4509
4510            redirectToSearchPage(isSuggestion = false) {
4511                let searchTerm = this.queryPhrase;
4512                
4513                if (isSuggestion) {
4514                    // Use suggestionHover if available, otherwise fall back to queryPhrase
4515                    searchTerm = this.suggestionHover || this.queryPhrase;
4516                }
4517
4518                window.location.href = '/catalogsearch/result/?q=' + encodeURIComponent(searchTerm);
4519            },
4520
4521            buildSearch() {
4522                window.magentoStorefrontEvents.context.setSearchExtension({
4523                    version: "4.4.1"
4524                });
4525
4526                // Wait for MagentoLiveSearch to be available
4527                return new Promise((resolve) => {
4528                    const checkForMagentoLiveSearch = () => {
4529                        if (window.MagentoLiveSearch) {
4530                            resolve(new MagentoLiveSearch({
4531                                environmentId: "2cc69165-2270-494c-893f-c00d0bb35bd7",
4532                                websiteCode: "base",
4533                                storeCode: "main_website_store",
4534                                storeViewCode: "default",
4535                                apiKey: "search_gql",
4536                            }));
4537                        } else {
4538                            setTimeout(checkForMagentoLiveSearch, 100);
4539                        }
4540                    };
4541
4542                    checkForMagentoLiveSearch();
4543                });
4544
4545            },
4546
4547            // this will open the popover, whenever the search-input has focus
4548            initTogglePopover() {
4549                const popover = document.getElementById('search');
4550
4551                popover.addEventListener('focus', () => {
4552                    if (this.isQueryLengthValid()) {
4553                        this.openPopover();
4554                    } else {
4555                        this.closePopover();
4556                    }
4557                });
4558            },
4559
4560            closePopover() {
4561                this.searchOpen = false;
4562                // Restore body scroll when closing search overlay
4563                document.body.style.overflow = '';
4564            },
4565
4566            closePopup() {
4567                this.searchOpen = false;
4568                // Restore body scroll when closing search overlay
4569                document.body.style.overflow = '';
4570            },
4571
4572            openPopover() {
4573                this.searchOpen = true;
4574
4575                if (window.innerWidth <= 768) {
4576                    // Lock body scroll when opening search overlay
4577                    document.body.style.overflow = 'hidden';
4578                }
4579            },
4580
4581            handleInput() {
4582                this.queryPhrase = this.$el.value;
4583                this.suggestionHover = '';
4584                this.isSuggestionHoverMode = false;
4585
4586                if (!this.isQueryLengthValid()) {
4587                    if (this.searchOpen){
4588                        this.closePopover();
4589                    }
4590                    return;
4591                }
4592
4593                this.getProducts();
4594                this.$nextTick(() => {
4595                    this.openPopover();
4596                });
4597            },
4598
4599            showProductPrice(){
4600                return this.product.price ? hyva.formatPrice(this.product.price) : '';
4601            },
4602
4603            handleProductClick() {
4604                window.magentoStorefrontEvents.context.setSearchResults(
4605                    window.magentoStorefrontEvents.context.getSearchResults()
4606                );
4607
4608                window.magentoStorefrontEvents.publish.searchProductClick("search-bar", `${this.product.sku}`);
4609
4610                // Timeout to prevent submission before event has fired.
4611                setTimeout(() => window.location.href = this.product.url, 500);
4612            },
4613
4614            // this will submit the form with the clicked suggestion as the search-phrase
4615            searchSuggestion() {
4616                document.getElementById('search').value = this.suggestion;
4617                document.getElementById('search_mini_form').submit();
4618            },
4619
4620            showResults(){
4621                return this.liveSearchProducts.length >= 1 && this.isQueryLengthValid() || this.isSuggestionHoverMode;
4622            },
4623
4624            showSuggestions(){
4625                return this.liveSearchSuggestions.length >= 1 && this.isQueryLengthValid();
4626            },
4627
4628            isQueryLengthValid() {
4629                return this.queryPhrase.length >= this.minQueryLength;
4630            },
4631
4632            getSearchClasses() {
4633                return this.searchOpen ? 'block' : 'hidden';
4634            },
4635            getSuggestionText(suggestion) {
4636                const matches = suggestion.match(new RegExp(this.queryPhrase, 'gmi'));
4637
4638                matches.map((match) => {
4639                    suggestion = suggestion.replaceAll(match, '<b>' + match + '</b>')
4640                });
4641
4642                return suggestion;
4643            },
4644            async onSuggestionHover(suggestion) {
4645                this.isSuggestionHoverMode = true;
4646                this.suggestionHover = suggestion;
4647
4648                await this.getProducts();
4649
4650                this.queryPhrase = suggestion;
4651            },
4652            onSuggestionUnhover() {
4653                this.isSuggestionHoverMode = false;
4654                this.suggestionHover = '';
4655            },
4656            getSeeResultsText(isSuggestion = false) {
4657                const text = 'See\u0020\u0025total\u0020results\u0020for\u0020\u0022\u0025term\u0022';
4658
4659                if (isSuggestion && this.isSuggestionHoverMode) {
4660                    return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.suggestionHover);
4661                }
4662
4663                return text.replace('%total', this.liveSearchTotalCount).replace('%term', this.queryPhrase);
4664            },
4665
4666            // get products from fetch-request and update liveSearchProducts and liveSearchSuggestions
4667            async getProducts() {
4668                this.searchOpen = true;
4669
4670                if (!this.isSuggestionHoverMode) {
4671                    this.isLoading = true;
4672                }
4673
4674                // Make sure search is initialized
4675                if (!this.searchInitialized && !this.searchInitializing) {
4676                    await this.initSearch();
4677                } else if (this.searchInitializing) {
4678                    // Wait for ongoing initialization to complete (reduced timeout)
4679                    let attempts = 0;
4680                    while (this.searchInitializing && attempts < 20) { // 2 seconds max instead of 5
4681                        await new Promise(resolve => setTimeout(resolve, 100));
4682                        attempts++;
4683                    }
4684                }
4685
4686                // If still not initialized, try to use global instance as fallback
4687                if (!this.search) {
4688                    if (window.liveSearchInstance) {
4689                        this.search = window.liveSearchInstance;
4690                        this.searchInitialized = true;
4691                    } else {
4692                        console.error('MagentoLiveSearch could not be initialized');
4693                        this.isLoading = false;
4694                        return;
4695                    }
4696                }
4697
4698                const result = await this.getLiveSearchProducts();
4699                this.isLoading = false;
4700
4701                this.liveSearchProducts = result.data.productSearch.items.map(item => ({
4702                    name: item.product.name,
4703                    price: item.product.price_range.maximum_price.regular_price.value,
4704                    currency: item.product.price_range.maximum_price.regular_price.currency,
4705                    image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
4706                    url: item.product.canonical_url,
4707                    id: item.product.id,
4708                    sku: item.product.sku
4709                }));
4710
4711                this.liveSearchSuggestions = result.data.productSearch.suggestions
4712                this.liveSearchTotalCount = result.data.productSearch.total_count;
4713
4714                //search-results-view
4715            },
4716
4717            // retrieve products from magento live search service
4718            async getLiveSearchProducts() {
4719                this.searchRequestId = Math.random().toString(16).slice(2);
4720
4721                if (!this.search) {
4722                    return {
4723                        data: {
4724                            productSearch: {
4725                                items: [],
4726                                suggestions: [],
4727                                total_count: 0,
4728                                page_info: {
4729                                    current_page: 1,
4730                                    page_size: this.pageSize
4731                                },
4732                                facets: []
4733                            }
4734                        }
4735                    };
4736                }
4737
4738                const searchQuery = this.isSuggestionHoverMode ? this.suggestionHover : this.queryPhrase;
4739
4740                const searchCtx = {
4741                    units: [{
4742                        searchUnitId: "search-bar",
4743                        queryTypes: ["products"],
4744                        phrase: searchQuery,
4745                        currentPage: 1,
4746                        pageSize: this.pageSize,
4747                        filter:[
4748                            {attribute:"visibility",in:["Search","Catalog, Search"]},
4749                            {attribute:"inStock",eq:"true"}
4750                        ],
4751                        sort: [{attribute: "relevance", direction: "DESC"}],
4752                        searchRequestId: this.searchRequestId
4753                    }]
4754                };
4755
4756                window.magentoStorefrontEvents.context.setSearchInput(searchCtx);
4757                window.magentoStorefrontEvents.publish.searchRequestSent("search-bar");
4758                const before = Date.now();
4759                let result;
4760
4761                try {
4762                    // Here we call the actual search method
4763                    result = await this.search.productSearch({
4764                        phrase: searchQuery,
4765                        page_size: this.pageSize,
4766                        sort: [{attribute: "relevance", direction: "DESC"}],
4767                        filter: [
4768                            {attribute: "visibility", in: ["Search", "Catalog, Search"]},
4769                            {attribute: "inStock", eq: "true"}
4770                        ],
4771                        current_page: 1,
4772                        data: {
4773                            products: true,
4774                            facets: true,
4775                            suggestions: true
4776                        },
4777                        context: {
4778                            customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"
4779                        }
4780                    });
4781                } catch (error) {
4782                    return { data: { productSearch: { items: [], suggestions: [], total_count: 0, page_info: { current_page: 1, page_size: this.pageSize } } } };
4783                }
4784
4785                const after = Date.now();
4786
4787                const productItems = result.data.productSearch.items || [];
4788                const suggestions = result.data.productSearch.suggestions || [];
4789                const facets = result.data.productSearch.facets || [];
4790
4791                const formattedProductItems = productItems.map((item, key) => ({
4792                    name: item.product.name,
4793                    sku: item.product.sku,
4794                    url: item.product.canonical_url,
4795                    imageUrl: item.product.image ? item.product.image.url : 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
4796                    price: item.product.price_range.minimum_price.final_price.value,
4797                    rank: key,
4798                }));
4799
4800                const formattedSuggestions = suggestions.map((item, key) => ({
4801                    suggestion: item,
4802                    rank: key,
4803                }));
4804
4805                const formattedFacets = facets.map((facet) => ({
4806                    attribute: facet.attribute,
4807                    title: facet.title,
4808                    type: facet.type || "PINNED",
4809                    buckets: facet.buckets.map((bucket) => bucket),
4810                }));
4811
4812                const searchCtxUpdated = {
4813                    units: [{
4814                        searchUnitId: "search-bar",
4815                        searchRequestId: this.searchRequestId,
4816                        executionTime: after - before,
4817                        products: formattedProductItems,
4818                        categories: [],
4819                        suggestions: this.isSuggestionHoverMode ? this.suggestions : formattedSuggestions,
4820                        page: result.data.productSearch.page_info.current_page,
4821                        perPage: result.data.productSearch.page_info.page_size,
4822                        facets: formattedFacets
4823                    }]
4824                };
4825
4826                if (this.isSuggestionHoverMode) {
4827                    this.liveSearchProducts = result.data.productSearch.items.map(item => ({
4828                        name: item.product.name,
4829                        price: item.product.price_range.maximum_price.regular_price.value,
4830                        currency: item.product.price_range.maximum_price.regular_price.currency,
4831                        image: item.product.thumbnail?.url || item.product.image?.url || 'https://www.purdys.com/media/catalog/product/placeholder/default/No-image-available_1.png',
4832                        url: item.product.canonical_url,
4833                        id: item.product.id,
4834                        sku: item.product.sku
4835                    }));
4836                }
4837
4838                window.magentoStorefrontEvents.context.setSearchResults(searchCtxUpdated);
4839                window.magentoStorefrontEvents.publish.searchResponseReceived("search-bar");
4840
4841                return result;
4842            }
4843        })),
4844        {once: true}
4845    )
4846</script>
4846
4847        </div>
4848    </div>
4849
4850    <!--Cart Drawer-->
4851    
4851<script>
4852    function initCartDrawer() {
4853        return {
4854            open: false,
4855            isLoading: false,
4856            cart: {},
4857            maxItemsToDisplay: 10,
4858            itemsCount: 0,
4859            itemCountSingularText: 'item',
4860            itemCountPluralText: 'items',
4861            updatedQuantities: {},
4862
4863            init() {
4864                // Initialization without free shipping calculation
4865            },
4866
4867            getData(data) {
4868                if (data.cart) {
4869                    this.cart = data.cart;
4870                    this.itemsCount = data.cart.items?.reduce((sum, item) => sum + (parseInt(item.qty) || 0), 0) || 0;
4871                    this.setCartItems();
4872
4873                    // Dispatch cart subtotal event for free shipping indicator
4874                    if (data.cart.subtotal) {
4875                        window.dispatchEvent(new CustomEvent('update-cart-subtotal', {
4876                            detail: {
4877                                subtotal: parseFloat(data.cart.subtotalAmount) || 0
4878                            }
4879                        }));
4880                    }
4881                }
4882                this.isLoading = false;
4883            },
4884
4885            cartItems: [],
4886            getItemCountTitle() {
4887                return hyva.strf('\u00250\u0020of\u0020\u00251\u0020products\u0020in\u0020cart\u0020displayed', this.maxItemsToDisplay, this.itemsCount)
4888            },
4889            setCartItems() {
4890                this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || [];
4891                if (this.maxItemsToDisplay > 0) {
4892                    this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10));
4893                }
4894            },
4895            updateQuantity(itemId, qty) {
4896                this.updatedQuantities[itemId] = qty;
4897                this.sendUpdateCart(itemId, qty);
4898            },
4899            sendUpdateCart(itemId, qty) {
4900                this.isLoading = true;
4901                const formKey = hyva.getFormKey();
4902                const postUrl = BASE_URL + 'checkout/sidebar/updateItemQty/';
4903                fetch(postUrl, {
4904                    "headers": {
4905                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
4906                    },
4907                    "body": "form_key=" + formKey + "&item_id=" + itemId + "&item_qty=" + qty,
4908                    "method": "POST",
4909                    "mode": "cors",
4910                    "credentials": "include"
4911                }).then(response => {
4912                    if (response.redirected) {
4913                        window.location.href = response.url;
4914                    } else if (response.ok) {
4915                        return response.json();
4916                    } else {
4917                        window.dispatchMessages && window.dispatchMessages([{ type: 'warning', text: 'Could\u0020not\u0020update\u0020item\u0020from\u0020quote.' }]);
4918                    }
4919                }).then(result => {
4920                    window.dispatchMessages && window.dispatchMessages([{ type: result.success ? 'success' : 'error', text: result.success ? 'You\u0020updated\u0020the\u0020item.' : result.error_message }], result.success ? 5000 : 0);
4921                    if (result.success) {
4922                        window.dataLayer = window.dataLayer || [];
4923                        window.dataLayer.push({ event: result.event, ecommerce: result.ecommerce });
4924                    }
4925                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
4926                    this.$dispatch && this.$dispatch('update-totals', {data: result.checkoutConfig?.totalsData});
4927                }).finally(() => {
4928                    this.isLoading = false;
4929                });
4930            },
4931            deleteItemFromCart(itemId) {
4932                this.isLoading = true;
4933                const itemData = this.cart.items.filter((item) => item['item_id'] === itemId);
4934                const formKey = hyva.getFormKey();
4935                const postUrl = BASE_URL + 'checkout/sidebar/removeItem/';
4936                fetch(postUrl, {
4937                    "headers": {
4938                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
4939                    },
4940                    "body": "form_key=" + formKey + "&item_id=" + itemId,
4941                    "method": "POST",
4942                    "mode": "cors",
4943                    "credentials": "include"
4944                }).then(response => {
4945                    if (response.redirected) {
4946                        window.location.href = response.url;
4947                    } else if (response.ok) {
4948                        return response.json();
4949                    } else {
4950                        window.dispatchMessages && window.dispatchMessages([{ type: 'warning', text: 'Could\u0020not\u0020remove\u
49500020item\u0020from\u0020quote.' }]);
4951                        this.isLoading = false;
4952                    }
4953                }).then(result => {
4954                    window.dispatchMessages && window.dispatchMessages([{ type: result.success ? 'success' : 'error', text: result.success ? 'You\u0020removed\u0020the\u0020item.' : result.error_message }], result.success ? 5000 : 0);
4955                    if (result.success && itemData) {
4956                        window.dispatchEvent(new CustomEvent('cart-item-removed', { detail: itemData }));
4957                    }
4958                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
4959                });
4960            },
4961            scrollLock(use = true) {
4962                document.body.style.overflow = use ? 'hidden' : '';
4963            },
4964            toggleCartDrawer(event) {
4965                if (event.detail && event.detail.isOpen !== undefined) {
4966                    if (event.detail.isOpen) {
4967                        this.openCartDrawer();
4968                    } else {
4969                        this.open = false;
4970                        this.scrollLock(false);
4971                        this.$refs && this.$refs.cartDialogContent && hyva.releaseFocus(this.$refs.cartDialogContent);
4972                    }
4973                } else {
4974                    this.openCartDrawer()
4975                }
4976            },
4977            openCartDrawer() {
4978                this.open = true;
4979                this.scrollLock(true);
4980                this.$nextTick(() => {
4981                    this.$refs && this.$refs.cartDialogContent && hyva.trapFocus(this.$refs.cartDialogContent)
4982                })
4983            },
4984            closeCartDrawer() {
4985                this.$dispatch('toggle-cart', { isOpen: false })
4986            },
4987            getSectionDataExtraActions() {
4988                if (!this.cart.extra_actions) {
4989                    return '';
4990                }
4991                const contentNode = document.createElement('div');
4992                contentNode.innerHTML = this.cart.extra_actions;
4993                hyva.activateScripts(contentNode);
4994                return contentNode.innerHTML;
4995            },
4996            getProductEditUrl(item) {
4997                if (item.product_type === 'bundle') {
4998                    return BASE_URL + 'build-a-box?item_id=' + item.item_id;
4999                }
5000
5001                return item.configure_url;
5002            },
5003            getProductImageUrl(item, src) {
5004                if (item.product_type === 'bundle') {
5005                    return BASE_URL + 'build-a-box/'
5006                }
5007
5008                return src;
5009            }
5010        }
5011    }
5012</script>
5012
5013<section x-cloak
5014         x-show="cart"
5015         id="cart-drawer"
5016         x-data="initCartDrawer()"
5017         @private-content-loaded.window="getData($event.detail.data)"
5018         @toggle-cart.window="toggleCartDrawer($event)"
5019         @keydown.escape="closeCartDrawer"
5020>
5021    <div role="dialog"
5022         aria-labelledby="cart-drawer-title"
5023         aria-modal="true"
5024         :aria-hidden="!open"
5025         class="fixed inset-y-0 end-0 z-30 flex max-w-full">
5026        <div class="backdrop"
5027             x-show="open"
5028             x-transition:enter="ease-in-out duration-500"
5029             x-transition:enter-start="opacity-0"
5030             x-transition:enter-end="opacity-100"
5031             x-transition:leave="ease-in-out duration-500"
5032             x-transition:leave-start="opacity-100"
5033             x-transition:leave-end="opacity-0"
5034             role="button"
5035             @click="closeCartDrawer"
5036             aria-label="Close&#x20;minicart"></div>
5037        <div class="relative w-screen max-w-md bg-white"
5038             x-show="open"
5039             x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
5040             x-transition:enter-start="ltr:translate-x-full rtl:-translate-x-full"
5041             x-transition:enter-end="translate-x-0"
5042             x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
5043             x-transition:leave-start="translate-x-0"
5044             x-transition:leave-end="ltr:translate-x-full rtl:-translate-x-full"
5045             x-ref="cartDialogContent"
5046             role="region"
5047             :tabindex="open ? 0 : -1"
5048             aria-label="My&#x20;Shopping&#x20;Bag"
5049        >
5050            <div class="flex flex-col h-full text-black">
5051                
5052                <header class="relative p-4 border-b border-subtext">
5053                    <h3 id="cart-drawer-title" class="flex items-center gap-2 !m-0">
5054                        <span class="font-bold text-lg uppercase">My Shopping Bag</span>
5055                        <span
5056                          class="rounded-full bg-primary-dark text-white text-xs px-2 py-1 font-semibold"
5057                          x-text="`${itemsCount} ${itemsCount === 1 ? itemCountSingularText : itemCountPluralText}`"
5058                          x-show="itemsCount > 0"
5059                        ></span>
5060                    </h3>
5061                </header>
5062
5063                
5064<!-- Free Shipping Indicator -->
5065<div id="minicart-free-shipping-indicator"
5066     class="free-shipping-indicator bg-background-light bg-opacity-50 pt-[11px] pb-3 px-4 bg-transparent"
5067     x-data="initFreeShippingIndicator()"
5068     x-init="init()"
5069     :class="getFreeShippingStateClass()"
5070     x-show="freeShippingVisible"
5071     x-cloak
5072     @shipping-estimation-address-updated.window="handleCountryChange($event.detail?.shippingAddress?.country_id)"
5073>
5074    <p class="text-center mb-1.5 min-h-[24px]" x-html="freeShippingMessage"></p>
5075
5076    <div class="rounded-full h-2 overflow-hidden bg-primary/[.15]">
5077        <div
5078            class="rounded-full h-2 transition-all duration-300 ease-out bg-primary"
5079            :style="`width: ${freeShippingProgressPercentage}%`"
5080        ></div>
5081    </div>
5082</div>
5083
5084<script>
5085    function initFreeShippingIndicator() {
5086        return {
5087            // Free shipping properties
5088            freeShippingThreshold: 100,
5089            freeShippingSubtotal: 0,
5090            freeShippingMessage: '',
5091            freeShippingProgressPercentage: 0,
5092            freeShippingEnabled: true,
5093            freeShippingVisible: false,
5094            freeShippingAllowedCountries: ["CA"],
5095            freeShippingAchievedMessage: 'Congratulations,\u0020you\u0020get\u0020\u003Cstrong\u003EFree\u0020Shipping\u0021\u003C\u002Fstrong\u003E',
5096            freeShippingRemainingMessage: 'Add\u0020\u003Cstrong\u003E\u0024\u00251\u003C\u002Fstrong\u003E\u0020more\u0020to\u0020get\u0020\u003Cstrong\u003EFree\u0020Shipping\u0021\u003C\u002Fstrong\u003E',
5097
5098            init() {
5099                this.calculateFreeShipping();
5100                
5101                // Listen for cart subtotal updates
5102                window.addEventListener('update-cart-subtotal', (event) => {
5103                    this.freeShippingSubtotal = event.detail.subtotal || 0;
5104                    this.calculateFreeShipping();
5105                });
5106
5107                const sectionData = JSON.parse(
5108                    hyva.getBrowserStorage().getItem('mage-cache-storage')
5109                ) || {};
5110
5111                const checkoutData = sectionData?.['checkout-data'] || {};
5112                const shippingAddress = checkoutData?.shippingAddressFromData || {};
5113                // window.checkoutConfig is `false` on an empty cart page and absent on non-cart
5114                // pages — reading .defaultCountryId off it crashed this component's init and left
5115                // the indicator permanently hidden. Guard it and fall back to the store default.
5116                const countryId = shippingAddress.country_id
5117                    || (window.checkoutConfig && window.checkoutConfig.defaultCountryId)
5118                    || 'CA';
5119                this.handleCountryChange(countryId);
5120            },
5121            
5122            calculateFreeShipping() {
5123                if (!this.freeShippingEnabled || this.freeShippingThreshold <= 0) {
5124                    return;
5125                }
5126
5127                if (this.freeShippingSubtotal >= this.freeShippingThreshold) {
5128                    this.freeShippingMessage = this.freeShippingAchievedMessage;
5129                    this.freeShippingProgressPercentage = 100;
5130                } else {
5131                    const remaining = this.freeShippingThreshold - this.freeShippingSubtotal;
5132                    this.freeShippingMessage = this.freeShippingRemainingMessage.replace('%1', remaining.toFixed(2));
5133                    this.freeShippingProgressPercentage = Math.min((this.freeShippingSubtotal / this.freeShippingThreshold) * 100, 100);
5134                }
5135            },
5136            
5137            getFreeShippingStateClass() {
5138                return this.freeShippingSubtotal >= this.freeShippingThreshold ? 'free-shipping-achieved' : '';
5139            },
5140            
5141            handleCountryChange(newCountryId) {
5142                                    this.freeShippingVisible =
5143                        this.freeShippingAllowedCountries.includes(newCountryId);
5144                            }
5145        };
5146    }
5147</script>
5147
5148
5149                
5150                <template x-if="!itemsCount">
5151                    <div class="relative px-4 py-6 bg-white border-bs sm:px-6 border-container">
5152                        Cart is empty                    </div>
5153                </template>
5154
5155                <template x-if="itemsCount">
5156                    <div class="minicart-item-container relative grid overflow-y-auto overscroll-y-contain">
5157                        <template x-for="item in cartItems">
5158                            <template x-if="item.is_hidden_cart_item !== true">
5159                            <div
5160                              class="flex items-start py-4 mx-4 space-x-3 transition duration-150 ease-in-out bg-white
5161                              rounded-sm border-b border-grey-checkbox"
5162                            >
5163                                <!-- Product image as before -->
5164                                <template x-if="item.product_type === 'bundle' || (item.product_has_url && item.is_visible_in_site_visibility)">
5165                                    <a :href="getProductImageUrl(item, item.product_url)"
5166                                       class="w-1/4 max-w-24 !ms-0"
5167                                       :aria-label="hyva.strf('Product\u0020\u0022\u00250\u0022', item.product_name)"
5168                                    >
5169                                        <img
5170                                          :src="item.product_image.src"
5171                                          :width="item.product_image.width"
5172                                          :height="item.product_image.height"
5173                                          loading="lazy"
5174                                          :alt="item.product_name"
5175                                        />
5176                                    </a>
5177                                </template>
5178                                <template x-if="item.product_type !== 'bundle' && (!item.product_has_url || !item.is_visible_in_site_visibility)">
5179                                    <div class="w-1/4 max-w-24 !ms-0">
5180                                        <img
5181                                          :src="item.product_image.src"
5182                                          :width="item.product_image.width"
5183                                          :height="item.product_image.height"
5184                                          loading="lazy"
5185                                          :alt="item.product_name"
5186                                        />
5187                                    </div>
5188                                </template>
5189                                <div class="w-3/4">
5190                                    <div>
5191                                        <p class="font-bold line-clamp-2">
5192                                            <span x-html="item.product_name"></span>
5193                                        </p>
5194                                    </div>
5195                                    <div x-data="{ showDetails: false }">
5196                                        <template x-if="item.product_type === 'bundle' && item.options?.length">
5197                                            <div>
5198                                                <div x-show="showDetails" class="my-3 flex flex-col gap-2">
5199                                                    <span class="body-3">
5200                                                        What&#039;s in the box:
5201                                                    </span>
5202                                                    <template x-for="option in item.options">
5203                                                        <template x-if="option.value">
5204                                                            <div
5205                                                              class="body-3 flex flex-col gap-y-2 [&_h4]:!text-sm
5206                                                                [&_h4]:!leading-[18px] [&_.product-item-cart-info]:!m-0"
5207                                                            >
5208                                                                <template x-if="Array.isArray(option.value)">
5209                                                                    <template x-for="value in option.value">
5210                                                                        <sp
5210an x-html="option.label === 'Sleeve' ? 'Sleeve: ' + value : value"></span>
5211                                                                    </template>
5212                                                                </template>
5213                                                                <template x-if="!Array.isArray(option.value)">
5214                                                                    <span x-html="option.label === 'Sleeve' ? 'Sleeve: ' + option.value : option.value"></span>
5215                                                                </template>
5216                                                            </div>
5217                                                        </template>
5218                                                    </template>
5219                                                </div>
5220                                                <button
5221                                                  @click="showDetails = !showDetails"
5222                                                  class="!text-primary body-1 font-bold flex items-center gap-2 mt-2 underline !border-0 !bg-transparent"
5223                                                  type="button">
5224                                                    <span
5225                                                      x-text="showDetail
5225s ? 'Hide details' :
5226                                                       'Show details'"
5227                                                    ></span>
5228                                                    <span :class="{ 'rotate-180': showDetails }">
5229                                                        <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="[&amp;&gt;path]:stroke-[4px]" role="img">
5230<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5231<title>chevron-down</title></svg>
5232                                                    </span>
5233                                                </button>
5234                                            </div>
5235                                        </template>
5236                                    </div>
5237                                    <div class="mt-3 flex flex-col gap-3">
5238                                        <div class="flex justify-between items-center gap-4">
5239                                            <!-- Price display -->
5240                                            <div class="flex flex-col items-end">
5241                                                <span
5242                                                  :class="{
5243                                                        'text-red font-bold text-xl leading-[26px]': item.base_final_price && item.base_final_price > item.product_price_value,
5244                                                        'font-bold text-xl leading-[26px]': !(item.base_final_price && item.base_final_price > item.product_price_value)
5245                                                    }"
5246                                                  x-html="hyva.formatPrice(item.qty * item.product_price_value)"
5247                                                ></span>
5248                                                <template x-if="item.base_final_price && item.base_final_price > item.product_price_value">
5249                                                    <span
5250                                                      class="line-through text-subtext text-sm mr-auto"
5251                                                      x-html="hyva.formatPrice(item.qty * item.base_final_price)"
5252                                                    ></span>
5253                                                </template>
5254                                            </div>
5255                                            <!-- Quantity input -->
5256                                            <div class="flex items-center border border-grey-muted rounded px-4 py-[9px] h-[42px] max-w-[120px] bg-white">
5257                                                <button type="button"
5258                                                        class="flex-1 text-black text-xl font-normal border-0 focus:outline-none
5259                                                               hover:bg-transparent hover:border-0 focus:bg-transparent focus:border-0"
5260                                                        :class="item.qty <= 1 ? 'text-grey-muted cursor-not-allowed' : 'text-black'"
5261                                                        :disabled="item.qty <= 1"
5262                                                        @click="item.qty = Math.max(1, parseInt(item.qty) - 1); updateQuantity(item.item_id, item.qty)"
5263                                                        :aria-label="'Decrease\u0020quantity\u0020for ' + item.product_name"
5264                                                        title="Minus">
5265                                                    <svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 16 16" fill="none" aria-hidden="true">
5266<path fill-rule="evenodd" clip-rule="evenodd" d="M16 8.86666L0 8.86666L0 7.53333L16 7.53333V8.86666Z" fill="currentColor"/>
5267</svg>
5268                                                </button>
5269                                                <input type="number"
5270                                                       :id="'qty-' + item.item_id"
5271                                                       x-model="item.qty"
5272                                                       class="text-center !font-proxima !border-0 focus:ring-0 focus:outline-none body-2 !text-[18px] !py-[0.5rem] !px-[0.75rem] max-w-[54px]"
5273                                                       @input="updateQuantity(item.item_id, item.qty)"
5274                                                       min="1"
5275                                                       aria-label="Quantity"
5276                                                />
5277                                                <button type="button"
5278                                                        class="flex-1 text-black text-xl font-normal border-0 focus:outline-none
5279                                                               hover:bg-transparent hover:border-0 focus:bg-transparent focus:border-0"
5280                                                        @click="item.qty = parseInt(item.qty) + 1; updateQuantity(item.item_id, item.qty)"
5281                                                        :aria-label="'Increase\u0020quantity\u0020for ' + item.product_name"
5282                                                        title="Plus">
5283                                                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
5284<path fill-rule="evenodd" clip-rule="evenodd" d="M7.19999 16L7.19999 -5.82819e-08L8.53333 0L8.53332 16L7.19999 16Z" fill="#141414"/>
5285<path fill-rule="evenodd" clip-rule="evenodd" d="M16 8.86666L0 8.86666L0 7.53333L16 7.53333V8.86666Z" fill="#141414"/>
5286</svg>
5287                                                </button>
5288                                            </div>
5289                                        </div>
5290                                        <!-- Edit/Delete as flex row -->
5291                                        <div class="flex items-center gap-4 justify-end">
5292                                            <a
5293                                              :href="getProductEditUrl(item)"
5294                                              x-show="item.product_type === 'bundle' || (item.product_type !== 'grouped' && item.is_visible_in_site_visibility)"
5295                                              class="font-bold text-base pr-4 border-r border-background-light cursor-pointer !text-primary"
5296                                              :aria-label="hyva.strf('Edit\u0020product\u0020\u0022\u00250\u0022', item.product_name)"
5297                                            >
5298                                                Edit product                                            </a>
5299                                            <button
5300                                              type="button"
5301                                              class="font-bold text-base !text-primary cursor-pointer
5302                                                           underline !border-0
5303                                                           hover:bg-transparent active:bg-transparent
5304                                                           focus:bg-transparent"
5305                                              @click="deleteItemFromCart(item.item_id)"
5306                                              :aria-label="hyva.strf('Remove\u0020product\u0020\u0022\u00250\u0022\u0020from\u0020cart', item.product_name)"
5307                                            >
5308                                                Remove                                            </button>
5309                                        </div>
5310                                    </div>
5311                                </div>
5312                            </div>
5313                            </template>
5314                        </template>
5315                    </div>
5316                </template>
5317
5318                <template x-if="itemsCount">
5319                    <div class="mt-auto">
5320                        
5321                        <div class="relative grid pb-4 pt-3 px-4 bg-white border-t border-black">
5322                            <p class="flex gap-4 font-bold text-xl leading-[26px] justify-between uppercase">
5323                                <span>Bag subtotal</span><span x-html="cart.subtotal"></span>
5324                            </p>
5325                            <div class="w-full flex gap-3 justify-between mt-3">
5326                                <a href="https://www.purdys.com/checkout/cart/"
5327                                   class="btn btn-secondary no-u
5327nderline w-full hover:no-underline"
5328                                >
5329                                    Edit Cart                                </a>
5330                                <a @click.prevent.stop="closeCartDrawer; $dispatch('toggle-authentication',
5331                                    {url: 'https://www.purdys.com/checkout/cart/'});"
5332                                   href="https://www.purdys.com/checkout/cart/"
5333                                   class="inline-flex btn btn-primary w-full hover:no-underline !border-0"
5334                                >
5335                                    Checkout                                </a>
5336                            </div>
5337                            <div x-html="getSectionDataExtraActions()"></div>
5338                                                    </div>
5339                    </div>
5340                </template>
5341
5342                            </div>
5343
5344            <button
5345              type="button"
5346              @click="closeCartDrawer"
5347              aria-label="Close&#x20;minicart"
5348              class="absolute top-0 end-0 p-4 text-black !border-0 !bg-transparent"
5349            >
5350                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none" class="text-black" aria-hidden="true">
5351<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
5352<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
5353</svg>
5354            </button>
5355        </div>
5356        <div class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50"
5357     style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.7);"
5358     x-show="isLoading"
5359     x-cloak
5360     x-transition:enter="ease-out duration-200"
5361     x-transition:enter-start="opacity-0"
5362     x-transition:enter-end="opacity-100"
5363     x-transition:leave="ease-in duration-200"
5364     x-transition:leave-start="opacity-100"
5365     x-transition:leave-end="opacity-0">
5366    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
5367    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
536712.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
5368    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
5369<title>loader</title></svg>
5370</div>
5371    </div>
5372
5373</section>
5374
5375    <!--Authentication Pop-Up-->
5376    
5376<script>
5377    function initAuthentication() {
5378        return {
5379            open: false,
5380            forceAuthentication: false,
5381            checkoutUrl: 'https://www.purdys.com/checkout/index/',
5382            errors: 0,
5383            hasCaptchaToken: 0,
5384            displayErrorMessage: false,
5385            errorMessages: [],
5386            setErrorMessages: function setErrorMessages(messages) {
5387                this.errorMessages = [messages];
5388                this.displayErrorMessage = this.errorMessages.length;
5389            },
5390            submitForm: function() {
5391                // Do not rename $form, the variable is expected to be declared in the recaptcha output
5392                const $form = document.querySelector('#login-form');
5393                
5394                if (this.errors === 0) {
5395                    this.dispatchLoginRequest($form);
5396                }
5397            },
5398            onPrivateContentLoaded: function(data) {
5399                const isLoggedIn = data.customer && data.customer.firstname;
5400                if (data.cart && !isLoggedIn) {
5401                    this.forceAuthentication = !data.cart.isGuestCheckoutAllowed;
5402                }
5403            },
5404            redirectIfAuthenticated: function(event) {
5405                if (event.detail && event.detail.url) {
5406                    this.checkoutUrl = event.detail.url;
5407                }
5408                if (!this.forceAuthentication) {
5409                    window.location.href = this.checkoutUrl;
5410                }
5411            },
5412            dispatchLoginRequest: function(form) {
5413                this.isLoading = true;
5414                const username = this.$refs['customer-email'].value;
5415                const password = this.$refs['customer-password'].value;
5416                const formKey = hyva.getFormKey();
5417                const bodyFields = {
5418                    'username': username,
5419                    'password': password,
5420                    'formKey': formKey
5421                };
5422                                const fieldName = '';
5423                const recaptchaField = fieldName && form[fieldName];
5424                if (recaptchaField) {
5425                    bodyFields[fieldName] = recaptchaField.value;
5426                }
5427                fetch('https://www.purdys.com/customer/ajax/login/', {
5428                    method: 'POST',
5429                    headers: {
5430                        'Content-Type': 'application/json',
5431                        'X-Requested-With': 'XMLHttpRequest'
5432                    },
5433                    body: JSON.stringify(bodyFields)
5434                }).then(response => {
5435                    return response.json()
5436                }).then(data => {
5437                    this.isLoading = false;
5438                    if (data.errors) {
5439                        dispatchMessages([{
5440                            type: 'error',
5441                            text: data.message
5442                        }], 5000);
5443                        this.errors = 1;
5444                        this.hasCaptchaToken = 0;
5445                    } else {
5446                        window.location.href = this.checkoutUrl;
5447                    }
5448                });
5449            }
5450        }
5451    }
5452</script>
5452
5453<section id="authentication-popup"
5454    x-data="initAuthentication()"
5455    @private-content-loaded.window="onPrivateContentLoaded($event.detail.data)"
5456    @toggle-authentication.window="open = forceAuthentication; redirectIfAuthenticated(event)"
5457    @keydown.window.escape="open = false">
5458    <div
5459        class="backdrop"
5460        aria-hidden="true"
5461        x-cloak
5462        x-show="open"
5463        x-transition:enter="ease-in-out duration-500"
5464        x-transition:enter-start="opacity-0"
5465        x-transition:enter-end="opacity-100"
5466        x-transition:leave="ease-in-out duration-500"
5467        x-transition:leave-start="opacity-100"
5468        x-transition:leave-end="opacity-0"
5469        @click="open = false"></div>
5470    <div role="dialog"
5471        aria-modal="true"
5472        @click.outside="open = false"
5473        class="inset-y-0 right-0 z-30 flex max-w-full fixed"
5474        x-cloak
5475        x-show="open">
5476        <div class="relative w-screen max-w-md pt-16 bg-container-lighter"
5477            x-show="open"
5478            x-cloak=""
5479            x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
5480            x-transition:enter-start="translate-x-full"
5481            x-transition:enter-end="translate-x-0"
5482            x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
5483            x-transition:leave-start="translate-x-0"
5484            x-transition:leave-end="translate-x-full">
5485            <div
5486                x-show="open"
5487                x-cloak=""
5488                x-transition:enter="ease-in-out duration-500"
5489                x-transition:enter-start="opacity-0"
5490                x-transition:enter-end="opacity-100"
5491                x-transition:leave="ease-in-out duration-500"
5492                x-transition:leave-start="opacity-100"
5493                x-transition:leave-end="opacity-0" class="absolute top-0 right-2 flex p-2 mt-2">
5494                <button
5495                    type="button"
5496                    @click="open = false;"
5497                    aria-label="Close&#x20;panel"
5498                    class="p-2 text-gray-300 transition duration-150 ease-in-out hover:text-black">
5499                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" role="img">
5500<path d="M3.3335 16.6667L16.6668 3.33337" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
5501<path d="M16.6668 16.6666L3.3335 3.33329" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
5502<title>Close panel</title></svg>
5503                </button>
5504            </div>
5505            <template x-if="open">
5506                <div class="flex flex-col h-full py-6 space-y-6 bg-white shadow-xl overflow-y-auto">
5507                    <div class="block-customer-login bg-container border border-container mx-4 p-4 shadow-sm">
5508                        <p id="authenticate-customer-login" class="text-lg leading-7 text-gray-900">
5509                            <strong class="font-medium">Checkout using your account</strong>
5510                        </p>
5511
5512                        <form class="form form-login"
5513                            method="post"
5514                            @submit.prevent="submitForm();"
5515                            id="login-form">
5516                                                        <div class="fieldset login">
5517                                <div class="field email required">
5518                                    <label class="label" for="form-login-username" form="login-form">
5519                                        <span>Email Address</span>
5520                                    </label>
5521                                    <div class="control">
5522                                        <input name="username"
5523                                            id="form-login-username"
5524                                            x-ref="customer-email"
5525                                            @change="errors = 0"
5526                                            type="email"
5527                                            required
5528                                            autocomplete="off"
5529                                            class="form-input input-text">
5530                                    </div>
5531                                </div>
5532                                <div class="field password required">
5533                                    <label for="form-login-password" class="label" form="login-form">
5534                                        <span>Password</span>
5535                                    </label>
5536                                    <div class="control">
5537                                        <input name="password"
5538                                            id="form-login-password"
5539                                            type="password"
5540                                            class="form-input input-text"
5541                                            required
5542                                            x-ref="customer-password"
5543                                            autocomplete="off"
5544                                            @change="errors = 0">
5545                                    </div>
5546                                </div>
5547
5548                                <input name="context" type="hidden" value="checkout" />
5549                                <div class="actions-toolbar flex justify-between pt-6 pb-2 items-center">
5550                                    <button type="submit"                                         class="inline-flex btn btn-primary disabled:opacity-75">
5551                                        Sign In                                    </button>
5552                                    <a href="https://www.purdys.com/customer/account/forgotpassword/">
5553                                        Forgot Your Password?                                    </a>
5554                                </div>
5555
5556                            </div>
5557                        </form>
5558                    </div>
5559                    <div class="mx-4">
5560                                            </div>
5561                    <div class="block-new-customer bg-container border border-container mx-4 p-4 shadow-sm">
5562                        <p id="authenticate-new-customer" class="text-lg mb-2 leading-7 text-gray-900">
5563                            <strong class="font-medium">Checkout as a new customer</strong>
5564                        </p>
5565
5566                        <div class="block-content">
5567                            <p class="mb-1">
5568                                Creating an account has many benefits:                            </p>
5569                            <ul class="list-disc pl-5">
5570                                <li> See order and shipping status</li>
5571                                <li> Track order history</li>
5572                                <li> Check out faster</li>
5573                            </ul>
5574                            <div class="actions-toolbar flex justify-between mt-6 mb-2 items-center">
5575                                <a href="https://www.purdys.com/customer/account/create/"
5576                                    class="inline-flex btn btn-primary">
5577                                    Create an Account                                </a>
5578                            </div>
5579                        </div>
5580                    </div>
5581                </div>
5582            </template>
5583        </div>
5584    </div>
5585</section>
5586</div>
5587
5588<div class="page messages">
5588<script>
5589        function initMessages() {
5590        "use strict";
5591        return {
5592            messages: window.mageMessages || [],
5593            isEmpty() {
5594                return this.messages.reduce(
5595                    function (isEmpty, message) {
5596                        return isEmpty && message === undefined
5597                    }, true
5598                )
5599            },
5600            removeMessage(messageIndex) {
5601                this.messages[messageIndex] = undefined;
5602            },
5603            addMessages(messages, hideAfter) {
5604                messages.map((message) => {
5605                    this.messages = this.messages.concat(message);
5606                    if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) {
5607                        hideAfter = window.defaultSuccessMessageTimeout;
5608                    }
5609                    if (hideAfter) {
5610                        this.setHideTimeOut(this.messages.length -1, hideAfter);
5611                    }
5612                });
5613            },
5614            setHideTimeOut(messageIndex, hideAfter) {
5615                setTimeout((messageIndex) => {
5616                    this.removeMessage(messageIndex);
5617                }, hideAfter, messageIndex);
5618            },
5619            getIcon(type) {
5620                switch (type) {
5621                    case 'success':
5622                        return "<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" role=\"img\">\n<path d=\"M10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10C0 4.47715 4.47715 0 10 0ZM10 1.66667C5.39763 1.66667 1.66667 5.39763 1.66667 10C1.66667 14.6024 5.39763 18.3333 10 18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667ZM12.8019 7.44548C13.0746 7.1758 13.5145 7.17846 13.7842 7.45117C14.0538 7.72389 14.0512 8.16376 13.7785 8.43343L9.47754 12.6864C9.20708 12.9538 8.77157 12.9537 8.50098 12.6864L6.51937 10.7284C6.24671 10.4589 6.24367 10.0198 6.51286 9.74691C6.78233 9.47413 7.22226 9.47105 7.49512 9.7404L8.98926 11.2158L12.8019 7.44548Z\" fill=\"currentColor\"\/>\n<title>circle-check<\/title><\/svg>\n";
5623                    case 'error':
5624                        return "<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" role=\"img\">\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M6.03085 6.04273C6.3053 5.77482 6.75026 5.77482 7.02471 6.04273L10.0848 9.02986L12.9753 6.20823C13.2497 5.94032 13.6947 5.94032 13.9692 6.20823C14.2436 6.47614 14.2436 6.9105 13.9692 7.17841L11.0786 10L13.9692 12.8217C14.2436 13.0896 14.2436 13.5239 13.9692 13.7918C13.6947 14.0598 13.2497 14.0598 12.9753 13.7918L10.0848 10.9702L7.02471 13.9574C6.75026 14.2253 6.3053 14.2253 6.03085 13.9574C5.7564 13.6894 5.7564 13.2551 6.03085 12.9872L9.09091 10L6.03085 7.01291C5.7564 6.745 5.7564 6.31063 6.03085 6.04273Z\" fill=\"currentColor\"\/>\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M10 18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667C5.39763 1.66667 1.66667 5.39763 1.66667 10C1.66667 14.6024 5.39763 18.3333 10 18.3333ZM10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20Z\" fill=\"currentColor\"\/>\n<title>circle-x-mark<\/title><\/svg>\n";
5625                    case 'warning':
5626                        return "<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" role=\"img\">\n<path d=\"M11.1034 11.8717H8.93425L8.55425 5H11.4676L11.1034 11.8717ZM10.0267 15.735C9.21925 15.735 8.53841 15.0542 8.53841 14.2467C8.53841 13.455 9.21925 12.7742 10.0267 12.7742C10.8342 12.7742 11.4992 13.455 11.4992 14.2467C11.4992 15.0542 10.8342 15.735 10.0267 15.735Z\" fill=\"currentColor\"\/>\n<path d=\"M18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667C5.39763 1.66667 1.66667 5.39763 1.66667 10C1.66667 14.6024 5.39763 18.3333 10 18.3333V20C4.47715 20 0 15.5228 0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20V18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10Z\" fill=\"currentColor\"\/>\n<title>warning<\/title><\/svg>\n";
5627                    default:
5628                        return "<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" role=\"img\">\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M10 18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667C5.39763 1.66667 1.66667 5.39763 1.66667 10C1.66667 14.6024 5.39763 18.3333 10 18.3333ZM10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20Z\" fill=\"currentColor\"\/>
5628\n<path d=\"M9.23913 14.1667V7.5H10.7609V14.1667H9.23913ZM8.33333 14.1667V13.4144C8.33333 13.2933 8.36151 13.2025 8.41787 13.142C8.48229 13.0815 8.57085 13.0383 8.68357 13.0123L9.37198 12.8567L9.52899 14.1667H8.33333ZM10.471 14.1667L10.628 12.8567L11.3164 13.0123C11.4291 13.0383 11.5137 13.0815 11.57 13.142C11.6345 13.2025 11.6667 13.2933 11.6667 13.4144V14.1667H10.471ZM9.52899 7.5L9.37198 8.80999L8.68357 8.65434C8.57085 8.6284 8.48229 8.58517 8.41787 8.52464C8.36151 8.46412 8.33333 8.37332 8.33333 8.25227V7.5H9.52899Z\" fill=\"currentColor\"\/>\n<path d=\"M10.8333 5.83333C10.8333 6.29357 10.4602 6.66667 10 6.66667C9.53976 6.66667 9.16667 6.29357 9.16667 5.83333C9.16667 5.3731 9.53976 5 10 5C10.4602 5 10.8333 5.3731 10.8333 5.83333Z\" fill=\"currentColor\"\/>\n<title>information<\/title><\/svg>\n";
5629                }
5630            },
5631            getMessageStyle(type) {
5632                switch (type) {
5633                    case 'success':
5634                        return '[--message-lighter:theme(colors.green.light)] [--message:theme(colors.green.DEFAULT)] [--message-darker:theme(colors.green.900)]'
5635                    case 'error':
5636                        return '[--message-lighter:theme(colors.red.light)] [--message:theme(colors.red.DEFAULT)] [--message-darker:theme(colors.red.900)]'
5637                    case 'warning':
5638                        return '[--message-lighter:theme(colors.orange.light)] [--message:theme(colors.orange.DEFAULT)] [--message-darker:theme(colors.yellow.900)]'
5639                    case 'notice':
5640                    case 'info':
5641                        return '[--message-lighter:theme(colors.background.light)] [--message:theme(colors.primary.DEFAULT)] [--message-darker:theme(colors.blue.900)]'
5642                    default:
5643                        return '[--message-lighter:theme(colors.background.light)] [--message:theme(colors.primary.DEFAULT)] [--message-darker:theme(colors.slate.900)]'
5644                }
5645            },
5646            eventListeners: {
5647                ['@messages-loaded.window'](event) {
5648                    this.addMessages(event.detail.messages, event.detail.hideAfter)
5649                },
5650                ['@private-content-loaded.window'](event) {
5651                    const data = event.detail.data;
5652                    if (
5653                        data.messages &&
5654                        data.messages.messages &&
5655                        data.messages.messages.length
5656                    ) {
5657                        this.addMessages(data.messages.messages);
5658                    }
5659                },
5660                ['@clear-messages.window']() {
5661                    this.messages = [];
5662                }
5663            }
5664        }
5665    }
5666</script>
5666
5667<section
5668    id="messages"
5669    x-data="initMessages()"
5670    x-bind="eventListeners"
5671    aria-live="assertive"
5672    role="alert"
5673>
5674    <template x-if="!isEmpty()">
5675        <div class="messages container py-3">
5676            <template x-for="(message, index) in messages" :key="index">
5677                <template x-if="message">
5678                    <div
5679                        class="message items-stretch gap-4 rounded text-body-2 mb-6 last-of-type:mb-0
5680                            bg-[var(--message-lighter)] text-[var(--message)]                            px-5 py-4"
5681                        :ui-id="'message-' + message.type"
5682                        :class="getMessageStyle(message.type)"
5683                    >
5684                                                <div class="grow flex items-center gap-3">
5685                                                            <span x-html="getIcon(message.type)" class="fill-[var(--message)]"></span>
5686                                                        <span class="text-black font-normal body-2" x-html="message.text"></span>
5687                            <button
5688                                type="button"
5689                                class="ms-auto text-black !border-0 !bg-transparent !opacity-100"
5690                                aria-label="Close message"
5691                                @click.prevent="removeMessage(index)"
5692                            >
5693                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="24" height="24" aria-hidden="true">
5694  <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
5695</svg>
5696                            </button>
5697                        </div>
5698                    </div>
5699                </template>
5700            </template>
5701        </div>
5702    </template>
5703</section>
5704</div>
5705    
5705<script>
5706        'use strict';
5707
5708        const initTopmenuDesktop_6ab63817b9359 = () => ({
5709            openSubmenuId: null,
5710            hoverTimeout: null,
5711            hoverBridgeTimeout: null,
5712            openSubmenuWithDelay(menuNode) {
5713                // Clear any existing timeout
5714                if (this.hoverTimeout) {
5715                    clearTimeout(this.hoverTimeout)
5716                }
5717
5718                // Set new timeout to open submenu after 0.2 seconds
5719                this.hoverTimeout = setTimeout(() => {
5720                    this.openSubmenuId = menuNode
5721                }, 200)
5722            },
5723            clearHoverTimeout() {
5724                if (this.hoverTimeout) {
5725                    clearTimeout(this.hoverTimeout)
5726                    this.hoverTimeout = null
5727                }
5728            },
5729            onMainMenuMouseLeave() {
5730                // Clear the hover timeout
5731                this.clearHoverTimeout()
5732
5733                // Set a bridge timeout to keep submenu open briefly
5734                // This prevents closing when moving to submenu
5735                if (this.hoverBridgeTimeout) {
5736                    clearTimeout(this.hoverBridgeTimeout)
5737                }
5738                this.hoverBridgeTimeout = setTimeout(() => {
5739                    this.openSubmenuId = null
5740                }, 100)
5741            },
5742            onSubmenuMouseEnter() {
5743                // Clear bridge timeout when entering submenu
5744                if (this.hoverBridgeTimeout) {
5745                    clearTimeout(this.hoverBridgeTimeout)
5746                    this.hoverBridgeTimeout = null
5747                }
5748            },
5749            onSubmenuMouseLeave() {
5750                // Close submenu when leaving submenu area
5751                this.openSubmenuId = null
5752            },
5753            toggleSubmenu(menuNode) {
5754                if (menuNode === this.openSubmenuId) {
5755                    this.openSubmenuId = null
5756                    hyva.releaseFocus()
5757                } else {
5758                    this.openSubmenuId = menuNode
5759                    this.$nextTick(() => {
5760                        hyva.trapFocus(this.$refs['submenu-' + menuNode])
5761                    })
5762                }
5763            },
5764            onSubmenuEscape(event) {
5765                event.stopPropagation()
5766                this.$refs['sr-button-' + this.openSubmenuId]?.focus()
5767                this.openSubmenuId = null
5768            }
5769        })
5770    </script>
5770
5771
5772    <div x-data="initTopmenuDesktop_6ab63817b9359()"
5773         class="
5774            snowdog-desktop-menu
5775                        hidden w-full bg-primary-dark lg:block md:px-5 2xl:px-10
5776        "
5777    >
5778        <nav
5779            class="snowdog-topmenu-desktop lg:block"
5780            aria-label="Main&#x20;menu"
5781        >
5782            <ul
5783                class="relative flex flex-wrap justify-center w-fit m-auto"
5784                @mouseleave="onMainMenuMouseLeave()"
5785            >
5786                                    <li class="
5787                            group
5788                            flex items-center justify-between px-5 py-3.5 m-0 list-none hover:bg-white before:content-['']
5789                                                    "
5790                        :class="{
5791                            'bg-white shadow-md' : '1' && openSubmenuId === '80'
5792                        }"
5793                        @mouseenter="openSubmenuWithDelay('80')"
5794                        @mouseleave="onMainMenuMouseLeave()"
5795                        @keydown.escape="onSubmenuEscape"
5796                    >
5797                        <div
5798                                class="group uppercase [&>a]:font-bold [&>a]:no-underline [&>a]:text-white group-hover:[&>a]:!text-primary-dark"
5799                                :class="openSubmenuId === '80'
5800                                ? '[&>a]:!text-primary-dark'
5801                                : ''"
5802                        >
5803                            
5804<a href="https://www.purdys.com/fall"
5805   class="snowdog-menu-link "
5806                    data-menu="menu-80"
5807        >
5808    Fall</a>
5809                        </div>
5810                                                    <div class="relative">
5811                                <button
5812                                    type="button"
5813                                    class="flex items-center ml-2 transition-transform duration-300 border-0 hover:border-0 hover:bg-transparent"
5814                                    :class="{
5815                                        'rotate-180' : openSubmenuId === '80'
5816                                    }"
5817                                    x-ref="sr-button-80"
5818                                    :aria-expanded="openSubmenuId === '80' ? 'true' : 'false'"
5819                                    @click="toggleSubmenu('80')"
5820                                >
5821                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="text-white group-hover:!text-primary-dark [&amp;&gt;path]:stroke-[4px] transition-transform" aria-hidden="true" :class="openSubmenuId === '80' ? '!text-primary-dark group-hover:!text-primary-dark rotate-180' : ''">
5822<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5823</svg>
5824                                    <span class="sr-only">
5825                                        Toggle submenu for Fall                                    </span>
5826                                </button>
5827                            </div>
5828                                            </li>
5829                                                        <li class="
5830                            group
5831                            flex items-center justify-between px-5 py-3.5 m-0 list-none hover:bg-white before:content-['']
5832                                                    "
5833                        :class="{
5834                            'bg-white shadow-md' : '1' && openSubmenuId === '1559'
5835                        }"
5836                        @mouseenter="openSubmenuWithDelay('1559')"
5837                        @mouseleave="onMainMenuMouseLeave()"
5838                        @keydown.escape="onSubmenuEscape"
5839                    >
5840                        <div
5841                                class="group uppercase [&>a]:font-bold [&>a]:no-underline [&>a]:text-white group-hover:[&>a]:!text-primary-dark"
5842                                :class="openSubmenuId === '1559'
5843                                ? '[&>a]:!text-primary-dark'
5844                                : ''"
5845                        >
5846                            
5847<a href="https://www.purdys.com/chocolate"
5848   class="snowdog-menu-link "
5849                    data-menu="menu-1559"
5850        >
5851    Chocolate</a>
5852                        </div>
5853                                                    <div class="relative">
5854                                <button
5855                                    type="button"
5856                                    class="flex items-center ml-2 transition-transform duration-300 border-0 hover:border-0 hover:bg-transparent"
5857                                    :class="{
5858                                        'rotate-180' : openSubmenuId === '1559'
5859                                    }"
5860                                    x-ref="sr-button-1559"
5861                                    :aria-expanded="openSubmenuId === '1559' ? 'true' : 'false'"
5862                                    @click="toggleSubmenu('1559')"
5863                                >
5864                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="text-white group-hover:!text-primary-dark [&amp;&gt;path]:stroke-[4px] transition-transform" aria-hidden="true" :class="openSubmenuId === '1559' ? '!text-primary-dark group-hover:!text-primary-dark rotate-180' : ''">
5865<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5866</svg>
5867                                    <span class="sr-only">
5868                                        Toggle submenu for Chocolate                                    </span>
5869                                </button>
5870                            </div>
5871                                            </li>
5872                                                        <li class="
5873                            group
5874                            flex items-center justify-between px-5 py-3.5 m-0 list-none hover:bg-white before:content-['']
5875                                                    "
5876                        :class="{
5877                            'bg-white shadow-md' : '1' && openSubmenuId === '11'
5878                        }"
5879                        @mouseenter="openSubmenuWithDelay('11')"
5880                        @mouseleave="onMainMenuMouseLeave()"
5881                        @keydown.escape="onSubmenuEscape"
5882                    >
5883                        <div
5884                                class="group uppercase [&>a]:font-bold [&>a]:no-underline [&>a]:text-white group-hover:[&>a]:!text-primary-dark"
5885                                :class="openSubmenuId === '11'
5886                                ? '[&>a]:!text-primary-dark'
5887                                : ''"
5888                        >
5889                            
5890<a href="https://www.purdys.com/gifts"
5891   class="snowdog-menu-link "
5892                    data-menu="menu-11"
5893        >
5894    Gifts</a>
5895                        </div>
5896                                                    <div class="relative">
5897                                <button
5898                                    type="button"
5899                                    class="flex items-center ml-2 transition-transform duration-300 border-0 hover:border-0 hover:bg-transparent"
5900                                    :class="{
5901                                        'rotate-180' : openSubmenuId === '11'
5902                                    }"
5903                                    x-ref="sr-button-11"
5904                                    :aria-expanded="openSubmenuId === '11' ? 'true' : 'false'"
5905                                    @click="toggleSubmenu('11')"
5906                                >
5907                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="text-white group-hover:!text-primary-dark [&amp;&gt;path]:stroke-[4px] transition-transform" aria-hidden="true" :class="openSubmenuId === '11' ? '!text-primary-dark group-hover:!text-primary-dark rotate-180' : ''">
5908<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5909</svg>
5910                                    <span class="sr-only">
5911                                        Toggle submenu for Gifts                                    </span>
5912                                </button>
5913                            </div>
5914                                            </li>
5915                                                        <li class="
5916                            group
5917                            flex items-center justify-between px-5 py-3.5 m-0 list-none hover:bg-white before:content-['']
5918                                                    "
5919                        :class="{
5920                            'bg-white shadow-md' : '1' && openSubmenuId === '76'
5921                        }"
5922                        @mouseenter="openSubmenuWithDelay('76')"
5923                        @mouseleave="onMainMenuMouseLeave()"
5924                        @keydown.escape="onSubmenuEscape"
5925                    >
5926                        <div
5927                                class="group uppercase [&>a]:font-bold [&>a]:no-underline [&>a]:text-white group-hover:[&>a]:!text-primary-dark"
5928                                :class="openSubmenuId === '76'
5929                                ? '[&>a]:!text-primary-dark'
5930                                : ''"
5931                        >
5932                            
5933<a href="https://www.purdys.com/custom"
5934   class="snowdog-menu-link custom"
5935                    data-menu="menu-76"
5936        >
5937    Custom</a>
5938                        </div>
5939                                                    <div class="relative">
5940                                <button
5941                                    type="button"
5942                                    class="flex items-center ml-2 transition-transform duration-300 border-0 hover:border-0 hover:bg-transparent"
5943                                    :class="{
5944                                        'rotate-180' : openSubmenuId === '76'
5945                                    }"
5946                                    x-ref="sr-button-76"
5947                                    :aria-expanded="openSubmenuId === '76' ? 'true' : 'false'"
5948                                    @click="toggleSubmenu('76')"
5949                                >
5950                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="text-white group-hover:!text-primary-dark [&amp;&gt;path]:stroke-[4px] transition-transform" aria-hidden="true" :class="openSubmenuId === '76' ? '!text-primary-dark group-hover:!text-primary-dark rotate-180' : ''">
5951<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5952</svg>
5953                                    <span class="sr-only">
5954                                        Toggle submenu for Custom                                    </span>
5955                                </button>
5956                            </div>
5957                                            </li>
5958                                                        <li class="
5959                            group
5960                            flex items-center justify-between px-5 py-3.5 m-0 list-none hover:bg-white before:content-['']
5961                                                    "
5962                        :class="{
5963                            'bg-white shadow-md' : '1' && openSubmenuId === '2179'
5964                        }"
5965                        @mouseenter="openSubmenuWithDelay('2179')"
5966                        @mouseleave="onMainMenuMouseLeave()"
5967                        @keydown.escape="onSubmenuEscape"
5968                    >
5969                        <div
5970                                class="group uppercase [&>a]:font-bold [&>a]:no-underline [&>a]:text-white group-hover:[&>a]:!text-primary-dark"
5971                                :class="openSubmenuId === '2179'
5972                                ? '[&>a]:!text-primary-dark'
5973                                : ''"
5974                        >
5975                            
5976<a href="https://www.purdys.com/discover"
5977   class="snowdog-menu-link "
5978                    data-menu="menu-2179"
5979        >
5980    Discover</a>
5981                        </div>
5982                                                    <div class="relative">
5983                                <button
5984                                    type="button"
5985                                    class="flex items-center ml-2 transition-transform duration-300 border-0 hover:border-0 hover:bg-transparent"
5986                                    :class="{
5987                                        'rotate-180' : openSubmenuId === '2179'
5988                                    }"
5989                                    x-ref="sr-button-2179"
5990                                    :aria-expanded="openSubmenuId === '2179' ? 'true' : 'false'"
5991                                    @click="toggleSubmenu('2179')"
5992                                >
5993                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 20 20" fill="none" class="text-white group-hover:!text-primary-dark [&amp;&gt;path]:stroke-[4px] transition-transform" aria-hidden="true" :class="openSubmenuId === '2179' ? '!text-primary-dark group-hover:!text-primary-dark rotate-180' : ''">
5994<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5995</svg>
5996                                    <span class="sr-only">
5997                                        Toggle submenu for Discover                                    </span>
5998                                </button>
5999                            </div>
6000                                            </li>
6001                                                </ul>
6002        </nav>
6003            <div
6004    x-ref="submenu-80"
6005    class="absolute left-0 top-full w-full z-30 shadow-md bg-white flex overflow-hidden"
6006    style="transform-origin: top;"
6007    x-show="openSubmenuId === '80'"
6008    x-transition:enter="transition-all duration-300 ease-out"
6009    x-transition:enter-start="transform scale-y-0"
6010    x-transition:enter-end="transform scale-y-100"
6011    x-transition:leave="transition-all duration-200 ease-in"
6012    x-transition:leave-start="transform scale-y-100"
6013    x-transition:leave-end="transform scale-y-0"
6014    x-cloak
6015    @mouseenter="onSubmenuMouseEnter()"
6016    @mouseleave="onSubmenuMouseLeave()"
6017>
6018    <div class="min-[1660px]:!max-w-[1740px] mx-auto flex flex-row justify-between w-full min-h-[400px] max-h-[600px]
6019        md:px-5 2xl:px-10 py-10 gap-10 [&_a]:no-underline overflow-y-auto">
6020        <!-- Left column: items without children and without image -->
6021        <div
6022          class="flex flex-col pr-10 gap-4 justify-start
6023           [&_a]:text-xl [&_a]:leading-[26px] [&_a]:font-bold [&_a]:text-primary-dark [&_a:hover]:text-primary max-w-[278px]"
6024        >
6025                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6026                    
6027<a class="snowdog-menu-link "
6028    href="https://www.purdys.com/fall-gift-ideas"
6029            data-menu="menu-2328"
6030    >
6031    Discover Thanksgiving</a>
6032                                    </div>
6033                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6034                    
6035<a class="snowdog-menu-link "
6036    href="https://www.purdys.com/halloween-gift-ideas"
6037            data-menu="menu-2351"
6038    >
6039    Discover Halloween</a>
6040                                    </div>
6041                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6042                    
6043<a class="snowdog-menu-link "
6044    href="https://www.purdys.com/share-joy-share-chocolate"
6045            data-menu="menu-3763"
6046    >
6047    Maritimes Collection</a>
6048                                    </div>
6049                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6050                            <a href="https://www.purdys.com/almost-perfect-chocolates-145-kg"
6051        class="snowdog-menu-link "
6052                    data-menu="menu-81"
6053                        data-menu="menu-81"    >
6054        Almost Perfects    </a>
6055                                    </div>
6056                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6057                    
6058<a class="snowdog-menu-link "
6059    href="https://www.purdys.com/ice-cream"
6060            data-menu="menu-3749"
6061    >
6062    Ice Cream &amp; Ice Cream Bars</a>
6063                                    </div>
6064                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6065                    
6066<a href="https://www.purdys.com/gifts/canadian-collection"
6067   class="snowdog-menu-link "
6068                    data-menu="menu-3785"
6069        >
6070    Canadian Collection</a>
6071                                    </div>
6072                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6073                    
6074<a class="snowdog-menu-link "
6075    href="https://www.purdys.com/summer-delivery"
6076            data-menu="menu-2350"
6077    >
6078    Summer Shipping</a>
6079                                    </div>
6080                    </div>
6081
6082        <div class="flex flex-wrap xl:flex-nowrap flex-1 gap-x-10 justify-between">
6083            <!-- Main column: items with children -->
6084                            <div class="max-h-[439px] columns-3 column-gap-8 column-fill-auto max-w-[75%]">
6085                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6086                        <div
6087                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6088                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6089                        >
6090                                    <span class="flex "
6091        tabindex="0"
6092        data-menu="menu-82"    >
6093        Product Type    </span>
6094                                                    </div>
6095                        <ul class="space-y-3 ml-0">
6096                                                            <li
6097                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6098                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6099                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6100                                >
6101                                    
6102<a href="https://www.purdys.com/chocolate/boxed-chocolates"
6103   class="snowdog-menu-link "
6104                    data-menu="menu-286"
6105        >
6106    Boxed Chocolate</a>
6107                                                                    </li>
6108                                                            <li
6109                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6110                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6111                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6112                                >
6113                                    
6114<a href="https://www.purdys.com/fall/halloween"
6115   class="snowdog-menu-link "
6116                    data-menu="menu-3779"
6117        >
6118    Halloween Chocolate</a>
6119                                                                    </li>
6120                                                            <li
6121                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6122                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6123                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6124                                >
6125                                    
6126<a href="https://www.purdys.com/fall/thanksgiving"
6127   class="snowdog-menu-link "
6128                    data-menu="menu-3782"
6129        >
6130    Thanksgiving Chocolate</a>
6131                                                                    </li>
6132                                                            <li
6133                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6134                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6135                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6136                                >
6137                                    
6138<a href="https://www.purdys.com/gifts/gift-baskets-and-sets"
6139   class="snowdog-menu-link "
6140                    data-menu="menu-287"
6141        >
6142    Gift Baskets and Sets</a>
6143                                                                    </li>
6144                                                            <li
6145                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6146                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6147                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6148                                >
6149                                    
6150<a href="https://www.purdys.com/chocolate/mix-and-match-chocolates"
6151   class="snowdog-menu-link "
6152                    data-menu="menu-288"
6153        >
6154    Mix and Match Chocolates</a>
6155                                                                    </li>
6156                                                    </ul>
6157                    </div>
6158                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6159                        <div
6160                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6161                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6162                        >
6163                                    <span class="flex "
6164        tabindex="0"
6165        data-menu="menu-83"    >
6166        By Price    </span>
6167                                                    </div>
6168                        <ul class="space-y-3 ml-0">
6169                                                            <li
6170                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6171                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6172                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6173                                >
6174                                    
6175<a href="https://www.purdys.com/fall/fall-low"
6176   class="snowdog-menu-link "
6177                    data-menu="menu-290"
6178        >
6179    Under $20</a>
6180                                                                    </li>
6181                                                            <li
6182                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6183                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6184                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6185                                >
6186                                    
6187<a href="#"
6188   class="snowdog-menu-link "
6189                    data-menu="menu-291"
6190        >
6191    $20 to $50</a>
6192                                                                    </li>
6193                                                            <li
6194                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6195                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6196                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6197                                >
6198                                    
6199<a href="https://www.purdys.com/fall/fall-medium"
6200   class="snowdog-menu-link "
6201                    data-menu="menu-2167"
6202        >
6203    Over $50</a>
6204                                                                    </li>
6205                                                    </ul>
6206                    </div>
6207                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6208                        <div
6209                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6210                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6211                        >
6212                                    <span class="flex "
6213        tabindex="0"
6214        data-menu="menu-2170"    >
6215        Others    </span>
6216                                                    </div>
6217                        <ul class="space-y-3 ml-0">
6218                                                            <li
6219                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6220                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6221                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6222                                >
6223                                            <a href="https://www.purdys.com/build-a-box"
6224        class="snowdog-menu-link "
6225                    data-menu="menu-2173"
6226                        data-menu="menu-2173"    >
6227        Build-a-box    </a>
6228                                                                    </li>
6229                                                            <li
6230                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6231                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6232                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6233                                >
6234                                    
6235<a class="snowdog-menu-link "
6236    href="https://www.purdys.com/shipping-gift-guarantee"
6237            data-menu="menu-2176"
6238    >
6239    Shipping and Delivery</a>
6240                                                                    </li>
6241                                                    </ul>
6242                    </div>
6243                
6244                <!-- Items with special class "menu-second-column" -->
6245                            </div>
6246            
6247            <!-- Right column: feature block if present -->
6248                            <div class="flex flex-row gap-6 justify-start [&>div]:max-w-[240px]">
6249                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-center                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
6250                            <!-- Render the feature node using the vendor node_type template logic -->
6251                                        <a href="https://www.purdys.com/halloween-gift-tin-12pc"
6252           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
6253            tabindex="-1"
6254                    >
6255            <img src="https://www.purdys.com/media/snowdog/menu/node/b/a/banner-container_1_.png"
6256                alt="Halloween&#x20;Tins"
6257                loading="lazy"
6258                width="273"
6259                height="364"
6260            />
6261        </a>
6262        <a href="https://www.purdys.com/halloween-gift-tin-12pc"
6263        class="snowdog-menu-link menu-second-column&#x20;mega-menu-promo-img"
6264                    data-menu="menu-2260"
6265                        data-menu="menu-2260"    >
6266        Halloween Tins    </a>
6267                                                    </div>
6268                                    </div>
6269                    </div>
6270    </div>
6271</div>
6272    <div
6273    x-ref="submenu-1559"
6274    class="absolute left-0 top-full w-full z-30 shadow-md bg-white flex overflow-hidden"
6275    style="transform-origin: top;"
6276    x-show="openSubmenuId === '1559'"
6277    x-transition:enter="transition-all duration-300 ease-out"
6278    x-transition:enter-start="transform scale-y-0"
6279    x-transition:enter-end="transform scale-y-100"
6280    x-transition:leave="transition-all duration-200 ease-in"
6281    x-transition:leave-start="transform scale-y-100"
6282    x-transition:leave-end="transform scale-y-0"
6283    x-cloak
6284    @mouseenter="onSubmenuMouseEnter()"
6285    @mouseleave="onSubmenuMouseLeave()"
6286>
6287    <div class="min-[1660px]:!max-w-[1740px] mx-auto flex flex-row justify-between w-full min-h-[400px] max-h-[600px]
6288        md:px-5 2xl:px-10 py-10 gap-10 [&_a]:no-underline overflow-y-auto">
6289        <!-- Left column: items without children and without image -->
6290        <div
6291          class="flex flex-col pr-10 gap-4 justify-start
6292           [&_a]:text-xl [&_a]:leading-[26px] [&_a]:font-bold [&_a]:text-primary-dark [&_a:hover]:text-primary max-w-[278px]"
6293        >
6294                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6295                    
6296<a class="snowdog-menu-link "
6297    href="https://www.purdys.com/fall-gift-ideas"
6298            data-menu="menu-2324"
6299    >
6300    Discover Thanksgiving</a>
6301                                    </div>
6302                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6303                    
6304<a class="snowdog-menu-link "
6305    href="https://www.purdys.com/halloween-gift-ideas"
6306            data-menu="menu-2360"
6307    >
6308    Discover Halloween</a>
6309                                    </div>
6310                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6311                    
6312<a class="snowdog-menu-link "
6313    href="https://www.purdys.com/share-joy-share-chocolate"
6314            data-menu="menu-3766"
6315    >
6316    Maritimes Collection</a>
6317                                    </div>
6318                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6319                    
6320<a href="https://www.purdys.com/chocolate/boxed-chocolates"
6321   class="snowdog-menu-link "
6322                    data-menu="menu-1568"
6323        >
6324    Boxed Chocolate</a>
6325                                    </div>
6326                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6327                            <a href="https://www.purdys.com/almost-perfect-chocolates-145-kg"
6328        class="snowdog-menu-link "
6329                    data-menu="menu-3788"
6330                        data-menu="menu-3788"    >
6331        Almost Perfects    </a>
6332                                    </div>
6333                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6334                    
6335<a class="snowdog-menu-link "
6336    href="https://www.purdys.com/pistachio-chocolate"
6337            data-menu="menu-1721"
6338    >
6339    Pistachio </a>
6340                                    </div>
6341                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6342                            <a href="https://www.purdys.com/build-a-box"
6343        class="snowdog-menu-link "
6344                    data-menu="menu-1577"
6345                        data-menu="menu-1577"    >
6346        Build-a-box    </a>
6347                                    </div>
6348                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6349                    
6350<a href="https://www.purdys.com/chocolate/send-chocolates-free-shipping"
6351   class="snowdog-menu-link "
6352                    data-menu="menu-1583"
6353        >
6354    Free Shipping </a>
6355                                    </div>
6356                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6357                    
6358<a href="https://www.purdys.com/chocolate/online-exclusive-chocolates"
6359   class="snowdog-menu-link "
6360                    data-menu="menu-1586"
6361        >
6362    Online Exclusive</a>
6363                                    </div>
6364                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6365                    
6366<a href="https://www.purdys.com/chocolate/most-reviewed-chocolate"
6367   class="snowdog-menu-link "
6368                    data-menu="menu-1589"
6369        >
6370    Most Reviewed</a>
6371                                    </div>
6372                    </div>
6373
6374        <div class="flex flex-wrap xl:flex-nowrap flex-1 gap-x-10 justify-between">
6375            <!-- Main column: items with children -->
6376                            <div class="max-h-[500px] columns-3 column-gap-8 column-fill-auto max-w-[75%]">
6377                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6378                        <div
6379                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6380                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6381                        >
6382                                    <span class="flex "
6383        tabindex="0"
6384        data-menu="menu-1595"    >
6385        Bestsellers    </span>
6386                                                    </div>
6387                        <ul class="space-y-3 ml-0">
6388                                                            <li
6389                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6390                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6391                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6392                                >
6393                                    
6394<a href="https://www.purdys.com/chocolate/bestsellers"
6395   class="snowdog-menu-link "
6396                    data-menu="menu-1598"
6397        >
6398    All Bestsellers</a>
6399                                                                    </li>
6400                                                            <li
6401                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6402                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6403                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6404                                >
6405                                    
6406<a href="https://www.purdys.com/chocolate/chocolate-sweet-georgia-browns"
6407   class="snowdog-menu-link "
6408                    data-menu="menu-1601"
6409        >
6410    Sweet Georgia Browns</a>
6411                                                                    </li>
6412                                                            <li
6413                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6414                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6415                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6416                                >
6417                                    
6418<a href="https://www.purdys.com/chocolate/chocolate-hedgehogs"
6419   class="snowdog-menu-link "
6420                    data-menu="menu-1604"
6421        >
6422    Hedgehogs</a>
6423                                                                    </li>
6424                                                            <li
6425                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6426                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6427                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6428                                >
6429                                    
6430<a href="https://www.purdys.com/chocolate/salted-caramel-chocolates"
6431   class="snowdog-menu-link "
6432                    data-menu="menu-1607"
6433        >
6434    Himalayan Pink Salt Caramels</a>
6435                                                                    </li>
6436                                                    </ul>
6437                    </div>
6438                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6439                        <div
6440                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6441                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6442                        >
6443                                    <span class="flex "
6444        tabindex="0"
6445        data-menu="menu-1610"    >
6446        CHOCOLATE TYPE    </span>
6447                                                    </div>
6448                        <ul class="space-y-3 ml-0">
6449                                                            <li
6450                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6451                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6452                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6453                                >
6454                                    
6455<a href="https://www.purdys.com/chocolate/dark-chocolate"
6456   class="snowdog-menu-link "
6457                    data-menu="menu-1616"
6458        >
6459    Dark Chocolate</a>
6460                                                                    </li>
6461                                                            <li
6462                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6463                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6464                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6465                                >
6466                                    
6467<a href="https://www.purdys.com/chocolate/milk-chocolate"
6468   class="snowdog-menu-link "
6469                    data-menu="menu-1619"
6470        >
6471    Milk Chocolate</a>
6472                                                                    </li>
6473                                                            <li
6474                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6475                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6476                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6477                                >
6478                                    
6479<a href="https://www.purdys.com/chocolate/white-chocolate"
6480   class="snowdog-menu-link "
6481                    data-menu="menu-1622"
6482        >
6483    White Chocolate</a>
6484                                                                    </li>
6485                                                            <li
6486                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6487                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6488                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6489                                >
6490                                    
6491<a href="https://www.purdys.com/chocolate/no-sugar-added"
6492   class="snowdog-menu-link "
6493                    data-menu="menu-1625"
6494        >
6495    No Sugar Added</a>
6496                                                                    </li>
6497                                                            <li
6498                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6499                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6500                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6501                                >
6502                                    
6503<a class="snowdog-menu-link "
6504    href="https://www.purdys.com/plant-based-chocolate"
6505            data-menu="menu-1613"
6506    >
6507    Plant-based Chocolate</a>
6508                                                                    </li>
6509                                                            <li
6510                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6511                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6512                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6513                                >
6514                                    
6515<a href="https://www.purdys.com/chocolate/fruit-flavoured-chocolate"
6516   class="snowdog-menu-link "
6517                    data-menu="menu-1628"
6518        >
6519    Fruit Flavours</a>
6520                                                                    </li>
6521                                                    </ul>
6522                    </div>
6523                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6524                        <div
6525                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6526                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6527                        >
6528                                    <span class="flex "
6529        tabindex="0"
6530        data-menu="menu-1724"    >
6531        COLLECTIONS    </span>
6532                                                    </div>
6533                        <ul class="space-y-3 ml-0">
6534                                                            <li
6535                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6536                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6537                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6538                                >
6539                                    
6540<a href="https://www.purdys.com/chocolate/see-all"
6541   class="snowdog-menu-link menu-second-column"
6542                    data-menu="menu-1727"
6543        >
6544    Chocolate</a>
6545                                                                    </li>
6546                                                            <li
6547                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6548                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6549                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6550                                >
6551                                    
6552<a href="https://www.purdys.com/chocolate/chocolate-bars-snacks"
6553   class="snowdog-menu-link "
6554                    data-menu="menu-1730"
6555        >
6556    Bars and Snacks</a>
6557                                                                    </li>
6558                                                            <li
6559                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6560                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6561                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6562                                >
6563                                    
6564<a href="https://www.purdys.com/chocolate/mint-chocolates"
6565   class="snowdog-menu-link "
6566                    data-menu="menu-1733"
6567        >
6568    Mint Chocolates</a>
6569                                                                    </li>
6570                                                            <li
6571                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6572                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6573                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6574                                >
6575                                    
6576<a href="https://www.purdys.com/chocolate/nuts-and-caramels"
6577   class="snowdog-menu-link "
6578                    data-menu="menu-1736"
6579        >
6580    Nuts and Caramels</a>
6581                                                                    </li>
6582                                                            <li
6583                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6584                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6585                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6586                                >
6587                                    
6588<a href="https://www.purdys.com/chocolate/assorted-chocolate"
6589   class="snowdog-menu-link "
6590                    data-menu="menu-1739"
6591        >
6592    Assorted Chocolate</a>
6593                                                                    </li>
6594                                                            <li
6595                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6596                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6597                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6598                                >
6599                                    
6600<a href="https://www.purdys.com/chocolate/peanut-butter"
6601   class="snowdog-menu-link "
6602                    data-menu="menu-1742"
6603        >
6604    Peanut Butter</a>
6605                                                                    </li>
6606                                                            <li
6607                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6608                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6609                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6610                                >
6611                                    
6612<a href="https://www.purdys.com/chocolate/fruits-ginger-and-spices"
6613   class="snowdog-menu-link "
6614                    data-menu="menu-1745"
6615        >
6616    Fruits, Ginger and Spices</a>
6617                                                                    </li>
6618                                                            <li
6619                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6620                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6621                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6622                                >
6623                                    
6624<a href="https://www.purdys.com/chocolate/chocolate-truffles"
6625   class="snowdog-menu-link "
6626                    data-menu="menu-1748"
6627        >
6628    Chocolate Truffles</a>
6629                                                                    </li>
6630                                                            <li
6631                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6632                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6633                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6634                                >
6635                                    
6636<a href="https://www.purdys.com/chocolate/brittle-bark-and-toffee"
6637   class="snowdog-menu-link "
6638                    data-menu="menu-1751"
6639        >
6640    Chocolate Bark, Brittle and Toffee</a>
6641                                                                    </li>
6642                                                            <li
6643                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6644                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6645                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6646                                >
6647                                    
6648<a href="https://www.purdys.com/chocolate/from-the-chocolate-kitchen"
6649   class="snowdog-menu-link "
6650                    data-menu="menu-1754"
6651        >
6652    From The Chocolate Kitchen</a>
6653                                                                    </li>
6654                                                            <li
6655                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6656                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6657                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6658                                >
6659                                    
6660<a href="https://www.purdys.com/chocolate/kosher"
6661   class="snowdog-menu-link "
6662                    data-menu="menu-1763"
6663        >
6664    Kosher Chocolate</a>
6665                                                                    </li>
6666                                                    </ul>
6667                    </div>
6668                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6669                        <div
6670                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6671                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6672                        >
6673                                    <span class="flex "
6674        tabindex="0"
6675        data-menu="menu-1673"    >
6676        SALE &amp; SPECIALS    </span>
6677                                                    </div>
6678                        <ul class="space-y-3 ml-0">
6679                                                            <li
6680                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6681                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6682                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6683                                >
6684                                    
6685<a href="https://www.purdys.com/chocolate/special-offers"
6686   class="snowdog-menu-link "
6687                    data-menu="menu-1676"
6688        >
6689    Special Offers</a>
6690                                                                    </li>
6691                                                            <li
6692                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6693                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6694                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6695                                >
6696                                    
6697<a href="https://www.purdys.com/chocolate/bulk-chocolate"
6698   class="snowdog-menu-link "
6699                    data-menu="menu-1679"
6700        >
6701    Bulk Chocolate</a>
6702                                                                    </li>
6703                                                            <li
6704                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6705                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6706                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6707                                >
6708                                    
6709<a href="https://www.purdys.com/chocolate/mix-match-low"
6710   class="snowdog-menu-link "
6711                    data-menu="menu-1682"
6712        >
6713    Mix and Match 3 for $11.75</a>
6714                                                                    </li>
6715                                                            <li
6716                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6717                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6718                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6719                                >
6720                                    
6721<a href="https://www.purdys.com/chocolate/mix-match-medium"
6722   class="snowdog-menu-link "
6723                    data-menu="menu-1685"
6724        >
6725    Mix and Match 3 for $12.50</a>
6726                                                                    </li>
6727                                                            <li
6728                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6729                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6730                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6731                                >
6732                                    
6733<a href="https://www.purdys.com/chocolate/mix-match-high"
6734   class="snowdog-menu-link "
6735                    data-menu="menu-1688"
6736        >
6737    Mix and Match 3 for $23</a>
6738                                                                    </li>
6739                                                    </ul>
6740                    </div>
6741                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6742                        <div
6743                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6744                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6745                        >
6746                                    <span class="flex "
6747        tabindex="0"
6748        data-menu="menu-1766"    >
6749        OTHER    </span>
6750                                                    </div>
6751                        <ul class="space-y-3 ml-0">
6752                                                            <li
6753                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6754                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6755                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6756                                >
6757                                    
6758<a class="snowdog-menu-link "
6759    href="https://www.purdys.com/ice-cream"
6760            data-menu="menu-2334"
6761    >
6762    Ice Cream &amp; Ice Cream Bars</a>
6763                                                                    </li>
6764                                                            <li
6765                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6766                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6767                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6768                                >
6769                                    
6770<a class="snowdog-menu-link "
6771    href="https://www.purdys.com/chocolate-legend"
6772            data-menu="menu-1769"
6773    >
6774    Chocolate Legend </a>
6775                                                                    </li>
6776                                                            <li
6777                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6778                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6779                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6780                                >
6781                                    
6782<a href="https://www.purdys.com/chocolate/new"
6783   class="snowdog-menu-link "
6784                    data-menu="menu-1772"
6785        >
6786    New</a>
6787                                                                    </li>
6788                                                            <li
6789                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6790                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6791                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6792                                >
6793                                    
6794<a class="snowdog-menu-link "
6795    href="https://www.purdys.com/shipping-gift-guarantee"
6796            data-menu="menu-1775"
6797    >
6798    Shipping Deadlines</a>
6799                                                                    </li>
6800                                                    </ul>
6801                    </div>
6802                
6803                <!-- Items with special class "menu-second-column" -->
6804                            </div>
6805            
6806            <!-- Right column: feature block if present -->
6807                            <div class="flex flex-row gap-6 justify-start [&>div]:max-w-[240px]">
6808                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-center                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
6809                            <!-- Render the feature node using the vendor node_type template logic -->
6810                                        <a href="https://www.purdys.com/coffin-gift-box"
6811           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
6812            tabindex="-1"
6813                    >
6814            <img src="https://www.purdys.com/media/snowdog/menu/node/b/a/banner-container_1.png"
6815                alt="Coffin&#x20;Box"
6816                loading="lazy"
6817                width="273"
6818                height="364"
6819            />
6820        </a>
6821        <a href="https://www.purdys.com/coffin-gift-box"
6822        class="snowdog-menu-link menu-second-column&#x20;mega-menu-promo-img"
6823                    data-menu="menu-2122"
6824                        data-menu="menu-2122"    >
6825        Coffin Box    </a>
6826                                                    </div>
6827                                    </div>
6828                    </div>
6829    </div>
6830</div>
6831    <div
6832    x-ref="submenu-11"
6833    class="absolute left-0 top-full w-full z-30 shadow-md bg-white flex overflow-hidden"
6834    style="transform-origin: top;"
6835    x-show="openSubmenuId === '11'"
6836    x-transition:enter="transition-all duration-300 ease-out"
6837    x-transition:enter-start="transform scale-y-0"
6838    x-transition:enter-end="transform scale-y-100"
6839    x-transition:leave="transition-all duration-200 ease-in"
6840    x-transition:leave-start="transform scale-y-100"
6841    x-transition:leave-end="transform scale-y-0"
6842    x-cloak
6843    @mouseenter="onSubmenuMouseEnter()"
6844    @mouseleave="onSubmenuMouseLeave()"
6845>
6846    <div class="min-[1660px]:!max-w-[1740px] mx-auto flex flex-row justify-between w-full min-h-[400px] max-h-[600px]
6847        md:px-5 2xl:px-10 py-10 gap-10 [&_a]:no-underline overflow-y-auto">
6848        <!-- Left column: items without children and without image -->
6849        <div
6850          class="flex flex-col pr-10 gap-4 justify-start
6851           [&_a]:text-xl [&_a]:leading-[26px] [&_a]:font-bold [&_a]:text-primary-dark [&_a:hover]:text-primary max-w-[278px]"
6852        >
6853                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6854                    
6855<a class="snowdog-menu-link "
6856    href="https://www.purdys.com/fall-gift-ideas"
6857            data-menu="menu-2363"
6858    >
6859    Fall Gift Ideas</a>
6860                                    </div>
6861                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6862                    
6863<a class="snowdog-menu-link "
6864    href="https://www.purdys.com/halloween-gift-ideas"
6865            data-menu="menu-3754"
6866    >
6867    Halloween Gift Ideas</a>
6868                                    </div>
6869                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6870                    
6871<a href="https://www.purdys.com/gifts/canadian-collection"
6872   class="snowdog-menu-link "
6873                    data-menu="menu-3760"
6874        >
6875    Canadian Souvenir</a>
6876                                    </div>
6877                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6878                    
6879<a class="snowdog-menu-link "
6880    href="https://www.purdys.com/pistachio-chocolate"
6881            data-menu="menu-232"
6882    >
6883    Pistachio Chocolates</a>
6884                                    </div>
6885                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
6886                            <a href="https://www.purdys.com/build-a-box"
6887        class="snowdog-menu-link "
6888                    data-menu="menu-1528"
6889                        data-menu="menu-1528"    >
6890        Build-a-box    </a>
6891                                    </div>
6892                    </div>
6893
6894        <div class="flex flex-wrap xl:flex-nowrap flex-1 gap-x-10 justify-between">
6895            <!-- Main column: items with children -->
6896                            <div class="max-h-[439px] columns-3 column-gap-8 column-fill-auto max-w-[75%]">
6897                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6898                        <div
6899                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6900                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6901                        >
6902                                    <span class="flex "
6903        tabindex="0"
6904        data-menu="menu-12"    >
6905        By Occasion    </span>
6906                                                    </div>
6907                        <ul class="space-y-3 ml-0">
6908                                                            <li
6909                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6910                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6911                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6912                                >
6913                                    
6914<a href="https://www.purdys.com/gifts/see-all-gifts"
6915   class="snowdog-menu-link "
6916                    data-menu="menu-267"
6917        >
6918    See All Gifts</a>
6919                                                                    </li>
6920                                                            <li
6921                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6922                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6923                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6924                                >
6925                                    
6926<a href="https://www.purdys.com/gifts/thank-you"
6927   class="snowdog-menu-link "
6928                    data-menu="menu-266"
6929        >
6930    Thank You Gifts</a>
6931                                                                    </li>
6932                                                            <li
6933                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6934                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6935                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6936                                >
6937                                    
6938<a href="https://www.purdys.com/gifts/birthday"
6939   class="snowdog-menu-link "
6940                    data-menu="menu-265"
6941        >
6942    Birthday Gifts</a>
6943                                                                    </li>
6944                                                            <li
6945                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6946                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6947                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6948                                >
6949                                    
6950<a href="https://www.purdys.com/gifts/anniversary"
6951   class="snowdog-menu-link "
6952                    data-menu="menu-268"
6953        >
6954    Anniversary Gifts</a>
6955                                                                    </li>
6956                                                            <li
6957                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6958                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6959                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6960                                >
6961                                    
6962<a href="https://www.purdys.com/gifts/spread-joy"
6963   class="snowdog-menu-link "
6964                    data-menu="menu-269"
6965        >
6966    Spread Joy</a>
6967                                                                    </li>
6968                                                            <li
6969                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6970                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6971                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6972                                >
6973                                    
6974<a href="https://www.purdys.com/discover/wedding-bridal-favours"
6975   class="snowdog-menu-link "
6976                    data-menu="menu-270"
6977        >
6978    Guide to Purdys Wedding Favours</a>
6979                                                                    </li>
6980                                                            <li
6981                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
6982                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
6983                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
6984                                >
6985                                    
6986<a href="https://www.purdys.com/chocolate/favours"
6987   class="snowdog-menu-link "
6988                    data-menu="menu-272"
6989        >
6990    See all Custom Favours</a>
6991                                                                    </li>
6992                                                    </ul>
6993                    </div>
6994                                    <div class="break-inside-avoid mb-10 inline-block w-full">
6995                        <div
6996                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
6997                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
6998                        >
6999                                    <span class="flex "
7000        tabindex="0"
7001        data-menu="menu-13"    >
7002        Product Type    </span>
7003                                                    </div>
7004                        <ul class="space-y-3 ml-0">
7005                                                            <li
7006                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7007                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7008                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7009                                >
7010                                    
7011<a href="https://www.purdys.com/gifts/gift-baskets-and-sets"
7012   class="snowdog-menu-link "
7013                    data-menu="menu-273"
7014        >
7015    Gift Baskets and Sets</a>
7016                                                                    </li>
7017                                                            <li
7018                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7019                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7020                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7021                                >
7022                                    
7023<a href="https://www.purdys.com/chocolate/boxed-chocolates"
7024   class="snowdog-menu-link "
7025                    data-menu="menu-274"
7026        >
7027    Gift Boxes</a>
7028                                                                    </li>
7029                                                            <li
7030                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7031                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7032                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7033                                >
7034                                    
7035<a href="https://www.purdys.com/chocolate/bestsellers"
7036   class="snowdog-menu-link "
7037                    data-menu="menu-3"
7038        >
7039    Bestsellers</a>
7040                                                                    </li>
7041                                                            <li
7042                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7043                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7044                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7045                                >
7046                                    
7047<a class="snowdog-menu-link "
7048    href="https://www.purdys.com/gift-cards"
7049            data-menu="menu-275"
7050    >
7051    Gift Card </a>
7052                                                                    </li>
7053                                                            <li
7054                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7055                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7056                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7057                                >
7058                                    
7059<a href="https://www.purdys.com/chocolate/kosher"
7060   class="snowdog-menu-link "
7061                    data-menu="menu-1513"
7062        >
7063    Kosher Chocolate</a>
7064                                                                    </li>
7065                                                    </ul>
7066                    </div>
7067                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7068                        <div
7069                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7070                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7071                        >
7072                                    <span class="flex "
7073        tabindex="0"
7074        data-menu="menu-14"    >
7075        Corporate Gifts     </span>
7076                                                    </div>
7077                        <ul class="space-y-3 ml-0">
7078                                                            <li
7079                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7080                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7081                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7082                                >
7083                                    
7084<a class="snowdog-menu-link "
7085    href="https://www.purdys.com/corporate-gifts"
7086            data-menu="menu-277"
7087    >
7088    Corporate Gifts</a>
7089                                                                    </li>
7090                                                            <li
7091                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7092                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7093                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7094                                >
7095                                    
7096<a class="snowdog-menu-link "
7097    href="https://www.purdys.com/corporate-gifting"
7098            data-menu="menu-1988"
7099    >
7100    Branded Corporate Gifts</a>
7101                                                                    </li>
7102                                                            <li
7103                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7104                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7105                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7106                                >
7107                                    
7108<a href="https://www.purdys.com/gifts/employee-gifts"
7109   class="snowdog-menu-link "
7110                    data-menu="menu-278"
7111        >
7112    Employee Gifts and Snacks</a>
7113                                                                    </li>
7114                                                    </ul>
7115                    </div>
7116                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7117                        <div
7118                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7119                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7120                        >
7121                                    <span class="flex "
7122        tabindex="0"
7123        data-menu="menu-15"    >
7124        By Price    </span>
7125                                                    </div>
7126                        <ul class="space-y-3 ml-0">
7127                                                            <li
7128                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7129                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7130                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7131                                >
7132                                    
7133<a href="https://www.purdys.com/gifts/gifts-low"
7134   class="snowdog-menu-link "
7135                    data-menu="menu-279"
7136        >
7137    Gift Under $20</a>
7138                                                                    </li>
7139                                                            <li
7140                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7141                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7142                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7143                                >
7144                                    
7145<a href="https://www.purdys.com/gifts/gifts-medium"
7146   class="snowdog-menu-link "
7147                    data-menu="menu-280"
7148        >
7149    Gifts $20 to $50</a>
7150                                                                    </li>
7151                                                            <li
7152                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7153                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7154                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7155                                >
7156                                    
7157<a href="https://www.purdys.com/gifts/gifts-high"
7158   class="snowdog-menu-link "
7159                    data-menu="menu-281"
7160        >
7161    Gifts Over $50</a>
7162                                                                    </li>
7163                                                    </ul>
7164                    </div>
7165                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7166                        <div
7167                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7168                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7169                        >
7170                                    <span class="flex "
7171        tabindex="0"
7172        data-menu="menu-16"    >
7173        Other    </span>
7174                                                    </div>
7175                        <ul class="space-y-3 ml-0">
7176                                                            <li
7177                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7178                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7179                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7180                                >
7181                                    
7182<a class="snowdog-menu-link "
7183    href="https://www.purdys.com/ice-cream"
7184            data-menu="menu-2337"
7185    >
7186    Ice Cream &amp; Ice Cream Bars</a>
7187                                                                    </li>
7188                                                            <li
7189                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7190                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7191                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7192                                >
7193                                    
7194<a href="https://www.purdys.com/chocolate/special-offers"
7195   class="snowdog-menu-link "
7196                    data-menu="menu-1545"
7197        >
7198    Special Offers</a>
7199                                                                    </li>
7200                                                            <li
7201                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7202                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7203                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7204                                >
7205                                    
7206<a href="https://www.purdys.com/chocolate/send-chocolates-free-shipping"
7207   class="snowdog-menu-link "
7208                    data-menu="menu-263"
7209        >
7210    Free Shipping </a>
7211                                                                    </li>
7212                                                            <li
7213                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7214                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7215                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7216                                >
7217                                            <a href="/chocolate-legend"
7218        class="snowdog-menu-link "
7219                    data-menu="menu-283"
7220                        data-menu="menu-283"    >
7221        Chocolate Legend     </a>
7222                                                                    </li>
7223                                                            <li
7224                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7225                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7226                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7227                                >
7228                                            <a href="/shipping-gift-guarantee"
7229        class="snowdog-menu-link "
7230                    data-menu="menu-284"
7231                        data-menu="menu-284"    >
7232        Shipping and Delivery    </a>
7233                                                                    </li>
7234                                                    </ul>
7235                    </div>
7236                
7237                <!-- Items with special class "menu-second-column" -->
7238                            </div>
7239            
7240            <!-- Right column: feature block if present -->
7241                            <div class="flex flex-row gap-6 justify-start [&>div]:max-w-[240px]">
7242                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-center                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
7243                            <!-- Render the feature node using the vendor node_type template logic -->
7244                                        <a href="https://www.purdys.com/fall-gift-ideas"
7245           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
7246            tabindex="-1"
7247                    >
7248            <img src="https://www.purdys.com/media/snowdog/menu/node/b/a/banner-container.png"
7249                alt="Coffin&#x20;Box"
7250                loading="lazy"
7251                width="273"
7252                height="364"
7253            />
7254        </a>
7255        <a href="https://www.purdys.com/fall-gift-ideas"
7256        class="snowdog-menu-link menu-second-column&#x20;mega-menu-promo-img"
7257                    data-menu="menu-3770"
7258                        data-menu="menu-3770"    >
7259        Talhulah Turkey &amp; Leaves    </a>
7260                                                    </div>
7261                                    </div>
7262                    </div>
7263    </div>
7264</div>
7265    <div
7266    x-ref="submenu-76"
7267    class="absolute left-0 top-full w-full z-30 shadow-md bg-white flex overflow-hidden"
7268    style="transform-origin: top;"
7269    x-show="openSubmenuId === '76'"
7270    x-transition:enter="transition-all duration-300 ease-out"
7271    x-transition:enter-start="transform scale-y-0"
7272    x-transition:enter-end="transform scale-y-100"
7273    x-transition:leave="transition-all duration-200 ease-in"
7274    x-transition:leave-start="transform scale-y-100"
7275    x-transition:leave-end="transform scale-y-0"
7276    x-cloak
7277    @mouseenter="onSubmenuMouseEnter()"
7278    @mouseleave="onSubmenuMouseLeave()"
7279>
7280    <div class="min-[1660px]:!max-w-[1740px] mx-auto flex flex-row justify-between w-full min-h-[400px] max-h-[600px]
7281        md:px-5 2xl:px-10 py-10 gap-10 [&_a]:no-underline overflow-y-auto">
7282        <!-- Left column: items without children and without image -->
7283        <div
7284          class="flex flex-col pr-10 gap-4 justify-start
7285           [&_a]:text-xl [&_a]:leading-[26px] [&_a]:font-bold [&_a]:text-primary-dark [&_a:hover]:text-primary max-w-[278px]"
7286        >
7287                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7288                            <a href="/build-a-box"
7289        class="snowdog-menu-link "
7290                    data-menu="menu-77"
7291                        data-menu="menu-77"    >
7292        Build-a-Box    </a>
7293                                    </div>
7294                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7295                            <a href="/corporate-gifting"
7296        class="snowdog-menu-link "
7297                    data-menu="menu-345"
7298                        data-menu="menu-345"    >
7299        Custom Corporate Gifts     </a>
7300                                    </div>
7301                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7302                            <a href="/wedding-and-bridal-favours"
7303        class="snowdog-menu-link "
7304                    data-menu="menu-346"
7305                        data-menu="menu-346"    >
7306        Wedding &amp; Anniversaries    </a>
7307                                    </div>
7308                    </div>
7309
7310        <div class="flex flex-wrap xl:flex-nowrap flex-1 gap-x-10 justify-between">
7311            <!-- Main column: items with children -->
7312            
7313            <!-- Right column: feature block if present -->
7314                            <div class="flex flex-row gap-6 justify-start [&>div]:max-w-[240px]">
7315                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-left                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
7316                            <!-- Render the feature node using the vendor node_type template logic -->
7317                                        <a href="/build-a-box"
7318           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
7319            tabindex="-1"
7320                    >
7321            <img src="https://www.purdys.com/media/snowdog/menu/node/i/m/image_5_.png"
7322                alt="Build&#x20;you&#x20;own&#x20;Box"
7323                loading="lazy"
7324                width="269"
7325                height="359"
7326            />
7327        </a>
7328        <a href="/build-a-box"
7329        class="snowdog-menu-link mega-menu-promo-img"
7330                    data-menu="menu-344"
7331                        data-menu="menu-344"    >
7332        Build-a-Box    </a>
7333                                                    </div>
7334                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-left                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
7335                            <!-- Render the feature node using the vendor node_type template logic -->
7336                                        <a href="/corporate-gifting"
7337           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
7338            tabindex="-1"
7339                    >
7340            <img src="https://www.purdys.com/media/snowdog/menu/node/i/m/image_3_.png"
7341                alt="Custom&#x20;Corporate&#x20;Gifts"
7342                loading="lazy"
7343                width="270"
7344                height="359"
7345            />
7346        </a>
7347        <a href="/corporate-gifting"
7348        class="snowdog-menu-link mega-menu-promo-img"
7349                    data-menu="menu-347"
7350                        data-menu="menu-347"    >
7351        Custom Corporate Gifts    </a>
7352                                                    </div>
7353                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-left                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
7354                            <!-- Render the feature node using the vendor node_type template logic -->
7355                                        <a href="/wedding-and-bridal-favours"
7356           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
7357            tabindex="-1"
7358                    >
7359            <img src="https://www.purdys.com/media/snowdog/menu/node/i/m/image_4_.png"
7360                alt="Custom&#x20;Wedding&#x20;Gifts"
7361                loading="lazy"
7362                width="270"
7363                height="359"
7364            />
7365        </a>
7366        <a href="/wedding-and-bridal-favours"
7367        class="snowdog-menu-link mega-menu-promo-img"
7368                    data-menu="menu-348"
7369                        data-menu="menu-348"    >
7370        Custom Wedding Gifts    </a>
7371                                                    </div>
7372                                    </div>
7373                    </div>
7374    </div>
7375</div>
7376    <div
7377    x-ref="submenu-2179"
7378    class="absolute left-0 top-full w-full z-30 shadow-md bg-white flex overflow-hidden"
7379    style="transform-origin: top;"
7380    x-show="openSubmenuId === '2179'"
7381    x-transition:enter="transition-all duration-300 ease-out"
7382    x-transition:enter-start="transform scale-y-0"
7383    x-transition:enter-end="transform scale-y-100"
7384    x-transition:leave="transition-all duration-200 ease-in"
7385    x-transition:leave-start="transform scale-y-100"
7386    x-transition:leave-end="transform scale-y-0"
7387    x-cloak
7388    @mouseenter="onSubmenuMouseEnter()"
7389    @mouseleave="onSubmenuMouseLeave()"
7390>
7391    <div class="min-[1660px]:!max-w-[1740px] mx-auto flex flex-row justify-between w-full min-h-[400px] max-h-[600px]
7392        md:px-5 2xl:px-10 py-10 gap-10 [&_a]:no-underline overflow-y-auto">
7393        <!-- Left column: items without children and without image -->
7394        <div
7395          class="flex flex-col pr-10 gap-4 justify-start
7396           [&_a]:text-xl [&_a]:leading-[26px] [&_a]:font-bold [&_a]:text-primary-dark [&_a:hover]:text-primary max-w-[278px]"
7397        >
7398                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7399                    
7400<a class="snowdog-menu-link "
7401    href="https://www.purdys.com/ice-cream"
7402            data-menu="menu-2340"
7403    >
7404    Ice Cream &amp; Ice Cream Bars</a>
7405                                    </div>
7406                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7407                            <a href="/blog.html"
7408        class="snowdog-menu-link "
7409                    data-menu="menu-2182"
7410                        data-menu="menu-2182"    >
7411        Purdys Blog    </a>
7412                                    </div>
7413                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7414                    
7415<a href="https://www.purdys.com/discover/purple-partnerships"
7416   class="snowdog-menu-link "
7417                    data-menu="menu-2185"
7418        >
7419    Purple Partnerships</a>
7420                                    </div>
7421                            <div class="text-base font-medium text-primary-dark hover:text-primary transition-colors">
7422                    
7423<a class="snowdog-menu-link "
7424    href="https://www.purdys.com/shipping-gift-guarantee"
7425            data-menu="menu-2188"
7426    >
7427    Shipping Deadlines</a>
7428                                    </div>
7429                    </div>
7430
7431        <div class="flex flex-wrap xl:flex-nowrap flex-1 gap-x-10 justify-between">
7432            <!-- Main column: items with children -->
7433                            <div class="max-h-[439px] columns-3 column-gap-8 column-fill-auto max-w-[75%]">
7434                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7435                        <div
7436                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7437                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7438                        >
7439                                    <span class="flex "
7440        tabindex="0"
7441        data-menu="menu-2191"    >
7442        Sustainability    </span>
7443                                                    </div>
7444                        <ul class="space-y-3 ml-0">
7445                                                            <li
7446                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7447                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7448                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7449                                >
7450                                    
7451<a class="snowdog-menu-link "
7452    href="https://www.purdys.com/sustainable-cocoa"
7453            data-menu="menu-2194"
7454    >
7455    Purdys&#039; Sustainable Cocoa Program</a>
7456                                                                    </li>
7457                                                            <li
7458                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7459                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7460                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7461                                >
7462                                    
7463<a class="snowdog-menu-link "
7464    href="https://www.purdys.com/sustainable-farms"
7465            data-menu="menu-2197"
7466    >
7467    Sustainable Farms</a>
7468                                                                    </li>
7469                                                            <li
7470                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7471                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7472                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7473                                >
7474                                    
7475<a class="snowdog-menu-link "
7476    href="https://www.purdys.com/sustainable-living"
7477            data-menu="menu-2200"
7478    >
7479    Sustainable Living</a>
7480                                                                    </li>
7481                                                            <li
7482                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7483                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7484                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7485                                >
7486                                    
7487<a class="snowdog-menu-link "
7488    href="https://www.purdys.com/clean-water-project"
7489            data-menu="menu-2203"
7490    >
7491    Clean Water Project</a>
7492                                                                    </li>
7493                                                    </ul>
7494                    </div>
7495                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7496                        <div
7497                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7498                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7499                        >
7500                                    <span class="flex "
7501        tabindex="0"
7502        data-menu="menu-2206"    >
7503        Corporate Gifts     </span>
7504                                                    </div>
7505                        <ul class="space-y-3 ml-0">
7506                                                            <li
7507                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7508                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7509                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7510                                >
7511                                    
7512<a class="snowdog-menu-link "
7513    href="https://www.purdys.com/corporate-gifts"
7514            data-menu="menu-2209"
7515    >
7516    Corporate Gifts Guides</a>
7517                                                                    </li>
7518                                                            <li
7519                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7520                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7521                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7522                                >
7523                                            <a href="/corporate-gifting"
7524        class="snowdog-menu-link "
7525                    data-menu="menu-2212"
7526                        data-menu="menu-2212"    >
7527        Branded Corporate Gifts    </a>
7528                                                                    </li>
7529                                                    </ul>
7530                    </div>
7531                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7532                        <div
7533                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7534                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7535                        >
7536                                    <span class="flex "
7537        tabindex="0"
7538        data-menu="menu-2215"    >
7539        Our Stories    </span>
7540                                                    </div>
7541                        <ul class="space-y-3 ml-0">
7542                                                            <li
7543                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7544                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7545                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7546                                >
7547                                    
7548<a href="https://www.purdys.com/discover/about-us"
7549   class="snowdog-menu-link "
7550                    data-menu="menu-2218"
7551        >
7552    About Us</a>
7553                                                                    </li>
7554                                                            <li
7555                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7556                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7557                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7558                                >
7559                                    
7560<a href="https://www.purdys.com/discover/purdys-heritage"
7561   class="snowdog-menu-link "
7562                    data-menu="menu-2221"
7563        >
7564    Purdys Heritage</a>
7565                                                                    </li>
7566                                                    </ul>
7567                    </div>
7568                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7569                        <div
7570                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7571                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7572                        >
7573                                    <span class="flex "
7574        tabindex="0"
7575        data-menu="menu-2224"    >
7576        Tips &amp; Guides    </span>
7577                                                    </div>
7578                        <ul class="space-y-3 ml-0">
7579                                                            <li
7580                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7581                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7582                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7583                                >
7584                                            <a href="/blog/is-chocolate-vegan-your-guide-to-vegan-chocolate.html"
7585        class="snowdog-menu-link "
7586                    data-menu="menu-2227"
7587                        data-menu="menu-2227"    >
7588        Is Chocolate Vegan    </a>
7589                                                                    </li>
7590                                                            <li
7591                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7592                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7593                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7594                                >
7595                                            <a href="/blog/celebrate-with-the-perfect-chocolate-gifts.html"
7596        class="snowdog-menu-link "
7597                    data-menu="menu-2230"
7598                        data-menu="menu-2230"    >
7599        The Tasty Art of Giving    </a>
7600                                                                    </li>
7601                                                            <li
7602                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7603                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7604                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7605                                >
7606                                    
7607<a class="snowdog-menu-link "
7608    href="https://www.purdys.com/wedding-and-bridal-favours"
7609            data-menu="menu-2233"
7610    >
7611    Guide to Purdys Wedding Favours</a>
7612                                                                    </li>
7613                                                    </ul>
7614                    </div>
7615                                    <div class="break-inside-avoid mb-10 inline-block w-full">
7616                        <div
7617                          class="uppercase tracking-[0.001em] font-bold text-primary-dark mb-4 text-xl leading-[26px]
7618                            [&_a]:text-primary-dark [&_a]:!font-bold [&_a:hover]:text-primary"
7619                        >
7620                                    <span class="flex "
7621        tabindex="0"
7622        data-menu="menu-2236"    >
7623        Marketing &amp; Tasting    </span>
7624                                                    </div>
7625                        <ul class="space-y-3 ml-0">
7626                                                            <li
7627                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7628                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7629                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7630                                >
7631                                    
7632<a href="https://www.purdys.com/discover/chocolate-legend"
7633   class="snowdog-menu-link "
7634                    data-menu="menu-2239"
7635        >
7636    Chocolate Legend</a>
7637                                                                    </li>
7638                                                            <li
7639                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7640                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7641                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7642                                >
7643                                    
7644<a href="https://www.purdys.com/discover/wine-and-chocolate-pairings"
7645   class="snowdog-menu-link "
7646                    data-menu="menu-2242"
7647        >
7648    Wine and Chocolate Pairings</a>
7649                                                                    </li>
7650                                                            <li
7651                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7652                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7653                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7654                                >
7655                                    
7656<a href="https://www.purdys.com/discover/recipes"
7657   class="snowdog-menu-link "
7658                    data-menu="menu-2245"
7659        >
7660    Recipes</a>
7661                                                                    </li>
7662                                                            <li
7663                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7664                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7665                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7666                                >
7667                                    
7668<a href="https://www.purdys.com/discover/gift-ideas"
7669   class="snowdog-menu-link "
7670                    data-menu="menu-2248"
7671        >
7672    Gift Ideas</a>
7673                                                                    </li>
7674                                                            <li
7675                                  class="body-1 text-primary-dark body-1 hover:text-primary before:content-[''] pl-0
7676                                  [&_a]:body-1 [&_a]:text-black [&_a:hover]:text-primary [&_a:hover]:cursor-pointer
7677                                  [&_span]:text-black [&_span:hover]:text-primary [&_span:hover]:cursor-pointer [&_span]:!p-0"
7678                                >
7679                                            <a href="/blog.html"
7680        class="snowdog-menu-link "
7681                    data-menu="menu-2251"
7682                        data-menu="menu-2251"    >
7683        Blog    </a>
7684                                                                    </li>
7685                                                    </ul>
7686                    </div>
7687                
7688                <!-- Items with special class "menu-second-column" -->
7689                            </div>
7690            
7691            <!-- Right column: feature block if present -->
7692                            <div class="flex flex-row gap-6 justify-start [&>div]:max-w-[240px]">
7693                                            <div class="flex flex-col justify-start [&>a:first-child]:mb-4 [&>a:nth-child(2)]:text-center                            [&>a:nth-child(2)]:font-bold [&>a:nth-child(2)]:text-black [&>a:nth-child(2)]:text-xl [&>a:nth-child(2)]:leading-[26px] [&>a:nth-child(2):hover]:text-primary">
7694                            <!-- Render the feature node using the vendor node_type template logic -->
7695                                        <a href="https://www.purdys.com/share-joy-share-chocolate"
7696           class="block mb-2 transition-opacity group-hover:opacity-80 min-h-[364px]"
7697            tabindex="-1"
7698                    >
7699            <img src="https://www.purdys.com/media/snowdog/menu/node/m/a/maritimes-collection-mega-menu.png"
7700                alt="Maritimes"
7701                loading="lazy"
7702                width="273"
7703                height="364"
7704            />
7705        </a>
7706        <a href="https://www.purdys.com/share-joy-share-chocolate"
7707        class="snowdog-menu-link menu-second-column&#x20;mega-menu-promo-img"
7708                    data-menu="menu-2257"
7709                        data-menu="menu-2257"    >
7710        Maritimes    </a>
7711                                                    </div>
7712                                    </div>
7713                    </div>
7714    </div>
7715</div>
7716    </div>
7717</header><div>
7718</div>
7718<main id="maincontent" class="page-main"><div id="contentarea" tabindex="-1"></div>
7719<div class="page-title-container container&#x20;flex&#x20;flex-col&#x20;md&#x3A;flex-row&#x20;flex-wrap&#x20;my-6&#x20;font-bold&#x20;lg&#x3A;mt-8&#x20;font-semibold&#x20;text-&#x5B;24px&#x5D;&#x20;leading-7&#x20;tracking-tiny&#x20;lg&#x3A;text-h3-lg&#x20;text-black">
7720            <!-- Desktop title: use h1 as usual -->
7721        <h1 class="page-title font-semibold&#x20;text-&#x5B;24px&#x5D;&#x20;leading-7&#x20;tracking-tiny&#x20;lg&#x3A;text-h3-lg&#x20;text-black"
7722            >
7723            <span class="base" data-ui-id="page-title-wrapper" >Customer Login</span>        </h1>
7724        </div>
7725<div class="columns"><div class="column main">    <!-- Yotpo - Add body class -->
7726    
7726<script>
7727        document.addEventListener('DOMContentLoaded', function () {
7728            document.body.classList.add('yotpo-yotpo-is-enabled');
7729        });
7730    </script>
7730
7731
7732    <!--/ Yotpo - Add body class -->
7733    <!-- Yotpo - Widget Script -->
7734    
7734<script>
7735        (function e(){var e=document.createElement("script");e.type="text/javascript",e.async=true,e.src="//staticw2.yotpo.com/Y8hTayDbyjtCoMfQkIIJpq9NdBI0r2HoSN33Q590/widget.js";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})();
7736    </script>
7736
7737    <!--/ Yotpo - Widget Script -->
7738<script nonce="aHhkaGVuNDFoY2Y2eHhyZTY4bzN2c3BycmM3d3FoNnI=">
7739    var feedId = getUrlParam('ff'),
7740        product = getUrlParam('fp'),
7741        currentDate = new Date(),
7742        session = getCookie('feed_session');
7743
7744    if (!session) {
7745        session = '' + Math.floor(currentDate.getTime() / 1000) + Math.floor(Math.random() * 10000001);
7746    }
7747
7748    if (session && feedId > 0 && product > 0) {
7749        setCookie('feed_session', session, {expires: 365, path: '/'});
7750        setCookie('feed_id', feedId, 365);
7751
7752        var xhr = new XMLHttpRequest(),
7753            baseUrl = 'https://www.purdys.com/',
7754            url = BASE_URL + '?rnd=' + Math.floor(Math.random() * 10000001) + "&feed=" + feedId + "&session=" + session + "&product=" + product;
7755
7756        xhr.open('GET', url, true);
7757        xhr.setRequestHeader('Content-Type', 'application/json');
7758        xhr.send();
7759    }
7760
7761    function getUrlParam(name) {
7762        let results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
7763
7764        if (results === null) {
7765            return '';
7766        } else {
7767            return results[1] || 0;
7768        }
7769    }
7770
7771    function getCookie(cookieName) {
7772        var name = cookieName + "=",
7773            decodedCookie = decodeURIComponent(document.cookie),
7774            cookieArray = decodedCookie.split(';');
7775
7776        for (var i = 0; i < cookieArray.length; i++) {
7777            var cookie = cookieArray[i].trim();
7778            if (cookie.indexOf(name) === 0) {
7779                return cookie.substring(name.length, cookie.length);
7780            }
7781        }
7782
7783        return null;
7784    }
7785
7786    function setCookie(cookieName, cookieValue, expirationDays) {
7787        var d = new Date();
7788        d.setTime(d.getTime() + (expirationDays * 24 * 60 * 60 * 1000));
7789        var expires = "expires=" + d.toUTCString();
7790        document.cookie = cookieName + "=" + cookieValue + ";" + expires + ";path=/";
7791    }
7792</script>
7792
7793
7794<script>
7795    window.klaviyoTrackEvent = function (eventName, data = {}) {
7796        window._learnq = window._learnq || [];
7797        window._learnq.push(['track', eventName, {
7798            ...data,
7799            Timestamp: new Date().toISOString()
7800        }]);
7801    }
7802</script>
7802
7803<div id="customer-login-container" class="login-container"><div class="bg-background-light/50 rounded py-6 px-4 md:p-10">
7804    <div aria-labelledby="block-customer-login-heading">
7805        <div class="flex flex-col gap-6 max-md:gap-4">
7806            <!-- Sign In Section Header -->
7807            <div class="text-center">
7808                <h1 class="text-[40px] max-md:text-[28px] font-semibold leading-[1.2] tracking-[0.01em] text-black mb-6 max-md:mb-6">
7809                    Sign in                </h1>
7810                <p class="text-base text-black leading-[1.375] mx-auto">
7811                    Experience a smoother checkout, multi-address shipping, order tracking, and more delicious benefits                </p>
7812            </div>
7813
7814            <!-- Login Form -->
7815            <form class="form form-login"
7816                  action="https://www.purdys.com/customer/account/loginPost/"
7817                  method="post"
7818                  x-data="initCustomerLoginForm_6ab6cfd600889()"
7819                  @submit.prevent="submitForm()"
7820                  id="customer-login-form">
7821                <input name="form_key" type="hidden" value="cbEPL7j02Kuo6BSa" />                <fieldset class="fieldset login">
7822                    <div class="flex flex-col gap-4">
7823                        <!-- Email Field -->
7824                        <div class="field email required">
7825                            <label class="flex items-center mb-4 text-base font-normal text-black"
7826                                   for="email_6ab6cfd600889">
7827                                <span>Email Address</span>
7828                                <span class="text-[#C11A25]">*</span>
7829                            </label>
7830                            <div class="control">
7831                                <input name="login[username]"
7832                                       class="w-full h-[42px] px-4 py-[10px] border border-gray rounded text-base text-black focus:border-primary focus:outline-none"
7833                                       required
7834                                       value=""
7835                                       autocomplete="off"
7836                                       id="email_6ab6cfd600889"
7837                                       type="email"
7838                                       title="Email&#x20;Address"
7839                                />
7840                            </div>
7841                        </div>
7842
7843                        <!-- Password Field -->
7844                        <div class="field password required">
7845                            <label class="flex items-center mb-4 text-base font-normal text-black"
7846                                   for="pass_6ab6cfd600889">
7847                                <span>Password</span>
7848                                <span class="text-[#C11A25]">*</span>
7849                            </label>
7850                            <div class="control flex items-center relative">
7851                                <div class="sr-only" aria-live="polite">
7852                                    <template x-if="!showPassword">
7853                                        <span>
7854                                            Password hidden                                        </span>
7855                                    </template>
7856                                    <template x-if="showPassword">
7857                                        <span>
7858                                            Password shown                                        </span>
7859                                    </template>
7860                                </div>
7861                                <input name="login[password]"
7862                                       class="w-full h-[42px] px-4 py-[10px] border border-gray rounded text-base text-black focus:border-primary focus:outline-none pe-10"
7863                                       required
7864                                       :type="showPassword ? 'text' : 'password'"
7865                                       autocomplete="off"
7866                                       id="pass_6ab6cfd600889"
7867                                       title="Password"
7868                                />
7869                                <button
7870                                        type="button"
7871                                        x-on:click="showPassword = !showPassword"
7872                                        :aria-pressed="showPassword ? 'true' : 'false'"
7873                                        class="px-4 py-3 absolute end-0"
7874                                        :aria-label="showPassword ? 'Hide\u0020Password' : 'Show\u0020Password'"
7875                                >
7876                                    <template x-if="!showPassword">
7877                                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
7878  <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
7879  <path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
7880<title>eye</title></svg>
7881                                    </template>
7882                                    <template x-if="showPassword">
7883                                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
7884  <path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/>
7885  <path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/>
7886<title>
7886eye-off</title></svg>
7887                                    </template>
7888                                </button>
7889                            </div>
7890                        </div>
7891
7892                        <!-- Keep me signed in checkbox -->
7893                        <div class="flex items-center gap-4">
7894                            <div class="flex items-center gap-4">
7895                                <input type="checkbox"
7896                                       id="keep_signed_in_6ab6cfd600889"
7897                                       name="persistent_remember_me"
7898                                       class="w-4 h-4 border border-[#BFBFBF] rounded-[1px] text-primary focus:ring-primary"
7899                                       value="1">
7900                                <label for="keep_signed_in_6ab6cfd600889" class="text-sm text-black">
7901                                    Keep me signed in                                </label>
7902                            </div>
7903                            <div class="relative h-5" x-data="{ showTooltip: false }">
7904                                <button type="button"
7905                                        class="w-5 h-5 text-primary hover:opacity-80 transition-opacity"
7906                                        @mouseenter="showTooltip = true"
7907                                        @mouseleave="showTooltip = false"
7908                                        @focus="showTooltip = true"
7909                                        @blur="showTooltip = false"
7910                                        aria-label="Information&#x20;about&#x20;keeping&#x20;you&#x20;signed&#x20;in">
7911                                    <img src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/images/svg/question-mark-circle.svg"
7912                                         alt="Help"
7913                                         class="w-5 h-5"/>
7914                                </button>
7915
7916                                <!-- Tooltip -->
7917                                <div x-show="showTooltip"
7918                                     x-transition:enter="transition ease-out duration-200"
7919                                     x-transition:enter-start="opacity-0 transform scale-95"
7920                                     x-transition:enter-end="opacity-100 transform scale-100"
7921                                     x-transition:leave="transition ease-in duration-75"
7922                                     x-transition:leave-start="opacity-100 transform scale-100"
7923                                     x-transition:leave-end="opacity-0 transform scale-95"
7924                                     class="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-3 py-2 bg-gray-900 text-white text-sm rounded shadow-lg whitespace-nowrap z-10"
7925                                     style="display: none;">
7926                                    Stay logged in for up to 30 days on this device                                    <div class="absolute top-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-t-gray-900"></div>
7927                                </div>
7928                            </div>
7929                        </div>
7930
7931                        <!-- Action Buttons -->
7932                        <div class="flex flex-col gap-4 items-center">
7933                            <button type="submit"
7934                                    class="w-full bg-primary text-white font-bold text-sm uppercase tracking-[0.03em] py-3 px-4 rounded hover:bg-primary/90 transition-colors"
7935                                    name="send"
7936                                                                >
7937                                <span class="leading-3">SIGN IN</span>
7938                            </button>
7939                            <a class="text-base font-bold text-primary hover:text-primary/80 transition-colors"
7940                               href="https://www.purdys.com/customer/account/forgotpassword/">
7941                                <span>Forgot password?</span>
7942                            </a>
7943                        </div>
7944                    </div>
7945
7946                    <!-- Error Messages -->
7947                    <div>
7948                        <template x-if="displayErrorMessage">
7949                            <p class="text-red flex items-center">
7950                                <span class="inline-block w-8 h-8 me-3">
7951                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
7952  <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
7953</svg>
7954                                </span>
7955                                <template x-for="errorMessage in errorMessages">
7956                                    <span x-html="errorMessage"></span>
7957                                </template>
7958                            </p>
7959                        </template>
7960                    </div>
7961                </fieldset>
7962            </form>
7963
7964            <!-- Separator Line -->
7965            <div class="w-[50%] m-auto h-px bg-[#BBBBC3]"></div>
7966
7967            <!-- Sign Up Link -->
7968            <div class="text-center">
7969                <p class="text-base text-black">
7970                    Don&#039;t have an account?                    <a href="https://www.purdys.com/customer/account/create/"
7971                       class="text-primary hover:text-primary-hover transition-colors">
7972                        Sign Up                    </a>
7973                </p>
7974            </div>
7975        </div>
7976    </div>
7977    
7977<script>
7978        function initCustomerLoginForm_6ab6cfd600889() {
7979            return {
7980                errors: 0,
7981                hasCaptchaToken: 0,
7982                showPassword: false,
7983                displayErrorMessage: false,
7984                errorMessages: [],
7985                setErrorMessages(messages) {
7986                    this.errorMessages = [messages]
7987                    this.displayErrorMessage = this.errorMessages.length
7988                },
7989                submitForm() {
7990                    // do not rename $form, the variable is the expected name in the recaptcha output
7991                    const $form = document.querySelector('#customer-login-form');
7992                    
7993                    if (this.errors === 0) {
7994                        $form.submit();
7995                    }
7996                }
7997            }
7998        }
7999    </script>
7999
8000</div>
8001
8002<!-- Mobile "Or" Separator -->
8003<div class="flex items-center gap-4 lg:hidden">
8004    <div class="flex-1 h-px bg-black"></div>
8005    <span class="text-base text-black font-normal leading-[22px]">Or</span>
8006    <div class="flex-1 h-px bg-black"></div>
8007</div>
8008    <div class="bg-background-light/50 rounded py-6 px-4 md:p-10 h-fit">
8009        <div class="flex flex-col gap-4 text-center">
8010            <!-- New Customers Header -->
8011            <div>
8012                <h1 class="text-[40px] max-md:text-[28px] font-semibold leading-[1.2] tracking-[0.01em] text-black mb-6 max-md:mb-4">
8013                    New Customers                </h1>
8014                <p class="text-base text-black leading-[1.375]">
8015                    Creating an account has many benefits: check out faster, keep more than one address, track orders and more.                </p>
8016            </div>
8017
8018            <!-- Create Account Button -->
8019            <div class="md:mt-4">
8020                <a href="https://www.purdys.com/customer/account/create/"
8021                   class="inline-block w-full bg-primary text-white font-bold text-sm uppercase tracking-[0.03em] py-3 px-4 rounded hover:bg-primary/90 transition-colors no-underline">
8022                    <span>Create An Account</span>
8023                </a>
8024            </div>
8025        </div>
8026    </div>
8027</div>
8028<script>
8029    const rawRequest = "";
8030    const searchRequest = rawRequest ? JSON.parse(rawRequest) : null;
8031
8032    const rawResponse = "";
8033    const searchResponse = rawResponse ? JSON.parse(rawResponse) : null;
8034
8035    const rawExecutionTime = "0";
8036    const executionTime = rawExecutionTime ? parseFloat(rawExecutionTime) : null;
8037
8038    const requestId = "684475d6\u002D1990\u002D4ada\u002Dbba5\u002D6c43b49cfb56";
8039
8040    const rawAttributes = "";
8041    const attributes = rawAttributes ? JSON.parse(rawAttributes) : null;
8042
8043    const rawPageSize = "24";
8044    const pageSize = rawPageSize ? parseInt(rawPageSize) : null;
8045
8046    const customerGroup = "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c";
8047
8048    window.LiveSearchMetrics = {
8049        searchRequest,
8050        searchResponse,
8051        requestId,
8052        executionTime,
8053        attributes,
8054        pageSize,
8055        context: {
8056            'customerGroup' : customerGroup
8057        }
8058    };
8059
8060    window.addEventListener('load', function () {
8061        magentoStorefrontEvents.context.setSearchExtension({
8062            version: "4.4.1"
8063        });
8064    })
8065</script>
8065
8066</div></div></main><footer class="footer"><div class="footer content"><div><style>#html-body [data-pb-style=RSAB68Q]{justify-content:flex-start;display:flex;flex-direction:column;background-color:#532e91;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;text-align:center;padding-top:0;padding-bottom:0}#html-body [data-pb-style=Q1MUREV]{text-align:center;padding-top:8px;padding-bottom:8px}#html-body [data-pb-style=LG8IL8Y],#html-body [data-pb-style=U4H5N6T]{background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}#html-body [data-pb-style=U4H5N6T]{justify-content:flex-start;display:flex;flex-direction:column;background-color:#2e1950;padding:60px 40px}#html-body [data-pb-style=LG8IL8Y]{align-self:stretch}#html-body [data-pb-style=KW4LBT0]{display:flex;width:100%}#html-body [data-pb-style=EE5JGGA],#html-body [data-pb-style=SSJH2YL]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:50%;align-self:stretch}#html-body [data-pb-style=MUYXYOX]{display:none}#html-body [data-pb-style=OML5YU9],#html-body [data-pb-style=SLEH9ES]{background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}#html-body [data-pb-style=OML5YU9]{justify-content:flex-start;display:flex;flex-direction:column;background-color:#2e1950;padding:40px}#html-body [data-pb-style=SLEH9ES]{align-self:stretch}#html-body [data-pb-style=FQHBO9B]{display:flex;width:100%}#html-body [data-pb-style=K2IN203]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:25%;align-self:stretch}#html-body [data-pb-style=IX9PFCI]{margin:0;padding:0}#html-body [data-pb-style=FUXQTVN]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:25%;align-self:stretch}#html-body [data-pb-style=LWQ7T9S]{margin:0;padding:0}#html-body [data-pb-style=AOFKXMR]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:25%;align-self:stretch}#html-body [data-pb-style=QX4A3JA]{margin:0;padding:0}#html-body [data-pb-style=C6W2PBQ]{justify-content:flex-start;display:flex;flex-direction:column;width:25%;align-self:stretch}#html-body [data-pb-style=BKE0357],#html-body [data-pb-style=C6W2PBQ],#html-body [data-pb-style=LYHHH0M]{background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}#html-body [data-pb-style=BKE0357]{justify-content:flex-start;display:flex;flex-direction:column;background-color:#2e1950;padding:0 40px 40px}#html-body [data-pb-style=LYHHH0M]{align-self:stretch}#html-body [data-pb-style=XN0IGTB]{display:flex;width:100%}#html-body [data-pb-style=G112RCT]{justify-content:flex-start;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:50%}#html-body [data-pb-style=G112RCT],#html-body [data-pb-style=UNQSC74],#html-body [data-pb-style=V56ANT6]{display:flex;flex-direction:column;align-self:stretch}#html-body [data-pb-style=V56ANT6]{justify-content:flex-start;width:50%}#html-body [data-pb-style=HDQ4Y37],#html-body [data-pb-style=J3XVEBX],#html-body [data-pb-style=V56ANT6]{background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}#html-body [data-pb-style=J3XVEBX]{justify-content:flex-start;display:flex;flex-direction:column;background-color:#2e1950;padding:16px 40px}#html-body [data-pb-style=HDQ4Y37]{align-self:stretch}#html-body [data-pb-style=WOWMXKM]{display:flex;width:100%}#html-body [data-pb-style=JLA0JXQ],#html-body [data-pb-style=PA43XLI],#html-body [data-pb-style=VVP4G3W]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll;width:33.3333%;align-self:stretch}</style><div data-content-type="row" data-appearance="full-width" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="RSAB68Q"><div class="row-full-width-inner" data-element="inner"><div data-content-type="html" data-appearance="default" data-element="main" data-pb-style="Q1MUREV" data-decoded="true"><div class="flex justify-center flex-wrap gap-x-1 gap-y-2 !text-white">
8067    <div class="flex items-center gap-2">
8068        <div class="stars flex items-center">
8069                            <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewbox="0 0 29 28" fill="none" role="img">
8070<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#B09FCC"></path>
8071<g clip-path="url(#clip0_26550_6322)">
8072<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#EEEAF4"></path>
8073</g>
8074<defs>
8075<clippath id="clip0_26550_6322">
8076<rect width="28" height="28" fill="white" transform="translate(0.5 0.00195312)"></rect>
8077</clippath>
8078</defs>
8079<title>star</title></svg>
8080                            <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewbox="0 0 29 28" fill="none" role="img">
8081<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#B09FCC"></path>
8082<g clip-path="url(#clip0_26550_6322_2)">
8083<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#EEEAF4"></path>
8084</g>
8085<defs>
8086<clippath id="clip0_26550_6322_2">
8087<rect width="28" height="28" fill="white" transform="translate(0.5 0.00195312)"></rect>
8088</clippath>
8089</defs>
8090<title>star</title></svg>
8091                            <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewbox="0 0 29 28" fill="none" role="img">
8092<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#B09FCC"></path>
8093<g clip-path="url(#clip0_26550_6322_3)">
8094<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#EEEAF4"></path>
8095</g>
8096<defs>
8097<clippath id="clip0_26550_6322_3">
8098<rect width="28" height="28" fill="white" transform="translate(0.5 0.00195312)"></rect>
8099</clippath>
8100</defs>
8101<title>star</title></svg>
8102                            <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewbox="0 0 29 28" fill="none" role="img">
8103<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#B09FCC"></path>
8104<g clip-path="url(#clip0_26550_6322_4)">
8105<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#EEEAF4"></path>
8106</g>
8107<defs>
8108<clippath id="clip0_26550_6322_4">
8109<rect width="28" height="28" fill="white" transform="translate(0.5 0.00195312)"></rect>
8110</clippath>
8111</defs>
8112<title>star</title></svg>
8113                            <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewbox="0 0 29 28" fill="none" role="img">
8114<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#B09FCC"></path>
8115<g clip-path="url(#clip0_26550_6322_5)">
8116<path d="M13.7354 4.75765C13.976 4.01698 15.0239 4.01698 15.2645 4.75765L17.0269 10.1816C17.1345 10.5128 17.4432 10.7371 17.7915 10.7371H23.4945C24.2733 10.7371 24.5971 11.7336 23.967 12.1914L19.3532 15.5435C19.0714 15.7483 18.9535 16.1111 19.0611 16.4424L20.8235 21.8663C21.0641 22.6069 20.2164 23.2228 19.5863 22.7651L14.9725 19.4129C14.6907 19.2082 14.3092 19.2082 14.0274 19.4129L9.41357 22.7651C8.78351 23.2228 7.93578 22.6069 8.17644 21.8663L9.93877 16.4424C10.0464 16.1111 9.9285 15.7483 9.64673 15.5435L5.03289 12.1914C4.40283 11.7336 4.72664 10.7371 5.50542 10.7371H11.2084C11.5567 10.7371 11.8654 10.5128 11.973 10.1816L13.7354 4.75765Z" fill="#EEEAF4"></path>
8117</g>
8118<defs>
8119<clippath id="clip0_26550_6322_5">
8120<rect width="28" height="28" fill="white" transform="translate(0.5 0.00195312)"></rect>
8121</clippath>
8122</defs>
8123<title>star</title></svg>
8124                    </div>
8125        <span class="body-2 font-bold">
8126            4.9 based on        </span>
8127    </div>
8128
8129    <div class="flex items-center gap-1">
8130        <span class="body-2 font-bold">
8131            24307 reviews.        </span>
8132        <a href="/reviews" class="reviews-link font-bold body-1 flex items-center gap-1 !text-white">
8133            <span>VIEW ALL REVIEWS</span>
8134            <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewbox="0 0 20 20" fill="none" class="-rotate-90 text-white [&>path]:stroke-[4px]" aria-hidden="true">
8135<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
8136</svg>
8137        </a>
8138    </div>
8139</div>
8140</div></div></div><div class="footer-newsletter" data-content-type="row" data-appearance="full-bleed" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="U4H5N6T"><div class="pagebuilder-column-group" data-background-images="{}" data-content-type="column-group" data-appearance="default" data-grid-size="12" data-background-lazy-load="" data-element="main" data-pb-style="LG8IL8Y"><div class="pagebuilder-column-line" data-content-type="column-line" data-element="main" data-pb-style="KW4LBT0"><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="EE5JGGA"><div data-content-type="text" data-appearance="default" data-element="main"><h2 style="text-align: left;"><span style="color: rgb(255, 255, 255); font-size: 40px;">Want FREE Sweet Georgia Browns on your next order</span></h2>
8141    <p style="text-align: left;"><span style="color: rgb(217, 220, 241); font-size: 16px;">Sign up for our tasty emails and we'll send you a promo code!</span></p></div></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="SSJH2YL"><div data-content-type="html" data-appearance="default" data-element="main" data-pb-style="MUYXYOX" data-decoded="true"><div class="w-full max-lg:mt-3">
8142    <form class="form subscribe" action="https://www.purdys.com/newsletter/subscriber/new/" method="post" x-data="{ ...initNewsletterForm(), ...hyva.formValidation($el) }" @submit.prevent="submitForm" id="newsletter-validate-detail" aria-label="Subscribe to Newsletter">
8143        <div class="fieldset">
8144            <div class="flex justify-center items-center md:justify-start fieldset">
8145                <div class="field field-reserved w-full">
8146                    <div class="control w-full">
8147                        <input name="email" type="email" required id="newsletter-subscribe" class="form-input inline-flex w-full h-[42px] !rounded-r-none !min-h-0" placeholder="Your email address" autocomplete="email" aria-describedby="footer-newsletter-heading" @change="onChange" data-validate='{"email": true, "required": true}' data-msg-email="Enter a valid email." data-msg-required="This is a required field.">
8148                    </div>
8149                    <input name="form_key" type="hidden" value="cbEPL7j02Kuo6BSa">                                    </div>
8150                <button class="btn h-[42px] btn-primary bg-primary-lightest text-black hover:bg-white shrink-0 rounded-l-none">
8151                    Sign Up                </button>
8152            </div>
8153            <!--            <button class="btn btn-primary bg-container-darker text-black hover:bg-white mt-8 w-full lg:hidden">-->
8154<!--                --><!--            </button>-->
8155        </div>
8156    </form>
8157    <div class="w-full">
8158            </div>
8159    
8159<script>
8160        function initNewsletterForm() {
8161            return {
8162                errors: 0,
8163                hasCaptchaToken: 0,
8164                submitForm() {
8165                    // Do not rename $form, the variable is expected to be declared in the recaptcha output
8166                    const $form = document.querySelector('#newsletter-validate-detail');
8167                    
8168                    this.validate()
8169                .then(() => {
8170                    // all fields validated
8171                    $form.submit();
8172                })
8173                .catch((invalid) => {
8174                    if (invalid.length > 0) {
8175                        invalid[0].focus();
8176                    }
8177                });
8178
8179                    // if (this.errors === 0) {
8180                    //     $form.submit();
8181                    // }
8182                }
8183            }
8184        }
8185    </script>
8185
8186</div>
8187
8188</div><div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><style>
8189    .klaviyo-newsletter-block {
8190    max-width:600px;
8191    }
8192    .klaviyo-newsletter-block button {
8193    background-color: red;
8194    }
8195    .klaviyo-newsletter-block h4 {
8196    color: #b09fcc;
8197    font-size: 20px;
8198    font-weight: 700;
8199    line-height: 26px;
8200    margin-bottom: 0;
8201    }
8202    .klaviyo-newsletter-block p {
8203    color: #fff;
8204    font-size: 16px;
8205    line-height: 22px;
8206    margin-bottom: 0;
8207    }
8208    </style>
8209    <div class="klaviyo-newsletter-block">
8210    <div class="klaviyo-form-V5WemK"></div>
8211    <!--
8212    <p>By submitting this form, you agree to receive email newsletters, also our <a style="color: #B09FCC;" href="https://www.purdys.com/terms-of-use" target="_blank">Terms and Conditions</a> &<a style="color: #B09FCC;" href="https://www.purdys.com/privacy-policy" target="_blank"> Privacy policy</a>. This form is protected by reCAPTCHA.
8213    -->
8214    </div>
8215</div></div></div></div></div><div class="footer-content" data-content-type="row" data-appearance="full-bleed" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="OML5YU9"><div class="pagebuilder-column-group" data-background-images="{}" data-content-type="column-group" data-appearance="default" data-grid-size="12" data-background-lazy-load="" data-element="main" data-pb-style="SLEH9ES"><div class="pagebuilder-column-line" data-content-type="column-line" data-element="main" data-pb-style="FQHBO9B"><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="K2IN203"><div data-content-type="scandiweb_accordion" data-appearance="default" block_title="Shop" content='&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Holidays collections" href="/holidays-collections"&gt;Holidays collections&lt;/a&gt;&lt;/p&gt;
8216&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Catalogues" href="/catalogues"&gt;Catalogues&lt;/a&gt;&lt;/p&gt;' is-opened="0" desktop-disabled="1" title_color="#ffffff" data-element="main" data-pb-style="IX9PFCI"><div data-element="block_directive">
8217<script>
8218    function accordion_6ab6cfd6088a1() {
8219        return {
8220            isOpen: Boolean(0),
8221        }
8222    }
8223</script>
8223
8224
8225<div x-data="accordion_6ab6cfd6088a1" data-content-type="accordion" class="w-full" x-defer="intersect">
8226    <button class="flex justify-between items-center gap-3 px-0 py-5 w-full body-2 max-md:px-4 max-lg:px-5 !border-0 md:border-0 !bg-transparent lg:pointer-events-none" x-on:click="isOpen = !isOpen" style="color: #ffffff">
8227        <span class="font-bold">Shop</span>
8228        <div class="lg:hidden">
8229            <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewbox="0 0 20 20" fill="none" class="transition-transform duration-200" aria-hidden="true" :class="{ 'rotate-180': isOpen }">
8230<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
8231</svg>
8232        </div>
8233    </button>
8234    <div class="grid transition-grid-row grid-rows-0fr lg:grid-rows-1fr duration-200" :class="{ 'grid-rows-1fr': isOpen, 'grid-rows-0fr': !isOpen }">
8235        <div class="overflow-hidden">
8236            <div class="max-lg:pb-5" data-content-type="accordion-content">
8237                <p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Holidays collections" href="/holidays-collections">Holidays collections</a></p>
8238<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Catalogues" href="/catalogues">Catalogues</a></p>            </div>
8239        </div>
8240    </div>
8241</div>
8242</div></div></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="FUXQTVN"><div data-content-type="scandiweb_accordion" data-appearance="default" block_title="About Purdys" content='&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="About Us" href="/about-us"&gt;About Us&lt;/a&gt;&lt;/p&gt;
8243&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Reviews" href="/reviews"&gt;Reviews&lt;/a&gt;&lt;/p&gt;
8244&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Purdys Blog" href="/blog.html"&gt;Purdys Blog&lt;/a&gt;&lt;/p&gt;
8245&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Careers" href="/careers"&gt;Careers&lt;/a&gt;&lt;/p&gt;
8246&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Shop Locations" href="/shops"&gt;Shop Locations&lt;/a&gt;&lt;/p&gt;
8247&lt;p&gt;&lt;a style="color: #ffffff;" tabindex="0" title="Donation Requests" href="/donation-requests"&gt;Donation Requests&lt;/a&gt;&lt;/p&gt;
8248' is-opened="0" desktop-disabled="1" title_color="#ffffff" data-element="main" data-pb-style="LWQ7T9S"><div data-element="block_directive">
8249<script>
8250    function accordion_6ab6cfd6093f1() {
8251        return {
8252            isOpen: Boolean(0),
8253        }
8254    }
8255</script>
8255
8256
8257<div x-data="accordion_6ab6cfd6093f1" data-content-type="accordion" class="w-full" x-defer="intersect">
8258    <button class="flex justify-between items-center gap-3 px-0 py-5 w-full body-2 max-md:px-4 max-lg:px-5 !border-0 md:border-0 !bg-transparent lg:pointer-events-none" x-on:click="isOpen = !isOpen" style="color: #ffffff">
8259        <span class="font-bold">About Purdys</span>
8260        <div class="lg:hidden">
8261            <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewbox="0 0 20 20" fill="none" class="transition-transform duration-200" aria-hidden="true" :class="{ 'rotate-180': isOpen }">
8262<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
8263</svg>
8264        </div>
8265    </button>
8266    <div class="grid transition-grid-row grid-rows-0fr lg:grid-rows-1fr duration-200" :class="{ 'grid-rows-1fr': isOpen, 'grid-rows-0fr': !isOpen }">
8267        <div class="overflow-hidden">
8268            <div class="max-lg:pb-5" data-content-type="accordion-content">
8269                <p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="About Us" href="/about-us">About Us</a></p>
8270<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Reviews" href="/reviews">Reviews</a></p>
8271<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Purdys Blog" href="/blog.html">Purdys Blog</a></p>
8272<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Careers" href="/careers">Careers</a></p>
8273<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Shop Locations" href="/shops">Shop Locations</a></p>
8274<p><a style="color: #ffffff;" tabindex="0" title="Donation Requests" href="/donation-requests">Donation Requests</a></p>
8275            </div>
8276        </div>
8277    </div>
8278</div>
8279</div></div></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="AOFKXMR"><div data-content-type="scandiweb_accordion" data-appearance="default" block_title="Support" content='&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Shipping" href="/shipping-gift-guarantee"&gt;Shipping&lt;/a&gt;&lt;/p&gt;
8280&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="FAQ" href="/faqs"&gt;FAQ&lt;/a&gt;&lt;/p&gt;
8281&lt;p&gt;&lt;a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="FAQ" href="/accessible-customer-service-policy"&gt;Accessible Customer Service Policy&lt;/a&gt;&lt;/p&gt;' is-opened="0" desktop-disabled="1" title_color="#ffffff" data-element="main" data-pb-style="QX4A3JA"><div data-element="block_directive">
8282<script>
8283    function accordion_6ab6cfd609d69() {
8284        return {
8285            isOpen: Boolean(0),
8286        }
8287    }
8288</script>
8288
8289
8290<div x-data="accordion_6ab6cfd609d69" data-content-type="accordion" class="w-full" x-defer="intersect">
8291    <button class="flex justify-between items-center gap-3 px-0 py-5 w-full body-2 max-md:px-4 max-lg:px-5 !border-0 md:border-0 !bg-transparent lg:pointer-events-none" x-on:click="isOpen = !isOpen" style="color: #ffffff">
8292        <span class="font-bold">Support</span>
8293        <div class="lg:hidden">
8294            <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewbox="0 0 20 20" fill="none" class="transition-transform duration-200" aria-hidden="true" :class="{ 'rotate-180': isOpen }">
8295<path d="M18.3329 5.83337L9.99959 14.1667L1.66626 5.83337" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
8296</svg>
8297        </div>
8298    </button>
8299    <div class="grid transition-grid-row grid-rows-0fr lg:grid-rows-1fr duration-200" :class="{ 'grid-rows-1fr': isOpen, 'grid-rows-0fr': !isOpen }">
8300        <div class="overflow-hidden">
8301            <div class="max-lg:pb-5" data-content-type="accordion-content">
8302                <p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="Shipping" href="/shipping-gift-guarantee">Shipping</a></p>
8303<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="FAQ" href="/faqs">FAQ</a></p>
8304<p><a style="color: #ffffff; margin-bottom: 12px;" tabindex="0" title="FAQ" href="/accessible-customer-service-policy">Accessible Customer Service Policy</a></p>            </div>
8305        </div>
8306    </div>
8307</div>
8308</div></div></div><div class="pagebuilder-column footer-contact" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="false" data-element="main" data-pb-style="C6W2PBQ"><div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><style>
8309    .contact-text {
8310    color: #ffffff;
8311    font-size: 18px;
8312    line-height: 24px;
8313    font-weight: bold;
8314    padding: 16px 0;
8315    }
8316
8317    @media (max-width: 1024px) {
8318    .contact-text {
8319    padding: 20px 0;
8320    }
8321    }
8322
8323    .footer-link {
8324    color: #ffffff;
8325    margin-bottom: 12px;
8326    display: inline-flex;
8327    align-items: center;
8328    gap: 8px;
8329    text-decoration: none;
8330    }
8331
8332    .footer-link span {
8333    text-decoration: underline;
8334    }
8335
8336    .footer-location {
8337    color: #ffffff;
8338    display: flex;
8339    align-items: flex-start;
8340    gap: 8px;
8341    text-decoration: none;
8342    }
8343
8344    .footer-location div {
8345    display: flex;
8346    flex-direction: column;
8347    }
8348
8349    .footer-regular-hours {
8350    color: #ffffff;
8351    font-weight: bold;
8352    margin-top: 20px;
8353    }
8354
8355    .footer-time {
8356    color: #ffffff;
8357    }
8358    </style>
8359
8360    <p class="contact-text">Contact Us</p>
8361
8362    <p>
8363    <a class="footer-link" tabindex="-1" title="1.888.478.7397" href="tel:1.888.478.7397">
8364    <img src="/media/wysiwyg/footer/mobile.png" alt="tel" width="20" height="20">
8365    <span>1.888.478.7397</span>
8366    </a>
8367    </p>
8368
8369    <p>
8370    <a class="footer-link" tabindex="-1" title="email" href="mailto:[email protected]">
8371    <img src="/media/wysiwyg/footer/email.png" alt="email" width="20" height="20">
8372    <span>[email protected]</span>
8373    </a>
8374    </p>
8375
8376    <div class="footer-location">
8377    <a tabindex="0" title="location" href="#">
8378    <img src="/media/wysiwyg/footer/location.png" alt="location" width="24" height="24">
8379    </a>
8380    <a style="
8381    display: flex;
8382    flex-direction: column;
8383    gap: 0;
8384    color: white;
8385    text-decoration: underline;"
8386    tabindex="0" title="location" href="#">
8387    <span>8330 Chester Street</span>
8388    <span>Vancouver, British Columbia</span>
8389    <span>Canada V5X 3Y7</span>
8390    </a>
8391    </a>
8392    </div>
8393
8394    <p class="footer-regular-hours">Regular hours:</p>
8395    <p class="footer-time">Mon - Fri, 9:00am to 4:00pm (PT)</p>
8396</div></div></div></div></div><div class="footer-icons" data-content-type="row" data-appearance="full-bleed" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="BKE0357"><div class="pagebuilder-column-group" data-background-images="{}" data-content-type="column-group" data-appearance="default" data-grid-size="12" data-background-lazy-load="" data-element="main" data-pb-style="LYHHH0M"><div class="pagebuilder-column-line" data-content-type="column-line" data-element="main" data-pb-style="XN0IGTB"><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="G112RCT"><div class="footer-icons-social" data-content-type="text" data-appearance="default" data-element="main"><p><a tabindex="0" title="Instagram" href="https://www.instagram.com/purdyschocolatier/"><img id="KJFHO9A" style="width: 20px; height: 20px;" src="/media/wysiwyg/footer/instagram.png" alt="instagram" width="20" height="20"></a></p>
8397    <p><a style="box-shadow: none; outline: 0px;" tabindex="0" title="Facebook" href="https://www.facebook.com/PurdysChocolatier"><img id="SPY4HUC" style="width: 20px; height: 20px;" src="/media/wysiwyg/footer/facebook.png" alt="facebook" width="20" height="20"></a></p>
8398    <p><a style="box-shadow: none; outline: 0px;" tabindex="0" title="Youtube" href="https://www.youtube.com/user/PurdysChocolates1"><img style="width: 20px; height: 20px;" src="/media/wysiwyg/footer/youtube.png" alt="youtube" width="20" height="20"></a></p>
8399    <p><a style="text-decoration-line: underline; box-shadow: none; outline: 0px;" tabindex="0" title="X" href="https://x.com/PurdysChocolate"><img style="width: 20px; height: 20px;" src="/media/wysiwyg/footer/x.png" alt="X" width="20" height="20"></a></p>
8400    <p><a tabindex="0" title="Tiktok" href="https://www.tiktok.com/@purdys.chocolatier"><img style="width: 20px; height: 20px;" src="/media/wysiwyg/footer/ticktok.png" alt="ticktok" width="20" height="20"></a></p>
8401    <p>&nbsp;</p></div></div><div class="pagebuilder-column footer-language-switcher-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="UNQSC74"><div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true">
8402<div class="footer-language-switcher-wrapper">
8403    <div class="footer-language-switcher" x-data="{ open: false }" @click.outside="open = false">
8404        <p class="footer-language-switcher__label">Choose language:</p>
8405        <div class="footer-language-switcher__content">
8406            <img src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/images/canad
8406a-flag.svg" alt="Canada flag" class="footer-language-switcher__flag" width="29" height="16">
8407            <button type="button" class="footer-language-switcher__toggle" @click="open = !open" :aria-expanded="open.toString()" aria-haspopup="listbox">
8408                <span>Canada — EN</span>
8409                <img src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/images/language-switcher-chevron.svg" alt="" class="footer-language-switcher__chevron" :class="{ 'is-open': open }" aria-hidden="true" width="12" height="7">
8410            </button>
8411            <div class="footer-language-switcher__menu" x-show="open" x-cloak>
8412                                                        <a href="https://www.purdys.com/stores/store/redirect/___store/default/uenc/aHR0cHM6Ly93d3cucHVyZHlzLmNvbS9jdXN0b21lci9hY2NvdW50L2xvZ2luLw~~/___from_store/default/" class="footer-language-switcher__item footer-language-switcher__item--active" role="option" aria-selected="true">
8413                        Canada — EN                    </a>
8414                                                        <a href="https://www.purdys.com/stores/store/redirect/___store/fr/uenc/aHR0cHM6Ly93d3cucHVyZHlzLmNvbS9mci9jdXN0b21lci9hY2NvdW50L2xvZ2luLw~~/___from_store/default/" class="footer-language-switcher__item" role="option" aria-selected="false">
8415                        Canada — FR                    </a>
8416                            </div>
8417        </div>
8418    </div>
8419</div>
8420</div></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="V56ANT6"><div class="footer-icons-payments" data-content-type="text" data-appearance="default" data-element="main"><p><img id="JUMKUDR" style="width: 34px; height: 24px;" src="/media/wysiwyg/footer/visa.png" alt="visa" width="40" height="28"></p>
8421<p><img style="width: 34px; height: 24px;" src="/media/wysiwyg/footer/mastercard.png" alt="mastercard" width="40" height="28"></p>
8422<p><img style="width: 35px; height: 24px;" src="/media/wysiwyg/Payment_Method.png" alt="" width="35" height="24"></p>
8423<p><img style="width: 34px; height: 24px;" src="/media/wysiwyg/footer/paypal.png" alt="paypal" width="40" height="28"></p></div></div></div></div></div><div class="footer-misc" data-content-type="row" data-appearance="full-bleed" data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="false" data-element="main" data-pb-style="J3XVEBX"><div class="pagebuilder-column-group" data-background-images="{}" data-content-type="column-group" data-appearance="default" data-grid-size="12" data-background-lazy-load="" data-element="main" data-pb-style="HDQ4Y37"><div class="pagebuilder-column-line" data-content-type="column-line" data-element="main" data-pb-style="WOWMXKM"><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="VVP4G3W"><div data-content-type="text" data-appearance="default" data-element="main"><p><span style="color: rgb(255, 255, 255);"><strong><span id="WP1B73J" style="font-size: 14px;">&copy; 2026 Purdys Chocolatier. All rights reserved.</span></strong></span></p></div></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="JLA0JXQ"></div><div class="pagebuilder-column" data-content-type="column" data-appearance="full-height" data-background-images="{}" data-background-lazy-load="" data-element="main" data-pb-style="PA43XLI"><div class="footer-misc-terms" data-content-type="text" data-appearance="default" data-element="main"><p><span style="color: rgb(255, 255, 255);"><strong><span style="font-size: 14px;"><a style="color: rgb(255, 255, 255);" tabindex="0" href="/terms-of-use">TERMS OF USE</a></span></strong></span></p>
8424    <p><span style="color: rgb(255, 255, 255);"><strong><span style="font-size: 14px;"><a style="color: rgb(255, 255, 255);" tabindex="0" href="/privacy-policy">PRIVACY POLICY</a></span></strong></span></p></div></div></div></div></div></div>
8424<script>
8425    'use strict';
8426
8427    function amBrandsPopup() {
8428        let cached = false;
8429
8430        const displayError = (error) => {
8431            console.error(error);
8432            typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
8433                [{
8434                    type: "error",
8435                    text: "Something\u0020went\u0020wrong.\u0020Please\u0020try\u0020again."
8436                }], 10000
8437            );
8438        };
8439
8440        let letters = [
8441            "A","B","C","D",
8442            "E","F","G","H","I","J","K","L","M",
8443            "N","O","P","Q","R","S","T","U","V","W","X","Y","Z","#"
8444        ];
8445
8446        return {
8447            hoverPanelActiveId: null,
8448            selectedLetter: null,
8449            items: [],
8450            letters: [],
8451            showCount: null,
8452            showFilter: null,
8453            showImages: true,
8454            showSearch: null,
8455            loading: false,
8456            label: 'Brands',
8457            isPopupEnabled: false,
8458            isTopMenuItemEnabled: false,
8459            cache: false,
8460            isMobile: false,
8461
8462            initErrorMessages(errors) {
8463                const messages = [];
8464                for (let error in Object.keys(errors)) {
8465                    messages.push({type: 'error', text: errors[error].message});
8466                }
8467                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(messages, 10000);
8468            },
8469
8470            chooseLetter(letter) {
8471                this.selectedLetter = this.selectedLetter === letter ? null : letter;
8472            },
8473
8474            getQuery() {
8475                return "query BrandsPopupQuery { ambrandlist(\n                    showCount: true\n                    displayZero: true\n                  ) {\n                    all_letters,\n                    items {\n                      alt\n                      brandId\n                      cnt\n                      image\n                      img\n                      label\n                      letter\n                      url\n                    }\n                  }\n                  storeConfig {\n                    amshopby_brand_general_brands_brands_popup,\n                    amshopby_brand_general_menu_item_label,\n                    amshopby_brand_general_brands_page,\n                    amshopby_brand_general_topmenu_enabled,\n                    amshopby_brand_general_brands_popup_config {\n                      show_images,\n                      display_zero,\n                      filter_display_all,\n                      image_width,\n                      image_height,\n                      show_filter,\n                      show_count\n                    }\n                  } }"            },
8476
8477            /**
8478             * Retrieve media url for given path
8479             *
8480             * @param path
8481             * @returns {string}
8482             */
8483            getMediaUrl(path) {
8484                let stringToRemove = 'index.php/';
8485                let baseUrl = BASE_URL.replace(stringToRemove, '');
8486                return path.includes(baseUrl) ? path : baseUrl + path;
8487            },
8488
8489            checkIsMobileResolution() {
8490                this.isMobile = window.matchMedia('(max-width: 1023px)').matches;
8491            },
8492
8493            getBrandUrl(url){
8494                return BASE_URL + url;
8495            },
8496
8497            init() {
8498                this.checkIsMobileResolution();
8499
8500                                this.$watch('hoverPanelActiveId', (value) => {
8501                    if (value === 'am-brand') {
8502                        this.sendRequest();
8503                    }
8504                });
8505                            },
8506
8507            /**
8508             * Get brands by letter
8509             *
8510             * @param result
8511             * @returns {{imageWidth: *, isTopMenuItemEnabled: *, showCount: *, displayAll: *, showFilter: *, showImages: *, isPopupEnabled: *, label: *, imageHeight: *, filterDisplayAll: *, brandsPage: *}}
8512             */
8513            settingsMapper(result) {
8514                const config = result.data.storeConfig?.amshopby_brand_general_brands_popup_config;
8515                return {
8516                    showImages: config.show_images,
8517                    showCount: config.show_count,
8518                    showFilter: config.show_filter,
8519                    imageWidth: config.image_width,
8520                    imageHeight: config.image_height,
8521                    filterDisplayAll: config.filter_display_all,
8522                    displayAll: config.display_zero,
8523                    isPopupEnabled: result.data.storeConfig?.amshopby_brand_general_brands_brands_popup,
8524                    label: result.data.storeConfig?.amshopby_brand_general_menu_item_label,
8525                    isTopMenuItemEnabled: result.data.storeConfig?.amshopby_brand_general_topmenu_enabled,
8526                    brandsPage: result.data.storeConfig?.amshopby_brand_general_brands_page,
8527                }
8528            },
8529
8530            /**
8531             * Send request to graphql
8532             *
8533             * @returns {Promise<any>}
8534             */
8535            async sendRequest() {
8536                if (this.isMobile) {
8537                    return false;
8538                }
8539
8540                this.loading = true;
8541
8542                try {
8543                    if (cached) {
8544                        this.loading = false;
8545                        return false;
8546                    }
8547
8548                    const response = await fetch('https://www.purdys.com/graphql', {
8549                        method: 'POST',
8550                        headers: {
8551                            'Content-Type': 'application/json',
8552                            'Store': 'default'
8553                        },
8554                        credentials: 'include',
8555                        body: JSON.stringify({query: this.getQuery(), variables: {}})
8556                    });
8557                    const result = await response.json();
8558
8559                    if (result?.errors) {
8560                        this.initErrorMessages(result.errors);
8561                        return;
8562                    }
8563
8564                    const data = result.data?.ambrandlist;
8565                    const mapper = this.settingsMapper(result);
8566
8567                    // Update component settings
8568                    Object.keys(mapper).forEach(config => {
8569                        this[config] = mapper[config];
8570                    });
8571
8572                    if (!this.filterDisplayAll) {
8573                        letters = data.all_letters.split(',');
8574                    }
8575
8576                    const items = data.items.map(brand => {
8577                        brand.image = brand.img
8578                            ? this.getMediaUrl(brand.img) : (brand.image ? this.getMediaUrl(brand.image) : null);
8579                        return brand;
8580                    });
8581
8582                    this.letters = letters.map(letter => ({
8583                        letter,
8584                        brands: this.getLetterItems(items, letter),
8585                    }));
8586
8587                    this.items = this.letters.filter(row => row.brands?.length > 0);
8588
8589                    cached = true;
8590                } catch (error) {
8591                    displayError(error);
8592                } finally {
8593                    this.loading = false;
8594                }
8595            },
8596
8597            /**
8598             * Get brands by letter
8599             *
8600             * @param items
8601             * @param letter
8602             * @returns {*}
8603             */
8604            getLetterItems(items, letter) {
8605                return items.filter(row => row.letter === letter);
8606            },
8607
8608            convertHtml(text) {
8609                let textField = document.createElement("textarea");
8610                textField.innerHTML = text;
8611                return textField.value;
8612            }
8613        }
8614    }
8615</script>
8615
8616</div></footer>
8617<script>
8618    function dataServicesShoppingCartContextData() {
8619        return {
8620            initContext() {
8621                const cartData = this.$event.detail.data.cart;
8622                let contextCartItems = [];
8623
8624                if (cartData && cartData.items) {
8625                    cartData.items.forEach(function (item) {
8626                        contextCartItems.push({
8627                            id: item.item_id,
8628                            formattedPrice: parseFloat(item.product_price_value ? item.product_price_value : 0),
8629                            quantity: item.qty,
8630                            product: {
8631                                productType: item.product_type,
8632                                productId: item.product_id,
8633                                name: item.product_name,
8634                                sku: item.product_sku,
8635                                mainImageUrl: item.product_image.src
8636                            },
8637                            prices: {
8638                                price: {
8639                                    value: parseFloat(item.product_price_value ? item.product_price_value : 0)
8640                                }
8641                            }
8642                        });
8643                    });
8644
8645                    magentoStorefrontEvents.context.setShoppingCart({
8646                        id: cartData.dsCartId,
8647                        totalQuantity: cartData.summary_count,
8648                        prices: {
8649                            subtotalExcludingTax: {
8650                                value: parseFloat(cartData.subtotalAmountExclTax ? cartData.subtotalAmountExclTax : 0)
8651                            },
8652                            subtotalIncludingTax: {
8653                                value: parseFloat(cartData.subtotalAmount ? cartData.subtotalAmount : 0)
8654                            }
8655                        },
8656                        items: contextCartItems,
8657                        possibleOnepageCheckout: cartData.possible_onepage_checkout,
8658                        giftMessageSelected : false,
8659                        giftWrappingSelected : false
8660                    });
8661                }
8662
8663                window.dispatchEvent(new Event("shoppingCartContextSet"));
8664            }
8665        }
8666    }
8667
8668    window.addEventListener('alpine:init', () => Alpine.data('dataServicesShoppingCartContextData', dataServicesShoppingCartContextData), {once: true});
8669</script>
8669
8670
8671<div x-data="dataServicesShoppingCartContextData"
8672     @private-content-loaded.window="initContext"></div>
8673
8674<script>
8675    function amBannerInjectorResolver () {
8676        const injectors = Object.values({"products.among.injector":{"position":14,"name":"amBannerAmongCategoryInjector"},"products.belowcart.injector":{"position":15,"name":"amBannerBelowCartInjector"}});
8677
8678        return {
8679            amBannerAmongCategoryInjector: function (sectionId, injectorParams) {
8680                const container = document.querySelector('[data-role="amasty-banner-container"][data-position="' + sectionId + '"]');
8681
8682                Object.keys(injectorParams.banners).map((id) => {
8683                    const params = injectorParams.banners[id];
8684                    const element = container.querySelector('[data-banner-id="' + id + '"]');
8685                    insertBannerAmongCategoryByConfig({
8686                        containerSelector: injectorParams.containerSelector,
8687                        itemSelector: injectorParams.itemSelector,
8688                        afterProductRow: params.afterProductRow,
8689                        afterProductNum: params.afterProductNum,
8690                        span: params.width
8691                    }, element);
8692                });
8693
8694                function insertBannerAmongCategoryByConfig (injectorConfig, element) {
8695                    const options = {
8696                        injectorConfig: {},
8697                        container: null,
8698                        after: null,
8699                        wrapper: null,
8700                        initialized: false,
8701                        gridSizes: ['sm', 'xl'],
8702                        bannerWidthClass: 'col-span',
8703                        ...injectorConfig
8704                    }
8705
8706                    insertBanner(element);
8707
8708                    function insertBanner(element) {
8709                        const initialized = setOptions();
8710
8711                        if (!initialized) {
8712                            return;
8713                        }
8714
8715                        element.classList.add('ambanners-injected-banner');
8716                        const wrapper = options.wrapper.cloneNode(true);
8717
8718                        wrapper.classList.remove('card', 'card-interactive');
8719                        addStylesForDifferentSizes(wrapper);
8720
8721                        insertWrapper(wrapper);
8722                        wrapper.append(element);
8723                    }
8724
8725                    function setOptions () {
8726                        const initialized = document.querySelector(options.containerSelector) !== null;
8727
8728                        if (!initialized) {
8729                            console.warn(
8730                                'Failed to initialize banner: Can\'t find an element with selector "' + options.containerSelector + '"'
8731                            );
8732
8733                            return;
8734                        }
8735
8736                        options.container = document.querySelector(options.containerSelector);
8737
8738                        setLineToInject();
8739
8740                        if (!options.after) {
8741                            return;
8742                        }
8743
8744                        setWrapper();
8745
8746                        return true;
8747                    }
8748
8749                    function setLineToInject() {
8750                        if (options.afterProductNum === -1) {
8751                            setFirstLineToInject();
8752                        } else {
8753                            setLineByPositionToInject();
8754                        }
8755                    }
8756
8757                    function setWrapper() {
8758                        if (options.after) {
8759                            options.wrapper = options.after.cloneNode();
8760                        }
8761                    }
8762
8763                    function setFirstLineToInject() {
8764                        options.after = document.querySelector(options.itemSelector);
8765                    }
8766
8767                    function setLineByPositionToInject() {
8768                        // calc banner insert offset
8769                        const offset = calculateOffsetBasedOnPreviousBanners();
8770
8771                        options.after = document.querySelectorAll(options.itemSelector)[options.afterProductNum - offset];
8772                    }
8773
8774                    function calculateOffsetBasedOnPreviousBanners () {
8775                        return [...document.querySelectorAll(`${options.itemSelector}`)]
8776                            ?.reduce((accumulator, amInjectedBannerWrapper) => {
8777                                const widthAttributeValue = Number(amInjectedBannerWrapper?.getAttribute('am-banner-span'))
8778
8779                                if (widthAttributeValue > 1) {
8780                                    accumulator += (widthAttributeValue - 1);
8781                                }
8782
8783                                return accumulator;
8784                            }, 0);
8785                    }
8786
8787                    function insertWrapper(insert) {
8788                        if (options.after) {
8789                            insertWrapperAfterFoundProduct(insert);
8790                        } else if (options.container) {
8791                            insertWrapperInProductListContainer(insert);
8792                        }
8793                    }
8794
8795                    function insertWrapperAfterFoundProduct(insert) {
8796                        if (options.afterProductNum === -1) {
8797                            options.after.parentNode.insertBefore(insert, options.after);
8798                        } else {
8799                            options.after.parentNode.insertBefore(insert, options.after.nextSibling);
8800                        }
8801                    }
8802
8803                    function insertWrapperInProductListContainer(insert) {
8804                        if (parseInt(options.afterProductRow) > 1) {
8805                            options.container.innerHTML += insert.innerHTML;
8806                        } else {
8807                            options.container.innerHTML = insert.innerHTML + options.container.innerHTML;
8808                        }
8809                    }
8810
8811                    function addStylesForDifferentSizes (wrapper) {
8812                        options.gridSizes?.forEach((size, index) => {
8813                            const widthValue = options.span > index + 1 ? index + 2 : options.span;
8814                            wrapper?.classList.add(`${size}:${options.bannerWidthClass}-${widthValue}`);
8815                            wrapper?.setAttribute('am-banner-span', widthValue);
8816                        });
8817                    }
8818                }
8819            },
8820
8821            amBannerBelowCartInjector: function (sectionId) {
8822                const belowProductAddToCartBanner = document.querySelector('.ambanners.ambanner-' + sectionId);
8823                belowProductAddToCartBanner.style.display = 'block';
8824                document.querySelectorAll('.product-item')?.forEach(product => {
8825                    product?.append(belowProductAddToCartBanner.cloneNode(true));
8826                });
8827                belowProductAddToCartBanner.style.display = 'none';
8828            },
8829
8830            resolve: function (position, injectorParams) {
8831                const injector = injectors.find((injector) => {
8832                    return injector.position === Number(position);
8833                });
8834
8835                return this[injector?.name]?.(position, injectorParams);
8836            }
8837        }
8838    }
8839</script>
8839
8840
8841    
8842<script>
8843    (function () {
8844        'use strict';
8845
8846        /**
8847         * Config to determine which element is responsible for the form submission
8848         *
8849         * @type {[{elementSelector: undefined|string, submitAttribute: string}]}
8850         */
8851        const formWrapperConfig = [{"elementSelector":null,"submitAttribute":"submit"},{"elementSelector":"[type=\"submit\"]","submitAttribute":"click"}];
8852
8853        /**
8854         * Replace protected forms submit with amRecaptchaModel.execute($event) method.
8855         * Call original submit on amrecaptcha-callback event after successful captcha validation.
8856         *
8857         * @return {void}
8858         */
8859        const wrapFormSubmit = function () {
8860            document.addEventListener("DOMContentLoaded", function () {
8861                const formsSelector = window.amRecaptchaModel?.formsToProtect || '';
8862                if (formsSelector.length === 0) {
8863                    return;
8864                }
8865
8866                document.querySelectorAll(formsSelector)?.forEach(formElement => {
8867                    if (!formElement) {
8868                        return;
8869                    }
8870
8871                    const { elementToWrap, attributeNameToWrap } = resolveElementWrapping(formElement);
8872                    if (!elementToWrap || !attributeNameToWrap) {
8873                        return;
8874                    }
8875
8876                    setElementAttributes(formElement, elementToWrap, attributeNameToWrap);
8877                });
8878            });
8879        };
8880
8881        /**
8882         * Find submit event and DOM element that has this event using formWrapperConfig.
8883         *
8884         * @param {HTMLElement} formElement
8885         * @return {{elementToWrap: undefined|string, attributeNameToWrap: undefined|string}}
8886         */
8887        const resolveElementWrapping = function (formElement) {
8888            let result = {
8889                elementToWrap: undefined,
8890                attributeNameToWrap: undefined
8891            };
8892
8893            formWrapperConfig.forEach(({ elementSelector, submitAttribute }) => {
8894                const elementToWrap = !!elementSelector ? formElement.querySelector(elementSelector) : formElement;
8895                if (!elementToWrap) {
8896                    return;
8897                }
8898
8899                const attributeNameToWrap = elementToWrap.getAttributeNames().find(
8900                    (elementAttribute) => {
8901                        /** @type {string[]} */
8902                        const submitAttributeVariations = ['@', 'x-on:'].map(variation => variation + submitAttribute);
8903
8904                        return submitAttributeVariations.some(
8905                            (submitAttributeVariation) => elementAttribute.startsWith(submitAttributeVariation)
8906                        )
8907                    }
8908                );
8909                if (!attributeNameToWrap) {
8910                    return;
8911                }
8912
8913                result.elementToWrap = elementToWrap;
8914                result.attributeNameToWrap = attributeNameToWrap;
8915            });
8916
8917            return result;
8918        }
8919
8920        /**
8921         *  Set attribute to wrap original submit, add eventListeners for captcha callbacks
8922         *
8923         * @param {HTMLElement} formElement
8924         * @param {HTMLElement} elementToWrap
8925         * @param {string} attributeNameToWrap
8926         */
8927        const setElementAttributes = function (formElement, elementToWrap, attributeNameToWrap) {
8928            const originalSubmit = elementToWrap.getAttribute(attributeNameToWrap);
8929            elementToWrap.removeAttribute(attributeNameToWrap);
8930
8931            /**
8932             * To properly set submit attribute - we need to replace '@' with 'x-on:'
8933             * and add preventDefault behaviour
8934             */
8935            elementToWrap.setAttribute(
8936                attributeNameToWrap.replace(/^@/, 'x-on:').replace(/.prevent$/, '') + '.prevent',
8937                'amRecaptchaModelExecute'
8938            );
8939            elementToWrap.setAttribute(
8940                'x-on:amrecaptcha-executable-callback',
8941                originalSubmit
8942            );
8943        }
8944
8945        const setAmRecaptchaModelExecute = function () {
8946            const formsSelector = window.amRecaptchaModel?.formsToProtect || '';
8947
8948            if (formsSelector.length === 0) {
8949                return;
8950            }
8951
8952            document.querySelectorAll(formsSelector).forEach(formElement => {
8953                const { elementToWrap, attributeNameToWrap } = resolveElementWrapping(formElement);
8954                if (!elementToWrap || !attributeNameToWrap) {
8955                    return;
8956                }
8957
8958                const formComponent = getFormComponent(elementToWrap),
8959                      origFormComponent = window[formComponent];
8960
8961                window[formComponent] = function () {
8962                    const instance = origFormComponent.apply(this, arguments),
8963                          reviewComponent = document.querySelector(
8964                              '[x-data="initReviewForm()"], [x-data="initReviewForm"]'
8965                          );
8966
8967                    if (reviewComponent?.getAttribute('x-data') === formComponent) {
8968                        instance.init = function () {
8969                            origFormComponent.apply(this, arguments).init;
8970                            this.$watch(
8971                                'errorMessages',
8972                                errorMessages => {
8973                                    errorMessages?.length > 0
8974                                    && window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
8975                                }
8976                            )
8977                        }
8978                    }
8979
8980                    instance.amRecaptchaModelExecute = function ($event) {
8981                        window.amRecaptchaModel.execute($event);
8982                    }
8983
8984                    instance.amRecaptchaModelRecaptchaCallback = function ($event, $el) {
8985                        $el ??= $event.detail.form;
8986                        window.amRecaptchaModel.recaptchaCallback($event, $el);
8987                    }
8988
8989                    instance.amRecaptchaModelExpiredCallback = function ($event, $el) {
8990                        $el ??= $event.detail.form;
8991                        window.amRecaptchaModel.expiredCallback($event, $el);
8992                    }
8993
8994                    return instance;
8995                }
8996            });
8997        }
8998
8999        /**
9000         * @param {HTMLElement} elementToWrap
9001         * @return {string}
9002         */
9003        const getFormComponent = function (elementToWrap) {
9004            let formComponent = elementToWrap.hasAttribute('x-data')
9005                ? elementToWrap.getAttribute('x-data')
9006                : elementToWrap.closest('[x-data]').getAttribute('x-data');
9007            const match = formComponent.match(/\b([a-zA-Z0-9_$]+)\s*\(\s*\)/);
9008
9009            if (match && match[1]) {
9010                return match[1];
9011            }
9012
9013            return formComponent.replace(/\(\)$/g, '');
9014        }
9015
9016        setAmRecaptchaModelExecute();
9017        wrapFormSubmit();
9018    })(window.amRecaptchaModel = window.amRecaptchaModel || {});
9019</script>
9019
9020<input type="hidden" name="wp_ga4_server_side_view_item_list" id="wp_ga4_server_side_view_item_list" value="2be88ca4242c76e8253ac62474851065032d6833">
9021    
9021<script>
9022        window.addEventListener('load', function() {
9023            window.wpGA4ServerSide.pushViewItemList('2be88ca4242c76e8253ac62474851065032d6833');
9024        });
9025    </script>
vendor: 1 bytes, line 9025
9025
9026<script>
9027
9028/**
9029 * Restructure slide links to only apply to buttons
9030 */
9031function restructureSlideLinks() {
9032    
9033    // Find all slide wrappers that are inside links, but only within home-3image-cta-block
9034    const slideWrappers = document.querySelectorAll('.home-3image-cta-block .pagebuilder-slide-wrapper');
9035    
9036    slideWrappers.forEach(function(slideWrapper) {
9037        const parentLink = slideWrapper.parentElement;
9038        
9039        if (parentLink && parentLink.tagName === 'A' && parentLink.getAttribute('data-element') === 'link') {
9040            
9041            // Get link attributes
9042            const href = parentLink.getAttribute('href');
9043            const target = parentLink.getAttribute('target') || '';
9044            const linkType = parentLink.getAttribute('data-link-type') || '';
9045            const title = parentLink.getAttribute('title') || '';
9046            
9047            // Find the button inside the slide
9048            const button = slideWrapper.querySelector('.pagebuilder-slide-button');
9049            
9050            if (button && href) {
9051                
9052                // Create new link element for the button
9053                const newLink = document.createElement('a');
9054                newLink.setAttribute('href', href);
9055                if (target) newLink.setAttribute('target', target);
9056                if (linkType) newLink.setAttribute('data-link-type', linkType);
9057                if (title) newLink.setAttribute('title', title);
9058                newLink.setAttribute('data-element', 'link');
9059                
9060                // Insert slide wrapper after parent link
9061                parentLink.parentNode.insertBefore(slideWrapper, parentLink.nextSibling);
9062                
9063                // Remove the now-empty parent link
9064                parentLink.remove();
9065                
9066                // Wrap the button in the new link
9067                button.parentNode.insertBefore(newLink, button);
9068                newLink.appendChild(button);
9069                
9070            }
9071        }
9072    });
9073}
9074
9075/**
9076 * Initialize on page load and when content is updated
9077 */
9078function init() {
9079    // Run immediately
9080    restructureSlideLinks();
9081    
9082    // Run on DOM ready
9083    if (document.readyState === 'loading') {
9084        document.addEventListener('DOMContentLoaded', function() {
9085            setTimeout(restructureSlideLinks, 100);
9086        });
9087    } else {
9088        setTimeout(restructureSlideLinks, 100);
9089    }
9090    
9091    // Run on window load
9092    window.addEventListener('load', function() {
9093        setTimeout(restructureSlideLinks, 500);
9094    });
9095    
9096    // Run when content is updated (for dynamic content)
9097    document.addEventListener('contentUpdated', function() {
9098        setTimeout(restructureSlideLinks, 100);
9099    });
9100}
9101
9102init();
9103</script>
9103 
9104
9105<script src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Purdys_CustomWeltPixelEvents/js/custom-weltpixel-utils.js"></script>
9105
9106
9107<script>
9108    (() => {
9109        function src_default(Alpine) {
9110            Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
9111                let evaluate = evaluateLater(expression);
9112                let options = {
9113                    rootMargin: getRootMargin(modifiers),
9114                    threshold: getThreshold(modifiers)
9115                };
9116                let observer = new IntersectionObserver((entries) => {
9117                    entries.forEach((entry) => {
9118                        if (entry.isIntersecting === (value === "leave"))
9119                            return;
9120                        evaluate();
9121                        modifiers.includes("once") && observer.disconnect();
9122                    });
9123                }, options);
9124                observer.observe(el);
9125                cleanup(() => {
9126                    observer.disconnect();
9127                });
9128            }));
9129        }
9130        function getThreshold(modifiers) {
9131            if (modifiers.includes("full"))
9132                return 0.99;
9133            if (modifiers.includes("half"))
9134                return 0.5;
9135            if (!modifiers.includes("threshold"))
9136                return 0;
9137            let threshold = modifiers[modifiers.indexOf("threshold") + 1];
9138            if (threshold === "100")
9139                return 1;
9140            if (threshold === "0")
9141                return 0;
9142            return Number(`.${threshold}`);
9143        }
9144        function getLengthValue(rawValue) {
9145            let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
9146            return match ? match[1] + (match[2] || "px") : void 0;
9147        }
9148        function getRootMargin(modifiers) {
9149            const key = "margin";
9150            const fallback = "0px 0px 0px 0px";
9151            const index = modifiers.indexOf(key);
9152            if (index === -1)
9153                return fallback;
9154            let values = [];
9155            for (let i = 1; i < 5; i++) {
9156                values.push(getLengthValue(modifiers[index + i] || ""));
9157            }
9158            values = values.filter((v) => v !== void 0);
9159            return values.length ? values.join(" ").trim() : fallback;
9160        }
9161
9162        document.addEventListener("alpine:init", () => {
9163            window.Alpine.plugin(src_default);
9164        });
9165    })();
9166</script>
vendor: 1 bytes, line 9166
9166
vendor: 1,455 bytes, lines 9167-9169
9167<script>
9168(()=>{function g(n){n.directive("collapse",e),e.inline=(t,{modifiers:i})=>{i.includes("min")&&(t._x_doShow=()=>{},t._x_doHide=()=>{})};function e(t,{modifiers:i}){let r=l(i,"duration",250)/1e3,u=l(i,"min",0),h=!i.includes("min");t._x_isShown||(t.style.height=`${u}px`),!t._x_isShown&&h&&(t.hidden=!0),t._x_isShown||(t.style.overflow="hidden");let c=(d,s)=>{let o=n.setStyles(d,s);return s.height?()=>{}:o},f={transitionProperty:"height",transitionDuration:`${r}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};t._x_transition={in(d=()=>{},s=()=>{}){h&&(t.hidden=!1),h&&(t.style.display=null);let o=t.getBoundingClientRect().height;t.style.height="auto";let a=t.getBoundingClientRect().height;o===a&&(o=u),n.transition(t,n.setStyles,{during:f,start:{height:o+"px"},end:{height:a+"px"}},()=>t._x_isShown=!0,()=>{t.getBoundingClientRect().height==a&&(t.style.overflow=null)})},out(d=()=>{},s=()=>{}){let o=t.getBoundingClientRect().height;n.transition(t,c,{during:f,start:{height:o+"px"},end:{height:u+"px"}},()=>t.style.overflow="hidden",()=>{t._x_isShown=!1,t.style.height==`${u}px`&&h&&(t.style.display="none",t.hidden=!0)})}}}}function l(n,e,t){if(n.indexOf(e)===-1)return t;let i=n[n.indexOf(e)+1];if(!i)return t;if(e==="duration"){let r=i.match(/([0-9]+)ms/);if(r)return r[1]}if(e==="min"){let r=i.match(/([0-9]+)px/);if(r)return r[1]}return i}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(g)});})();
9169</script>
vendor: 1 bytes, line 9169
9169
9170<script>
9171    for (const [selector, deferUntil] of Object.entries({".product-slider section[x-data]":"intersect",".product-info [x-data]":"intersect","#filters-content [x-data]":"intersect","#review_form":"intersect","section[x-data^=initRecentlyViewedProductsComponent]":"intersect","div[x-data^=initBundleOptions]":"intersect","#product_addtocart_form [x-data]":"intersect","#notice-cookie-block":"idle"})) {
9172        document.querySelectorAll(selector).forEach(el => el.setAttribute('x-defer', `${deferUntil}`));
9173    }
9174</script>
vendor: 1 bytes, line 9174
9174
9175<script>
9176    (function () {
9177        "use strict";
9178
9179        const hasAlpine = new Promise(resolve => {
9180            window.addEventListener('alpine:initialized', resolve, {once: true, passive: true});
9181        });
9182
9183        const hasInteract = new Promise(resolve => {
9184            (events => {
9185                const onInteract = () => {
9186                    resolve();
9187                    events.forEach(type => window.removeEventListener(type, onInteract));
9188                }
9189                events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true}))
9190            })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown'])
9191        });
9192
9193        const onIntersect = (el) => {
9194            return new Promise(resolve => {
9195                const observer = new IntersectionObserver(entries => {
9196                    for (const entry of entries) {
9197                        if (entry.isIntersecting) {
9198                            observer.disconnect()
9199                            resolve();
9200                        }
9201                    }
9202                }, {});
9203                observer.observe(el);
9204            });
9205        }
9206
9207        function runComponent(el) {
9208            hasAlpine.then(() => {
9209                el.removeAttribute('x-ignore');
9210                queueMicrotask(() => Alpine.initTree(el));
9211            });
9212        }
9213
9214        function initDeferredComponents() {
9215            document.querySelectorAll('[x-data][x-defer]').forEach(el => {
9216                el.setAttribute('x-ignore', '');
9217                const deferUntil = (el.getAttribute('x-defer') || '').trim();
9218                switch (deferUntil) {
9219                    case 'interact':
9220                        hasInteract.then(() => runComponent(el));
9221                        break;
9222                    case 'intersect':
9223                        onIntersect(el).then(() => runComponent(el))
9224                        break;
9225                    case 'idle':
9226                        window.requestIdleCallback
9227                            ? window.requestIdleCallback(() => runComponent(el), {timeout: 4000})
9228                            : setTimeout(() => runComponent(el), 4000);
9229                        break;
9230                    case 'eager':
9231                        runComponent(el);
9232                        break;
9233                    default:
9234                        if (deferUntil.startsWith('event:') && deferUntil.length > 6) {
9235                            window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true});
9236                        }
9237                }
9238            });
9239        }
9240
9241        window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true});
9242    })()
9243</script>
vendor: 1 bytes, line 9243
9243
9244<script>
9245    (() => {
9246        // src/dialog.js
9247        function dialog_default(Alpine) {
9248            Alpine.directive("htmldialog", fylgjaAlpineDialog);
9249            function fylgjaAlpineDialog(el, { expression, modifiers }, { evaluateLater, cleanup }) {
9250            const evaluate = expression.length ? evaluateLater(expression) : () => {
9251            };
9252            const lockPageScroll = modifiers.includes("noscroll");
9253            el.style.display = null;
9254            el.hidden = false;
9255            el.style.length === 0 && el.removeAttribute("style");
9256            function scrollLock(use = true) {
9257                document.body.style.overflow = use ? "hidden" : "";
9258            }
9259            function escapeDialog(event) {
9260                if (event.key !== "Escape")
9261                return;
9262                event.preventDefault();
9263                evaluate();
9264            }
9265            function backdropDialog(event) {
9266                const rect = el.getBoundingClientRect();
9267                const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
9268                if (isInDialog)
9269                return;
9270                evaluate();
9271            }
9272            el._x_doShow = () => {
9273                if (el.hasAttribute("open"))
9274                return;
9275                el.showModal();
9276                document.addEventListener("keydown", escapeDialog);
9277                el.addEventListener("click", backdropDialog);
9278                scrollLock(lockPageScroll);
9279            };
9280            el._x_doHide = () => {
9281                if (!el.hasAttribute("open"))
9282                return;
9283                el.close();
9284                document.removeEventListener("keydown", escapeDialog);
9285                el.removeEventListener("click", backdropDialog);
9286                scrollLock(false);
9287            };
9288            cleanup(() => {
9289                document.removeEventListener("keydown", escapeDialog);
9290                el.removeEventListener("click", backdropDialog);
9291                scrollLock(false);
9292            });
9293            }
9294        }
9295
9296        // src/cdn.js
9297        document.addEventListener("alpine:init", () => {
9298            window.Alpine.plugin(dialog_default);
9299        });
9300    })();
9301</script>
9301
9302
9303<script type="module"
9304        src="https://www.purdys.com/static/version1790083580/frontend/Purdys2/hyva/en_US/Hyva_Theme/js/alpine3.min.js"
9305        defer
9306        crossorigin
9307></script>
vendor: 1 bytes, line 9307
9307
9308<script>
9309    'use strict';
9310    function dispatchMessages(messages, hideAfter) {
9311        const messagesEvent = new CustomEvent("messages-loaded", {
9312            detail: {
9313                messages: messages,
9314                hideAfter: hideAfter
9315            }
9316        });
9317        window.dispatchEvent(messagesEvent);
9318    }
9319
9320    if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
9321        console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
9322    }
9323
9324    (function( hyva, undefined ) {
9325
9326        hyva.initFormKey = () => {
9327            const inputSelector = 'input[name="form_key"]',
9328                formKey = hyva.getFormKey();
9329
9330            Array.from(document.querySelectorAll(inputSelector)).map(function (input) {
9331                input.value = formKey
9332            });
9333        }
9334
9335        hyva.initMessages = () => {
9336            try {
9337                const messages = hyva.getCookie('mage-messages');
9338                window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : [];
9339
9340                dispatchMessages(window.mageMessages);
9341
9342                                // empty `mage-messages` cookie
9343                const skipSetDomain = true;
9344                hyva.setCookie('mage-messages','', -1, skipSetDomain);
9345
9346            } catch (error) {
9347                console.warn('Error parsing Cookie Messages:', error);
9348            }
9349        }
9350
9351        window.addEventListener('DOMContentLoaded', hyva.initFormKey);
9352        hyva.alpineInitialized(hyva.initMessages)
9353
9354    }( window.hyva = window.hyva || {} ));
9355</script>
vendor: 1 bytes, line 9355
9355
9356<script>
9357    'use strict';
9358    {
9359        const private_content_key = 'mage-cache-storage';
9360        const private_content_expire_key = 'mage-cache-timeout';
9361        const private_content_version_key = 'private_content_version';
9362        const section_data_ids_key = 'section_data_ids';
9363        const mage_cache_session_id_key = 'mage-cache-sessid';
9364        const last_visited_store_key = 'last_visited_store';
9365
9366        const ttl = 604800;
9367
9368        if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
9369            console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
9370        }
9371
9372        function loadSectionData () {
9373            const browserStorage = hyva.getBrowserStorage();
9374            if (!browserStorage) {
9375                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
9376                    [{
9377                        type: "warning",
9378                        text: "Please enable LocalStorage in your browser."
9379                    }]
9380                );
9381                return;
9382            }
9383            try {
9384                let isInvalid = false;
9385
9386                if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) {
9387                    isInvalid = true;
9388                }
9389                hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false);
9390
9391                if (!hyva.getCookie(mage_cache_session_id_key)) {
9392                    isInvalid = true;
9393                    browserStorage.removeItem(private_content_key);
9394                    const skipSetDomain = true;
9395                    const days = false;
9396                    hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain)
9397                }
9398
9399                const cookieVersion = hyva.getCookie(private_content_version_key);
9400                const storageVersion = browserStorage.getItem(private_content_version_key);
9401
9402                if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) {
9403                    isInvalid = true;
9404                }
9405
9406                const privateContentExpires = browserStorage.getItem(private_content_expire_key);
9407                if (privateContentExpires && new Date(privateContentExpires) < new Date()) {
9408                    browserStorage.removeItem(private_content_key);
9409                }
9410
9411                if (isInvalid && cookieVersion) {
9412                    fetchPrivateContent([]);
9413                } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) {
9414                    const privateContent = JSON.parse(browserStorage.getItem(private_content_key));
9415                    if (
9416                        privateContent &&
9417                        privateContentExpires &&
9418                        privateContent.cart &&
9419                        privateContent.customer
9420                    ) {
9421                        dispatchPrivateContent(privateContent);
9422                    } else {
9423                        fetchPrivateContent([]);
9424                    }
9425                } else {
9426                    if (document.getElementById('default-section-data')) {
9427                        const privateContent = JSON.parse(document.getElementById('default-section-data').innerText.trim());
9428                        dispatchPrivateContent(privateContent);
9429                    } else {
9430                        dispatchPrivateContent({});
9431                    }
9432                }
9433
9434            } catch (error) {
9435                console.warn('Error retrieving Private Content:', error);
9436            }
9437        }
9438
9439        hyva.alpineInitialized(loadSectionData)
9440        window.addEventListener('reload-customer-section-data', loadSectionData);
9441
9442        window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data);
9443
9444        function dispatchPrivateContent(data) {
9445
9446            const privateContentEvent = new CustomEvent("private-content-loaded", {
9447                detail: {
9448                    data: window.processSectionDataBeforeDispatch(data)
9449                }
9450            });
9451            window.dispatchEvent(privateContentEvent);
9452        }
9453
9454        function fetchPrivateContent(sections) {
9455            fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, {
9456                method: 'GET',
9457                headers: {
9458                    'Content-Type': 'application/json',
9459                    'X-Requested-With': 'XMLHttpRequest'
9460                }
9461            })
9462                .then(response => response.ok && response.json())
9463                .then(
9464                    data => {
9465                        if (data) {
9466                            try {
9467                                const browserStorage = hyva.getBrowserStorage();
9468
9469                                // merge new data preserving non-invalidated sections
9470                                const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {};
9471
9472                                if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) {
9473                                    delete oldSectionData['checkout-data'];
9474                                }
9475                                const newSectionData = Object.assign(oldSectionData, data);
9476
9477                                dispatchPrivateContent(newSectionData);
9478
9479                                // don't persist messages, they've been dispatched already
9480                                if (newSectionData.messages && newSectionData.messages.messages ) {
9481                                    newSectionData.messages.messages = [];
9482                                }
9483
9484                                browserStorage.setItem(private_content_key, JSON.stringify(newSectionData));
9485
9486                                const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString();
9487                                browserStorage.setItem(private_content_expire_key, expiresAt);
9488
9489                                const newCookieVersion = hyva.getCookie(private_content_version_key);
9490                                browserStorage.setItem(private_content_version_key, newCookieVersion);
9491
9492                                // We don't need the section_data_ids in Hyvä, but we store them for compatibility
9493                                // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout
9494                                hyva.setCookie(
9495                                    section_data_ids_key,
9496                                    JSON.stringify(
9497                                        Object.keys(data).reduce((sectionDataIds, sectionKey) => {
9498                                            sectionDataIds[sectionKey] = data[sectionKey]['data_id'];
9499                                            return sectionDataIds;
9500                                        }, {})
9501                                    ),
9502                                    false,
9503                                    true
9504                                );
9505                            } catch (error) {
9506                                console.warn("Couldn't store privateContent", error);
9507                            }
9508                        }
9509                    }
9510                );
9511        }
9512    }
9513</script>
vendor: 1 bytes, line 9513
9513
9514<script>
9515    (() => {
9516        document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc()));
9517    })()
9518</script>
vendor: 1 bytes, line 9518
9518
9519<script>
9520    (events => {
9521        const dispatchUserInteractionEvent = () => {
9522            events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent))
9523            window.dispatchEvent(new Event('init-external-scripts'))
9524        };
9525        events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true}))
9526    })(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown'])
9527</script>
vendor: 1 bytes, line 9527
9527
9528<script>
9529    'use strict';
9530
9531    (() => {
9532        const initCarousels = (elements) => {
9533            const initSlider = (slider) => {
9534                slider.innerHTML = `<div data-role="swiper-wrapper" class="swiper-wrapper">${slider.innerHTML}</div>`;
9535                slider.parentElement.classList.add('relative');
9536                slider.insertAdjacentHTML(
9537                    'beforeend',
9538                    '\u000A\u003Cdiv\u000A\u0020\u0020\u0020\u0020class\u003D\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020swiper\u002Darrows\u002Dcontainer\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020max\u002Dlg\u0026\u0023x3A\u003Bmb\u002D6\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0022\u000A\u0020\u0020\u0020\u0020\u003E\u000A\u0020\u0020\u0020\u0020\u003Cdiv\u0020class\u003D\u0022swiper\u002Darrows\u002Dcontainer\u002Dwrapper\u0020\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Cdiv\u0020class\u003D\u0022swiper\u002Dbutton\u002Dprev\u0020\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020fill\u003D\u0022none\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020stroke\u002Dwidth\u003D\u00222\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020class\u003D\u0022rtl\u003Arotate\u002D180\u0022\u0020width\u003D\u002220\u0022\u0020height\u003D\u002220\u0022\u0020aria\u002Dhidden\u003D\u0022true\u0022\u003E\u000A\u0020\u0020\u003Cpath\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020d\u003D\u0022M15\u002019l\u002D7\u002D7\u00207\u002D7\u0022\u002F\u003E\u000A\u003C\u002Fsvg\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003C\u002Fdiv\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Cdiv\u0020class\u003D\u0022swiper\u002Dbutton\u002Dnext\u0020\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020fill\u003D\u0022none\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020stroke\u002Dwidth\u003D\u00222\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020class\u003D\u0022rtl\u003Arotate\u002D180\u0022\u0020width\u003D\u002220\u0022\u0020height\u003D\u002220\u0022\u0020aria\u002Dhidden\u003D\u0022true\u0022\u003E\u000A\u0020\u0020\u003Cpath\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020d\u003D\u0022M9\u00205l7\u00207\u002D7\u00207\u0022\u002F\u003E\u000A\u003C\u002Fsvg\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003C\u002Fdiv\u003E\u000A\u0020\u0020\u0020\u0020\u003C\u002Fdiv\u003E\u000A\u003C\u002Fdiv\u003E\u000A\u0020\u0020\u0020\u0020\u003Cdiv\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020class\u003D\u0022swiper\u002Dpagination\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020my\u002D6\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0022\u000A\u0020\u0020\u0020\u0020\u003E\u003C\u002Fdiv\u003E\u000A');
9539                slider.classList.add('swiper');
9540                slider.classList.add('swiper-slider-content');
9541
9542                const slides = slider.querySelectorAll('[data-content-type="slide"]');
9543
9544                slides.forEach(slide => {
9545                    slide.classList.add('swiper-slide');
9546                });
9547
9548                const isAutoplay = slider.dataset.autoplay === 'true';
9549                const autoplaySpeed = slider.dataset.autoplaySpeed;
9550                const isLoop = slider.dataset.infiniteLoop === 'true';
9551
9552                const swiperOptions = {
9553                    spaceBetween: 0,
9554                    loop: isLoop,
9555                    speed: 800,
9556                    threshold: 20,
9557                    autoHeight: true,
9558                    navigation: {
9559                        nextEl: '.swiper-button-next',
9560                        prevEl: '.swiper-button-prev',
9561                    },
9562                    pagination: {
9563                        el: '.swiper-pagination',
9564                        type: 'bullets',
9565                        dynamicBullets: true,
9566                        dynamicMainBullets: 4,
9567                        clickable: true,
9568                    },
9569                    mousewheel: {
9570                        forceToAxis: true,
9571                        thresholdDelta: 10,
9572                    },
9573                    autoplay: isAutoplay && autoplaySpeed ? {
9574                        delay: autoplaySpeed
9575                    } : undefined,
9576                };
9577
9578                initSwiperSlider(slider, swiperOptions);
9579            }
9580
9581            elements.forEach(element => {
9582                if (element.dataset.contentType === 'slider') {
9583                    initSlider(element);
9584                }
9585            });
9586        };
9587
9588
9589        document.addEventListener('alpine:init', () => {
9590            const carouselElements = document.querySelectorAll(
9591                `[data-content-type="products"][data-appearance="carousel"],
9592                [data-content-type="slider"],[data-content-type="products"][data-appearance="insider_carousel"]`
9593            );
9594
9595            if (carouselElements.length > 0) {
9596                initCarousels(carouselElements);
9597            }
9598        });
9599    })();
9600</script>
9600<script>
9601    'use strict';
9602
9603    (() => {
9604        const applyShowOnHover = (element) => {
9605            const showOverlayOnHover = (element) => {
9606                const overlay = element.querySelector('.pagebuilder-overlay');
9607                const color = overlay.dataset.overlayColor;
9608
9609                element.addEventListener('mouseover', () => {
9610                    overlay.style.backgroundColor = color;
9611                });
9612                element.addEventListener('mouseout', () => {
9613                    overlay.style.backgroundColor = 'transparent';
9614                });
9615            };
9616
9617            const showButtonOnHover = (element) => {
9618                const button = element.querySelector('.pagebuilder-banner-button');
9619
9620                element.addEventListener('mouseover', () => {
9621                    button.style.opacity = '1';
9622                    button.style.visibility = 'visible';
9623                });
9624                element.addEventListener('mouseout', () => {
9625                    button.style.opacity = '0';
9626                    button.style.visibility = 'hidden';
9627                });
9628            };
9629
9630            if (element.dataset.showOverlay === 'hover') {
9631                showOverlayOnHover(element);
9632            }
9633            if (element.dataset.showButton === 'hover') {
9634                showButtonOnHover(element);
9635            }
9636        };
9637
9638        window.addEventListener('DOMContentLoaded', () => {
9639            document.querySelectorAll('[data-content-type="banner"],[data-content-type="slider"]').forEach(element => {
9640                applyShowOnHover(element);
9641            });
9642        });
9643    })();
9644</script>
vendor: 1 bytes, line 9644
9644
9645<script>
9646    'use strict';
9647
9648    (function () {
9649        const modals = [];
9650        const excludedFromFocusTrapping = new Set();
9651
9652        function trapFocusInNextModalWithOverlay() {
9653            for (let idx = modals.length -1; idx >= 0; idx--) {
9654                const nextOnStack = modals[idx];
9655                const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name];
9656                if (! isOverlayDisabled(nextDialogElement)) {
9657                    hyva.trapFocus(nextDialogElement);
9658                    break;
9659                }
9660            }
9661        }
9662
9663        function focusables(dialogElement) {
9664            const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
9665            return Array.from(dialogElement.querySelectorAll(selector))
9666                .filter(el => !el.hasAttribute('disabled'));
9667        }
9668
9669        function firstVisible(elements) {
9670            const a = Array.from(elements);
9671            for (let i = 0; i < a.length; i++) {
9672                if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i];
9673            }
9674            return null;
9675        }
9676
9677        function isInViewport(element) {
9678            const rect = element && element.getBoundingClientRect();
9679            return rect &&
9680                rect.top >= 0 &&
9681                rect.left >= 0 &&
9682                rect.right <= window.innerWidth &&
9683                rect.bottom <= window.innerHeight;
9684        }
9685
9686        function setFocusAfterTransition(dialogElement, duration) {
9687                        const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]'));
9688            const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]'));
9689            next: for (let candidate of candidates) {
9690                for (let child of nested) {
9691                    if (child.contains(candidate)) continue next;
9692                }
9693                setTimeout(() => candidate.focus(), 50);
9694                break;
9695            }
9696            window.setTimeout(() => {
9697                const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
9698                    focusables(dialogElement)[0] ||
9699                    null;
9700                focusElement && isInViewport(focusElement) && focusElement.focus();
9701            }, Math.max(1, duration));
9702        }
9703
9704        function determineTrigger($refs, dialog, trigger) {
9705                        if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) {
9706                return dialog.target;
9707            }
9708                        if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) {
9709                return trigger.target;
9710            }
9711                        if (typeof trigger === 'string') {
9712                try {
9713                    return $refs[trigger] || document.querySelector(trigger)
9714                } catch (e) {}
9715            }
9716                        if (trigger instanceof Element) {
9717                return trigger;
9718            }
9719
9720                        return null;
9721        }
9722
9723        function isOverlayDisabled(dialog) {
9724            return dialog && dialog.hasAttribute('x-no-overlay')
9725        }
9726
9727        function areRemainingModalsWithoutOverlay(modals)
9728        {
9729            const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled);
9730
9731            return overflowDisabled.length === modals.length;
9732        }
9733
9734        window.hyva.modal = function(options = {}) {
9735                        if (this.$el && this.$el.dataset && this.$el.dataset.options) {
9736                try {
9737                    options = Object.assign(options, JSON.parse(this.$el.dataset.options || '{}'));
9738                } catch (e) {
9739                    throw new Error('Cannot read the dialog options from the data-options attribute: not valid JSON');
9740                }
9741            }
9742
9743            const config = Object.assign({
9744                dialog: 'dialog',                 duration: 300,                 transitionEnter: 'transition ease-out duration-300',
9745                transitionEnterStart: 'opacity-0',
9746                transitionEnterEnd: 'opacity-100',
9747                transitionLeave: 'transition ease-in duration-300',
9748                transitionLeaveStart: 'opacity-100',
9749                transitionLeaveEnd: 'opacity-0',
9750            }, options);
9751            let lastHide = 0;
9752
9753            return {
9754                opened: {},
9755                show(dialog, trigger) {
9756                    const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger);
9757                    const name = typeof dialog === 'string' ? dialog : config.dialog;
9758                    const dialogElement = this.$refs[name];
9759                    if (! dialogElement) {
9760                                                return;
9761                    }
9762                    const useOverlay = ! dialogElement.hasAttribute('x-no-overlay');
9763
9764                    dialogElement.scrollTop = 0;
9765
9766                                        if (this.opened[name]) {
9767                        return;
9768                    }
9769
9770                    if (focusTargetAfterHide) {
9771                        focusTargetAfterHide.setAttribute('aria-expanded', 'true');
9772                    }
9773
9774                    this.opened[name] = true;
9775                    useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement));
9776                    setFocusAfterTransition(dialogElement, config.duration);
9777
9778                    const frame = {name, instance: this, focusTarget: focu
9778sTargetAfterHide, time: Date.now()};
9779
9780                    modals.push(frame);
9781                    if (useOverlay) {
9782                        document.body.classList.add('overflow-hidden');
9783                    }
9784                    return new Promise(resolve => frame.resolve = resolve);
9785                },
9786                cancel() {
9787                    this.hide(false);
9788                },
9789                ok() {
9790                    this.hide(true);
9791                },
9792                hide(value) {
9793                                        if (Date.now() - lastHide < config.duration) {
9794                        return;
9795                    }
9796                    lastHide = Date.now();
9797
9798                    const modal = modals.pop() || {};
9799                    if (! modal.instance) {
9800                        return;
9801                    }
9802
9803                    const name = modal.name;
9804                    this.opened[name] = false;
9805                    hyva.releaseFocus(modal.instance.$refs[modal.name])
9806                    trapFocusInNextModalWithOverlay();
9807
9808                    const nextFocusAfterHide = modal.focusTarget;
9809                    nextFocusAfterHide && setTimeout(() => {
9810                        nextFocusAfterHide.setAttribute('aria-expanded', 'false');
9811                        nextFocusAfterHide.focus()
9812                    }, config.duration);
9813
9814                    if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
9815                        document.body.classList.remove('overflow-hidden');
9816                    }
9817
9818                    modal.resolve(value);
9819                },
9820                overlay(dialog) {
9821                    dialog = this.$el.dataset.dialogRefName || dialog;
9822                    const name = typeof dialog === 'string' ? dialog : config.dialog;
9823                    return {
9824                        ['x-show']() {
9825                            return this.opened[name]
9826                        },
9827                        ['x-transition:enter']: config.transitionEnter,
9828                        ['x-transition:enter-start']: config.transitionEnterStart,
9829                        ['x-transition:enter-end']: config.transitionEnterEnd,
9830                        ['x-transition:leave']: config.transitionLeave,
9831                        ['x-transition:leave-start']: config.transitionLeaveStart,
9832                        ['x-transition:leave-end']: config.transitionLeaveEnd,
9833                        ['@hyva-modal-show.window'](event) {
9834                            event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide)
9835                        }
9836                    };
9837                },
9838                showDialogOnInit() {
9839                    const parent = this.$el.closest('[data-dialog-ref-name]');
9840                    if (parent && parent.dataset.dialogRefName) {
9841                        this.$dispatch('hyva-modal-show', {dialog: parent.dataset.dialogRefName})
9842                    }
9843                }
9844            };
9845        }
9846
9847        window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length -1]
9848
9849        window.hyva.modal.pop = function () {
9850            if (modals.length > 0) {
9851                const modal = modals[modals.length -1];
9852                modal.instance.hide();
9853            }
9854        }
9855
9856        window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {
9857            typeof selectors === 'string' || selectors instanceof String
9858                ? excludedFromFocusTrapping.add(selectors)
9859                : selectors.map(selector => excludedFromFocusTrapping.add(selector));
9860        }
9861
9862        window.hyva.modal.eventListeners = {
9863            keydown: event => {
9864                if (event.key === 'Escape') {
9865                    window.hyva.modal.pop();
9866                }
9867            },
9868                        click: event => {
9869                if (modals.length > 0) {
9870                    const modal = modals[modals.length -1];
9871                    const dialog = modal.instance.$refs[modal.name];
9872                    if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago
9873                        ! isOverlayDisabled(dialog) && // if dialog has overlay
9874                        ! dialog.contains(event.target)) { // if click is outside of dialog
9875                        modal.instance.hide();
9876                    }
9877                }
9878            }
9879        };
9880
9881        document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);
9882
9883        document.addEventListener('click', window.hyva.modal.eventListeners.click);
9884    })();
9885    window.addEventListener('alpine:init', () => {
9886        Alpine.data('hyvaModal', window.hyva.modal);
9887    }, {once: true});
9888</script>
vendor: 1 bytes, line 9888
9888
9889<script>
9890    function initConfigurableOptions(productId, optionConfig) {
9891
9892        function findPathParam(key) {
9893                        const baseUrl = (BASE_URL.substring(0, 2) === '//' ? 'http:' : '') + BASE_URL;
9894            const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/');
9895            const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3);
9896            for (let i = 0; i < pathParts.length; i += 2) {
9897                if (pathParts[i] === key && pathParts.length > i) {
9898                    return pathParts[i + 1];
9899                }
9900            }
9901        }
9902
9903        return {
9904            optionConfig,
9905            productId,
9906            itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'),
9907            allowedAttributeOptions: [],
9908            selectedValues: [],
9909            init() {
9910                this.findAllowedAttributeOptions();
9911                this.$nextTick(() => {
9912                    if (typeof this.optionConfig.defaultValues === 'object') {
9913                        for (const [attributeId, value] of Object.entries(this.optionConfig.defaultValues)) {
9914                            this.changeOption(attributeId, value + '');
9915                        }
9916                    }
9917                    this.preselectQuerystringItems();
9918                    this.preselectLocationHashItems();
9919                });
9920            },
9921            productIndex: 0,
9922            productIndexForPrice: 0,
9923            optionIsActive(attributeId, optionId) {
9924                                return !!this.getAllowedAttributeOptions(attributeId).find(
9925                    option => option.id === optionId
9926                )
9927            },
9928            optionIsEnabled(attributeId, optionId) {
9929                                for (const productId in this.optionConfig.index) {
9930                    if (this.optionConfig.index[productId][attributeId] === optionId) {
9931                        return true;
9932                    }
9933                }
9934                return false;
9935            },
9936            findSimpleIndex() {
9937                                this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues);
9938                this.productIndexForPrice = this.findCheapestProductForPartialSelection(this.selectedValues);
9939            },
9940            calculateSimpleIndexForPartialSelection(selectedValues) {
9941                if (selectedValues.length === 0) return 0;
9942                return this.findProductIdsForPartialSelection(selectedValues)[0];
9943            },
9944            calculateSimpleIndexForFullSelection(selectedValues) {
9945                if (! this.isFullSelection(selectedValues)) return false;
9946
9947                const productIndexes = this.optionConfig.index;
9948                return Object.keys(productIndexes).find(productIndex => {
9949                    const productCandidateOptions = productIndexes[productIndex];
9950
9951                    for (const productOption in productCandidateOptions) {
9952                        if (
9953                            !selectedValues[productOption] ||
9954                            selectedValues[productOption] !== productCandidateOptions[productOption]
9955                        ) {
9956                            return false;
9957                        }
9958                    }
9959                    return productIndex;
9960                });
9961            },
9962            findAllowedAttributeOptions() {
9963                                this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues);
9964            },
9965            calculateAllowedAttributeOptions(selectedValues) {
9966                const allAttributes = this.optionConfig.attributes;
9967                const allAttributesSorted = Object.values(allAttributes).sort((a,b) => {
9968                    return a.position - b.position
9969                });
9970
9971                const newAllowedAttributeOptions = [];
9972
9973                allAttributesSorted.forEach(attribute => {
9974                    const selectionWithoutAttr = Object.assign({}, this.removeAttrFromSelection(selectedValues, attribute.id));
9975                    const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr);
9976                    newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => {
9977                        return !!option.products.find(product => {
9978                            return availableIndexes.includes(product);
9979                        })
9980                    });
9981                });
9982                return newAllowedAttributeOptions;
9983            },
9984            calculateAvailableProductIndexes(selectedOptions) {
9985                if (Object.keys(selectedOptions).length === 0) {
9986                                        if (Object.values(this.optionConfig.salable || {}).length) {
9987                                                return [].concat.apply([], [].concat.apply([], Object.values(this.optionConfig.salable).map(Object.values))).filter((x, i, a) => a.indexOf(x) === i)
9988                    }
9989                                        return Object.keys(this.optionConfig.index);
9990                }
9991
9992                                const selectedIds = Object.keys(selectedOptions);
9993                if (Object.values(this.optionConfig.salable || {}).length) {
9994                                        const selectedOptionIndexes = selectedIds.map(attrId => {
9995                        const optionValue = selectedOptions[attrId];
9996                        return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || []
9997                    })
9998                                        return selectedOptionIndexes.reduce((acc, optionIndexes) => {
9999                        return acc.filter(index => optionIndexes.includes(index));
10000                    });
10001                } else {
10002                                        const productIndexes = this.optionConfig.index;
10003                    return Object.keys(productIndexes).filter(index => {
10004                                                for (const attrId of selectedIds) {
10005                            if (productIndexes[index][attrId] !== `${selectedOptions[attrId]}`) return false
10006                        }
10007                        return true
10008                    });
10009                }
10010            },
10011            findAttributeByOptionId(optionId) {
10012                for (const attributeId in this.optionConfig.attributes) {
10013                    const attributeOptions = this.optionConfig.attributes[attributeId].options || [];
10014                    if (attributeOptions.find(option => option.id === optionId)) {
10015                        return attributeId;
10016                    }
10017                }
10018            },
10019            getAllowedAttributeOptions(attributeId) {
10020                return this.allowedAttributeOptions[attributeId] || []
10021            },
10022            getAllAttributeOptions(attributeId) {
10023                return (
10024                    this.optionConfig.attributes[attributeId] &&
10025                    this.optionConfig.attributes[attributeId].options
10026                ) || []
10027            },
10028            getProductIdsForOption(option) {
10029                const attributeId = this.findAttributeByOptionId(option.id);
10030                const allOptions = this.optionConfig.attributes[attributeId];
10031                const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id);
10032                return opt && opt.products
10033                    ? opt.products
10034                    : [];
10035            },
10036            findProductIdsForPartialSelection(optionSelection) {
10037                const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => {
10038                    const newCandidates = this.getProductIdsForOption({id: optionId});
10039                    return candidates === null
10040                        ? newCandidates
10041                        : candidates.filter(productId => newCandidates.includes(productId));
10042                }, null);
10043                return candidateProducts || [];
10044            },
10045            findCheapestProductForPartialSelection(optionSelection) {
10046                const candidateProducts = this.findProductIdsForPartialSelection(optionSelection);
10047                return candidateProducts.reduce((cheapest, simpleIdx) => {
10048                    // in the first iteration we start with simpleIdx as the currently cheapest product
10049                    if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx;
10050                    const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount;
10051                    return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount
10052                        ? simpleIdx
10053                        : cheapest;
10054                }, 0)
10055            },
10056            findProductIdToUseForOptionPrice(option) {
10057                // try to find a product for a complete selection
10058                const attributeId = this.findAttributeByOptionId(option.id);
10059                const optionSelection = Object.assign({}, this.selectedValues, {[attributeId]: option.id});
10060                const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection);
10061                // if there is no complete selection, use the cheapest product for the option
10062                return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection);
10063            },
10064            getAttributeOptionLabel(option) {
10065                const optionProduct = this.findProductIdToUseForOptionPrice(option);
10066
10067                if ((! optionProduct) || (optionProduct === this.productIndexForPrice)) {
10068                    return option.label;
10069                }
10070
10071                const currentPrice = this.getOptionPriceAdjustmentBasePrice();
10072
10073                if (this.optionConfig.optionPrices[optionProduct]) {
10074                    const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount;
10075                    if (optionPrice !== currentPrice){
10076                        return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true);
10077                    }
10078                }
10079                return option.label;
10080            },
10081            getOptionPriceAdjustmentBasePrice() {
10082                if (this.optionConfig.optionPrices[this.productIndexForPrice]) {
10083                    return this.optionConfig.optionPrices[this.productIndexForPrice].finalPrice.amount
10084                }
10085                return this.optionConfig.prices.finalPrice.amount; // default price if no option selection
10086            },
10087            clearOptionIfActive(optionId, value) {
10088                if (this.selectedValues[optionId] === value) {
10089                    this.blurLabel()
10090                    this.changeOption(optionId, '')
10091                }
10092            },
10093            removeAttrFromSelection(selectedValues, attributeId) {
10094                                attributeId = parseInt(attributeId);
10095                return selectedValues.reduce((newSelection, val, attr) => {
10096                    if (attr !== attributeId) {
10097                        newSelection[attr] = val;
10098                    }
10099                    return newSelection;
10100                }, []);
10101            },
10102            changeOption(attributeId, value) {
10103                if (value === '') {
10104                    this.selectedValues = this.removeAttrFromSelection(this.selectedValues, attributeId)
10105                } else if (value && this.getAllowedAttributeOptions(attributeId).find(option => option.id === value)) {
10106                                        this.selectedValues[attributeId] = value;
10107                }
10108                this.findSimpleIndex();
10109                this.findAllowedAttributeOptions();
10110                this.updatePrices();
10111                this.updateGallery();
10112
10113                const candidates = this.findProductIdsForPartialSelection(this.selectedValues);
10114
10115                                window.dispatchEvent(
10116                    new CustomEvent(
10117                        'configurable-selection-changed',
10118                        {
10119                            detail: {
10120                                productId: this.productId,
10121                                optionId: attributeId,
10122                                value: value,
10123                                productIndex: this.productIndex,
10124                                selectedValues: this.selectedValues,
10125                                candidates: candidates,
10126                                skuCandidates: Object.values(candidates).map(id =>
10126 this.optionConfig.sku?.[id] ?? null).filter(Boolean),
10127                            }
10128                        }
10129                    )
10130                );
10131            },
10132            calculateIsMinimalPrice() {
10133                return ! this.isFullSelection(this.selectedValues);
10134            },
10135            isFullSelection(selectedValues) {
10136                return Object.values(selectedValues).length === Object.keys(this.optionConfig.attributes).length;
10137            },
10138            updatePrices() {
10139                const value = this.optionConfig.optionPrices[this.productIndexForPrice] || this.optionConfig.prices;
10140                window.dispatchEvent(
10141                    new CustomEvent(
10142                        "update-prices-" + this.productId,
10143                        {
10144                            detail: Object.assign(
10145                                value,
10146                                { isMinimalPrice: this.calculateIsMinimalPrice() }
10147                            )
10148                        }
10149                    )
10150                );
10151            },
10152            updateGallery () {
10153                if (this.productIndex) {
10154                    const images = this.optionConfig.images[this.productIndex];
10155                    images && window.dispatchEvent(new CustomEvent(
10156                        "update-gallery",
10157                        { detail: this.sortImagesByPosition(images) }
10158                    ));
10159                } else {
10160                    window.dispatchEvent(new Event("reset-gallery"));
10161                }
10162            },
10163            sortImagesByPosition(images) {
10164                return images.sort((x, y) => {
10165                    return x.position === y.position ? 0 : (parseInt(x.position) > parseInt(y.position) ? 1 : -1)
10166                });
10167            },
10168            onGetCartData(data) {
10169                            },
10170            preselectCartItems(data) {
10171                // pre-select options based on cart data for current (quote) itemId
10172                const cart = data && data.cart;
10173                if (cart && cart.items) {
10174                    const cartItem = cart.items.find((item) => {
10175                        return (
10176                            item.item_id === this.itemId
10177                            && item.product_id === this.productId
10178                        )
10179                    });
10180                    if (cartItem && cartItem.options && cartItem.options.length) {
10181                        cartItem.options.map(option => {
10182                            this.changeOption(option.option_id, option.option_value);
10183                        })
10184                    }
10185                }
10186            },
10187            preselectQuerystringItems() {
10188                // pre-select option like ?size=167
10189                const urlQueryParams = new URLSearchParams(window.location.search.replace('?',''));
10190                this.preselectItemsBasedOnLocation(attribute => urlQueryParams.get(attribute.code));
10191            },
10192            preselectLocationHashItems() {
10193                // pre-select option like #144=167
10194                const urlHashParams = new URLSearchParams(window.location.hash.replace('#',''));
10195                this.preselectItemsBasedOnLocation(attribute => urlHashParams.get(attribute.id));
10196            },
10197            preselectItemsBasedOnLocation(getLocationValue) {
10198                Object.values(this.optionConfig.attributes).map(attribute => {
10199                    const v = getLocationValue(attribute);
10200                    v && this.changeOption(attribute.id, v)
10201                });
10202            }
10203        }
10204    }
10205</script>
vendor: 1 bytes, line 10205
10205
10206<script>
10207    function initSwatchOptions(swatchConfig) {
10208        return {
10209            swatchConfig,
10210            getAttributeSwatchData(attributeId) {
10211                const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]);
10212                swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']);
10213
10214                return swatchConfig;
10215            },
10216            mapSwatchTypeNumberToTypeCode(typeNumber) {
10217                switch ("" + typeNumber) {
10218                    case "1":
10219                        return "color"
10220                    case "2":
10221                        return "image"
10222                    case "3":
10223                        return "empty"
10224                    case "0":
10225                    default:
10226                        return "text"
10227                }
10228            },
10229            getTypeOfFirstOption(attributeId) {
10230                for (const optionId in this.swatchConfig[attributeId]) {
10231                    const option = this.swatchConfig[attributeId][optionId];
10232                    if (typeof option.type !== 'undefined') {
10233                        return this.mapSwatchTypeNumberToTypeCode(option.type);
10234                    }
10235                }
10236            },
10237            getVisualSwatchType(attributeId, targetOptionId) {
10238                // If a type configuration is present for the given option id, use it
10239                const config = this.swatchConfig[attributeId];
10240                if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') {
10241                    return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type);
10242                }
10243
10244                // Otherwise - if no config is present for the target option - use the type of the first option
10245                // with a type property from the attribute, thus assuming its the same type as the target option.
10246                // (This edge case condition can occur on single swatch products if some options are not salable)
10247                return this.getTypeOfFirstOption(attributeId);
10248            },
10249            getSwatchType(attributeId, optionId) {
10250                // Deserialize the attribute details the first time they are used
10251                if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) {
10252                    this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId);
10253                }
10254                const type =  this.swatchConfig[attributeId] &&
10255                    this.swatchConfig[attributeId].details &&
10256                    this.swatchConfig[attributeId].details.swatch_input_type ||
10257                    "empty";
10258                return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type;
10259            },
10260            isTextSwatch(attributeId, optionId) {
10261                return this.getSwatchType(attributeId, optionId) === 'text';
10262            },
10263            isVisualSwatch(attributeId, optionId) {
10264                const type = this.getSwatchType(attributeId, optionId);
10265
10266                return ['image', 'color'].includes(type);
10267            },
10268            getSwatchBackgroundStyle(attributeId, optionId) {
10269                const config = this.getSwatchConfig(attributeId, optionId);
10270                const type = this.getSwatchType(attributeId, optionId);
10271
10272                if (type === "color") {
10273                        return 'background-color:' + config.value;
10274                } else if (type === "image") {
10275                        return "background: #fff url('" + config.value + "') no-repeat center";
10276                } else {
10277                    return '';
10278                }
10279            },
10280            getSwatchText(attributeId, optionId) {
10281                const config = this.getSwatchConfig(attributeId, optionId);
10282                return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId);
10283            },
10284            getOptionLabelFromOptionConfig(attributeId, optionId) {
10285                // Fallback if no value is present in swatchConfig data
10286                // Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190
10287                const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId);
10288                return option && option[0] && option[0].label ||'';
10289            },
10290            getSwatchConfig(attributeId, optionId) {
10291                return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId]
10292                    ? this.swatchConfig[attributeId][optionId]
10293                    : false;
10294            },
10295            activeTooltipItem: false,
10296            tooltipPositionElement: false,
10297            isTooltipVisible() {
10298                return this.activeTooltipItem &&
10299                    this.getSwatchConfig(
10300                        this.activeTooltipItem.attribute,
10301                        this.activeTooltipItem.item
10302                    );
10303            },
10304            isFirstItemCol() {
10305                return this.activeTooltipItem.index === 0;
10306            },
10307            getTooltipImageStyle(attributeId, optionId) {
10308                const config = this.getSwatchConfig(attributeId, optionId);
10309                const type = this.getSwatchType(attributeId, optionId);
10310
10311                if (type === "color") {
10312                    return 'background-color:' + config.value + '; width: 110px; height: 90px;';
10313                } else if (type === "image") {
10314                    return "background: #ffffff url('" + config.thumb +
10315                        "') center center no-repeat; width: 110px; height: 90px;";
10316                } else {
10317                    return 'display:none';
10318                }
10319            },
10320            getTooltipPosition() {
10321                return this.tooltipPositionElement ?
10322                    `top: ${this.tooltipPositionElement.offsetTop}px;` +
10323                    `left: ${
10324                        this.tooltipPositionElement.offsetLeft - (
10325                            this.tooltipPositionElement.closest('.snap') &&
10326                            this.tooltipPositionElement.closest('.snap').scrollLeft ||
10327                            0
10328                        )
10329                    }px;` : ''
10330            },
10331            getTooltipLabel() {
10332                return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label
10333            },
10334            focusedLabel: false,
10335            focusLabel(optionId) {
10336                this.focusedLabel = optionId;
10337            },
10338            blurLabel() {
10339                this.focusedLabel = false;
10340            },
10341            showSwatches: false,
10342            initShowSwatchesIntersect() {
10343                if ('IntersectionObserver' in window && !window.scrollY) {
10344                    let io = new IntersectionObserver(
10345                        entries => {
10346                            entries.map(entry => {
10347                                if (entry.isIntersecting) {
10348                                    this.showSwatches = true;
10349                                    io.unobserve(this.$root);
10350                                }
10351                            })
10352                        }
10353                    );
10354                    io.observe(this.$root);
10355                } else {
10356                    this.showSwatches = true
10357                }
10358            }
10359        }
10360    }
10361</script>
vendor: 1 bytes, line 10361
10361
10362<script>
10363    'use strict';
10364
10365    (function () {
10366        const EVENT_NAME = 'amhideprice-swatch-change';
10367        const selectors = {
10368            swatchOptions: 'div[x-data^=initConfigurable][x-data*=Options]',
10369            parentSwatchContainers: '.product_addtocart_form',
10370            qty: '[x-data^=initQtyField]',
10371            wishlist: '[data-addto="wishlist"]',
10372            compare: '[data-addto="compare"]',
10373            addToCart: '.product-info button.btn.btn-primary, [x-data^=initQtyField] ~ button.btn.btn-primary',
10374            replaceAddToCart: '.amasty-hide-price-button',
10375            replacePriceButton: '[data-amhide="AmastyHidePricePopup"]',
10376            priceBox: '.price-box.price-final_price'
10377        };
10378
10379        const injectSwatchObserver = function () {
10380            const swatches = document.querySelectorAll(selectors.swatchOptions);
10381
10382            swatches.forEach(swatch => {
10383                const injectedDispatch = `$dispatch('${EVENT_NAME}', `
10384                    + `{ productIndex: productIndex, element: $el, optionConfig: optionConfig })`;
10385
10386                let mutatedInitAttribute = swatch.getAttribute('x-init');
10387                mutatedInitAttribute += `; $watch('productIndex', (productIndex) => { ${injectedDispatch} });`;
10388                swatch.setAttribute('x-init', mutatedInitAttribute);
10389            });
10390        };
10391
10392        const hideProductElements = function ({ detail: eventData }) {
10393            const { element, optionConfig, productIndex } = eventData;
10394
10395            const isVisible = optionConfig?.optionPrices?.[productIndex]?.finalPrice?.amount !== 0;
10396            setProductElementsVisibility(element, isVisible, optionConfig, productIndex);
10397        }
10398
10399        const setProductElementsVisibility = function (element, isVisible, optionConfig, productIndex) {
10400            const parentNode = getParentNode(element, optionConfig);
10401            if (!parentNode) {
10402                return;
10403            }
10404
10405            const affectedNodes = getAffectedNodes(parentNode, optionConfig, productIndex);
10406            affectedNodes.forEach((node) => {
10407                isVisible ? node.classList.remove('hidden') : node.classList.add('hidden');
10408            });
10409
10410            amHidePrice.removeHidePriceButtons(parentNode);
10411            !isVisible && insertHidePriceElements(parentNode, optionConfig, productIndex);
10412        }
10413
10414        const getParentNode = function (element, optionConfig) {
10415            const parentContainers = selectors.parentSwatchContainers + ', ' + optionConfig?.amHidePrice.selectors.parent ?? '';
10416
10417            return element.closest(parentContainers) ?? element.parentNode?.parentNode;
10418        }
10419
10420        const insertHidePriceElements = function (parentNode, optionConfig, productIndex) {
10421            amHidePrice.insertAfterDomElement(
10422                parentNode,
10423                selectors.priceBox,
10424                optionConfig?.amHidePrice.children[productIndex]
10425            );
10426            amHidePrice.insertAfterDomElement(
10427                parentNode,
10428                selectors.addToCart,
10429                optionConfig?.amHidePrice.addToCartHtml
10430            );
10431        }
10432
10433        const getAffectedNodes = function (parentNode, optionConfig, productIndex) {
10434            if (parentNode === null) {
10435                return [];
10436            }
10437
10438            const allAffectedNodes = [selectors.qty];
10439
10440            if (optionConfig?.amHidePrice.hide_compare) {
10441                allAffectedNodes.push(selectors.compare);
10442            }
10443
10444            if (optionConfig?.amHidePrice.hide_wishlist) {
10445                allAffectedNodes.push(selectors.wishlist);
10446            }
10447
10448            if (optionConfig?.amHidePrice.hide_price || !!optionConfig?.amHidePrice.children[productIndex]) {
10449                allAffectedNodes.push(selectors.priceBox);
10450            }
10451
10452            if (optionConfig?.amHidePrice.hide_addtocart) {
10453                allAffectedNodes.push(selectors.addToCart);
10454                allAffectedNodes.push(optionConfig?.amHidePrice.selectors.add_to_cart);
10455            }
10456
10457            return parentNode.querySelectorAll(allAffectedNodes.join(',')) ?? [];
10458        }
10459
10460        injectSwatchObserver();
10461        window.addEventListener(EVENT_NAME, hideProductElements);
10462    })();
10463</script>
vendor: 1 bytes, line 10463
10463
10464<script>
10465    'use strict';
10466
10467    (function (amHidePrice) {
10468        amHidePrice.activateScripts = function (contentNode) {
10469            // Extract all the script tags from the content.
10470            const tmpScripts = contentNode.getElementsByTagName('script');
10471
10472            if (tmpScripts.length > 0) {
10473                const scripts = [];
10474                for (let i = 0; i < tmpScripts.length; i++) {
10475                    scripts.push(tmpScripts[i]);
10476                }
10477
10478                for (let i = 0; i < scripts.length; i++) {
10479                    let script = document.createElement('script');
10480                    script.innerHTML = scripts[i].innerHTML;
10481                    document.head.appendChild(script);
10482                    scripts[i].parentNode.removeChild(scripts[i]);
10483                }
10484            }
10485
10486            return contentNode;
10487        };
10488
10489        amHidePrice.removeScripts = function (contentNode) {
10490            let scripts = contentNode.getElementsByTagName('script');
10491            for (let i = 0; i < scripts.length; i++) {
10492                scripts[i].parentNode.removeChild(scripts[i]);
10493            }
10494
10495            return contentNode;
10496        };
10497
10498        amHidePrice.insertAfterDomElement = function (parentNode, targetSelector, content) {
10499            const node = parentNode.querySelector(targetSelector);
10500            if (!node || !content) {
10501                return;
10502            }
10503
10504            const contentNode = document.createElement('div');
10505            contentNode.setAttribute("data-id","amHidePriceButton");
10506            contentNode.insertAdjacentHTML('afterbegin', content);
10507
10508            node.after(contentNode);
10509            amHidePrice.activateScripts(contentNode);
10510        };
10511
10512        amHidePrice.removeHidePriceButtons = function (parentNode) {
10513            Object.values(parentNode.querySelectorAll(this.amHidePriceButtonSelector)).forEach(
10514                (amHidePriceButton) => {
10515                    amHidePriceButton.remove();
10516                });
10517        }
10518
10519        amHidePrice.amHidePriceButtonSelector = '[data-id="amHidePriceButton"]';
10520    } (window.amHidePrice = window.amHidePrice || {}));
10521</script>
10521
10522
10523    <section x-cloak x-data="amRecaptchaLoading"
10524             @amcaptcha-loading-start.window="loadingStart" @amcaptcha-loading-stop.window="loadingStop">
10525        <div class="flex flex-row start-0 top-0 justify-center items-center w-full h-full absolute select-none z-10"
10526     style="background: rgba(255,255,255,0.5);"
10527     x-show="isLoading"
10528     x-cloak
10529     x-transition:enter="ease-out duration-200"
10530     x-transition:enter-start="opacity-0"
10531     x-transition:enter-end="opacity-100"
10532     x-transition:leave="ease-in duration-200"
10533     x-transition:leave-start="opacity-100"
10534     x-transition:leave-end="opacity-0">
10535    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
10536    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
1053612.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
10537    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
10538<title>loader</title></svg>
10539</div>
10540    </section>
10541    
10541<script>
10542        function amRecaptchaLoading() {
10543            return {
10544                isLoading: false,
10545
10546                loadingStart() {
10547                    this.isLoading = true;
10548                },
10549
10550                loadingStop() {
10551                    this.isLoading = false;
10552                }
10553            };
10554        }
10555        (() => {
10556            const initFn = () => Alpine.data('amRecaptchaLoading', amRecaptchaLoading);
10557            window.Alpine ? initFn() : window.addEventListener('alpine:init', initFn, {once: true})
10558        })()
10559    </script>
10559
10560    
10560<script>
10561    'use strict';
10562
10563    function initParentContainerProcessor() {
10564        const selectors = {
10565            labelContainer: '.amasty-label-container',
10566            galleryImg: '#gallery img:not(.amasty-label-image)'
10567        }
10568
10569        return {
10570            /**
10571             * @param {AmlabelComponent} label
10572             * @return {void}
10573             */
10574            process: function (label) {
10575                this.moveLabelToParent(label);
10576                this.setParentStyles(label);
10577            },
10578
10579            /**
10580             * @param {AmlabelComponent} label
10581             * @return {void}
10582             */
10583            moveLabelToParent: function (label) {
10584                const newParent = this.getNewParent(label);
10585
10586                if (!newParent) {
10587                    return;
10588                }
10589
10590                const wrapperElement = newParent.querySelector(label.wrapperClass);
10591                label.parent = newParent;
10592
10593                // if same wrapper already exists - move label there
10594                if (wrapperElement && !wrapperElement.isSameNode(label.element)) {
10595                    this.insertLabelByPriority(label, wrapperElement);
10596                } else {
10597                    newParent.prepend(label.element);
10598                }
10599            },
10600
10601            /**
10602             * @param {AmlabelComponent} label
10603             * @return {HTMLElement|null}
10604             */
10605            getNewParent: function (label) {
10606                // move label to container from settings
10607                let newParent = label.element.closest(label.config.path)
10608                    || this.findPreviousNodeExcludingScriptsAndDifferentLabels(label.element)?.querySelector(label.config.path)
10609                    || label.parent.querySelector(label.config.path);
10610
10611                // Try to find default gallery container on product page if none of the config selectors found
10612                if (!newParent && label.config.move !== 1 && label.config.mode === 'prod') {
10613                    newParent = document.querySelector(selectors.galleryImg)?.parentElement;
10614                }
10615
10616                return newParent;
10617            },
10618
10619            /**
10620             * @param {HTMLElement} element
10621             * @return {HTMLElement|null}
10622             */
10623            findPreviousNodeExcludingScriptsAndDifferentLabels: function (element) {
10624                const previousElement = element?.previousElementSibling;
10625                if (!previousElement) {
10626                    return null;
10627                }
10628
10629                if (previousElement?.tagName !== 'SCRIPT'
10630                    && !previousElement?.className?.includes?.('amlabel-position-wrapper')
10631                ) {
10632                    return previousElement;
10633                }
10634
10635                return this.findPreviousNodeExcludingScriptsAndDifferentLabels(previousElement);
10636            },
10637
10638            /**
10639             * @param {AmlabelComponent} label
10640             * @param {HTMLElement} wrapperElement
10641             * @return {void}
10642             */
10643            insertLabelByPriority: function (label, wrapperElement) {
10644                const labelContainers = wrapperElement.querySelectorAll(selectors.labelContainer);
10645                const currentLabelOrder = label.labelContainer.dataset.amlabelOrder;
10646                let insertAfterContainer = null;
10647
10648                // find the label behind which we want to insert current one by priority
10649                labelContainers.forEach(labelContainer => {
10650                    if (labelContainer.dataset.amlabelOrder < currentLabelOrder) {
10651                        insertAfterContainer = labelContainer;
10652                    }
10653                });
10654
10655                insertAfterContainer === null
10656                    ? wrapperElement.prepend(label.labelContainer)
10657                    : insertAfterContainer.after(label.labelContainer);
10658
10659                label.element.remove();
10660                label.element = wrapperElement;
10661            },
10662
10663            /**
10664             * @param {AmlabelComponent} label
10665             * @return {void}
10666             */
10667            setParentStyles: function (label) {
10668                /* required for child position absolute */
10669                !(label.parent.style.position === 'absolute') && (label.parent.style.position = 'relative');
10670                !label.parent.style.width && label.parent.classList.add('w-fit-content');
10671                !label.parent.style.marginLeft && label.parent.classList.add('ml-auto');
10672                !label.parent.style.marginRight && label.parent.classList.add('mr-auto');
10673            },
10674        }
10675    }
10676</script>
vendor: 1 bytes, line 10676
10676
10677<script>
10678    'use strict';
10679
10680    function initLabelItemProcessor() {
10681        /**
10682         * @typedef {Object} AmlabelComponent
10683         *
10684         * @property {HTMLElement} element Label wrapper element
10685         * @property {HTMLElement} parent Element where label should be placed
10686         * @property {boolean} initialized Is label initialized
10687         * @property {string} wrapperClass Dynamic class for label wrapper to place multiple labels properly by position
10688         * @property {HTMLElement} labelContainer Container for label text image and tooltip
10689         * @property {Config} config Label Configuration
10690         * @property {Object} parentContainerProcessor
10691         * @property {Object} labelItemProcessor
10692         */
10693
10694        /**
10695         * @typedef {Object} AmLabelConfig
10696         *
10697         * @property {0|1} alignment Labels Alignment config value (0 - Horizontal| 1 - Vertical)
10698         * @property {number} label Label Id
10699         * @property {number} margin Margin between labels config value
10700         * @property {('cat'|'prod')} mode Label mode
10701         * @property {number} move
10702         * @property {number} order Label order
10703         * @property {string} path The css selector to which label should place
10704         * @property {string} position Label position
10705         * @property {string} product Product Id
10706         * @property {string} redirect_url
10707         * @property {string} size Label size
10708         * @property {{
10709         *     backgroundColor: string,
10710         *     color: string,
10711         *     content: string,
10712         *     status: 1|2|3
10713         * }} tooltip
10714         */
10715
10716        return {
10717            /**
10718             * @param {AmlabelComponent} label
10719             * @return {void}
10720             */
10721            process: function(label) {
10722                this.setLabelSize(label);
10723                this.setLinkProps(label);
10724            },
10725
10726            /**
10727             * @param {AmlabelComponent} label
10728             * @return {void}
10729             */
10730            setLabelSize: function (label) {
10731                if (!label.config.size) {
10732                    return;
10733                }
10734
10735                label.labelContainer.style.width = label.parent.offsetWidth * label.config.size / 100 + 'px';
10736            },
10737
10738            /**
10739             *
10740             * @param {Object} $event
10741             * @param {HTMLElement} tooltipNode
10742             */
10743            placeTooltip: function($event, tooltipNode) {
10744                const labelNode = $event.target;
10745                const labelNodeRect = labelNode.getBoundingClientRect();
10746
10747                tooltipNode.style.bottom = (window.innerHeight - labelNodeRect.top)  + 'px';
10748                tooltipNode.style.left = (labelNodeRect.left + labelNode.offsetWidth / 2 ) + 'px';
10749            },
10750
10751            /**
10752             * @param {AmlabelComponent} label
10753             * @return {void}
10754             */
10755            setLinkProps: function (label) {
10756                !!label.config.redirect_url && label.labelContainer.classList.add('-link', 'cursor-pointer');
10757            },
10758
10759            /**
10760             * @param {Object} $event Click event
10761             * @param {string} redirectUrl
10762             */
10763            openLink: function($event, redirectUrl) {
10764                if (redirectUrl.length === 0) {
10765                    return;
10766                }
10767
10768                $event.preventDefault();
10769                window.open(redirectUrl, '_blank');
10770            }
10771        }
10772    }
10773</script>
10773
10774
10775<script>
10776    (function () {
10777        'use strict';
10778
10779        const observedEvent = 'amlabel-swatch-product-changed';
10780        const selectors = {
10781            swatchOptions: 'div[x-data^=initConfigurable][x-data*=Options]',
10782            addToCartFormOnListing: 'form.product_addtocart_form',
10783            galleryImage: '#gallery img:not(.amasty-label-image)',
10784            labelWrapper: '.amlabel-position-wrapper'
10785        }
10786
10787        /**
10788         * @return {void}
10789         */
10790        const injectLabelObserver = function () {
10791            const swatches = document.querySelectorAll(selectors.swatchOptions);
10792
10793            swatches.forEach(swatch => {
10794                const isListing = !!swatch.closest(selectors.addToCartFormOnListing);
10795                const injectedDispatch = `$dispatch('${observedEvent}', `
10796                    + `{productIndex: productIndex, element: $el, optionConfig: optionConfig, isListing: ${isListing ? 1 : 0}})`;
10797
10798                let mutatedInitAttribute = swatch.getAttribute('x-init');
10799                mutatedInitAttribute += `; $watch('productIndex', (productIndex) => { ${injectedDispatch} });`;
10800                swatch.setAttribute('x-init', mutatedInitAttribute);
10801            });
10802        }
10803
10804        /**
10805         * @param {{
10806         *  productIndex: number,
10807         *  element: HTMLElement,
10808         *  optionConfig: Object,
10809         *  isListing: 0|1
10810         * }} payload
10811         * @return {void}
10812         */
10813        const updateLabel = function ({detail: payload}) {
10814            const {productIndex, element, optionConfig, isListing} = payload;
10815
10816            if (!productIndex) {
10817                return;
10818            }
10819
10820            const reloadUrl = optionConfig.label_reload;
10821            const headers = {
10822                "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
10823            };
10824            const body = new URLSearchParams({
10825                product_ids: productIndex,
10826                in_product_list: isListing
10827            });
10828            const labelContainerSelector = isListing ? optionConfig.label_category : optionConfig.label_product;
10829
10830            fetch(`${reloadUrl}?${body.toString()}`, {headers: headers, method: 'GET'}).then((response) => {
10831                if (response.ok) {
10832                    return response.json();
10833                }
10834            }).then((result) => {
10835                const labelHtml = result.labels && result.labels[productIndex];
10836                let labelContainer = findClosest(element, labelContainerSelector);
10837
10838                // Try to find default gallery container on product page if none of the config selectors found
10839                if (labelContainer === null && isListing === 0) {
10840                    labelContainer = document.querySelector(selectors.galleryImage)?.parentElement;
10841                }
10842
10843                if (!!labelContainer) {
10844                    !!labelHtml ? replaceLabels(labelContainer, labelHtml) : clearLabelWrapper(labelContainer);
10845                }
10846            }).catch((error) => {
10847                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
10848                    [{
10849                        type: 'error',
10850                        text: error
10851                    }],
10852                    5000
10853                );
10854            });
10855        }
10856
10857        /**
10858         * We use approach from hyva.replaceDomElement method to replace labels and init components
10859         *
10860         * @param {HTMLElement} labelContainer
10861         * @param {string} labelHtml
10862         * @return {void}
10863         */
10864        function replaceLabels(labelContainer, labelHtml) {
10865            const parser = new DOMParser();
10866            const doc = parser.parseFromString(labelHtml, 'text/html');
10867            const nodes = doc.querySelectorAll(selectors.labelWrapper);
10868
10869            if (!nodes) {
10870                return;
10871            }
10872
10873            clearLabelWrapper(labelContainer);
10874
10875            // Extract all the script tags from the new content.
10876            // Script tags won't execute when inserted into a dom-element directly,
10877            // therefore we need to inject them to the head of the document.
10878            const tmpScripts = doc.getElementsByTagName('script');
10879
10880            if (tmpScripts.length > 0) {
10881                // Push all script tags into an array
10882                // (to prevent dom manipulation while iterating over dom nodes)
10883                const scripts = [...tmpScripts];
10884
10885                // Iterate over all script tags and duplicate+inject each into the head
10886                scripts.forEach(script => {
10887                    let scriptNode = document.createElement('script');
10888                    scriptNode.innerHTML = script.innerHTML;
10889                    document.head.appendChild(scriptNode);
10890
10891                    // Remove the original (non-executing) node from the page
10892                    script.parentNode.removeChild(script);
10893                });
10894            }
10895
10896            labelContainer.append(...nodes);
10897        }
10898
10899        /**
10900         * @param {HTMLElement} labelContainer
10901         * @return {void}
10902         */
10903        function clearLabelWrapper(labelContainer) {
10904            labelContainer.querySelectorAll(selectors.labelWrapper).forEach(wrapper => wrapper.remove());
10905        }
10906
10907        /**
10908         * @param {HTMLElement} currentElement
10909         * @param {string} selector
10910         * @return {HTMLElement|null}
10911         */
10912        function findClosest(currentElement, selector) {
10913            // We need to limit parent searches to prevent labels from being associated with the wrong product.
10914            const maxDepth = 3;
10915            let counter = 0;
10916            let closest = null;
10917
10918            while (currentElement.parentNode && closest === null && counter < maxDepth) {
10919                ++counter;
10920                currentElement = currentElement.parentNode;
10921                closest = currentElement.querySelector(selector);
10922            }
10923
10924            return closest;
10925        }
10926
10927        injectLabelObserver();
10928        window.addEventListener(observedEvent, updateLabel);
10929    })();
10930</script>
vendor: 1 bytes, line 10930
10930
10931<script>
10932    'use strict';
10933
10934    (function () {
10935        window.amLabels = {
10936            productLabelsUrl: 'amasty_label/ajax/label',
10937            /**
10938             * @param {Array} productIds
10939             * @return {Promise<any>}
10940             */
10941            getLabelsHtml: function (productIds) {
10942                const headers = {
10943                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
10944                };
10945                const body = new URLSearchParams({
10946                    product_ids: productIds,
10947                    in_product_list: true
10948                });
10949
10950                return fetch(BASE_URL + this.productLabelsUrl + '?' + body.toString(), {
10951                    headers: headers,
10952                    method: 'GET'
10953                }).then((response) => {
10954                    if (response.ok) {
10955                        return response.json();
10956                    }
10957                }).then((result) => {
10958                    return Object.values(result.labels);
10959                }).catch((error) => {
10960                    typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
10961                        [{
10962                            type: 'error',
10963                            text: error
10964                        }],
10965                        5000
10966                    );
10967                });
10968            }
10969        };
10970    })();
10971</script>
10971<script>
10972    'use strict';
10973
10974    (function () {
10975        window.initAmRecentlyViewedLabels = window.initAmRecentlyViewedLabels || {
10976            selectors: {
10977                recentlyViewedContainer: '[x-data^=initRecentlyViewedProductsComponent]',
10978                productPhoto: '.product-item-photo'
10979            },
10980            recentlyViewedProductsKey: 'recently_viewed_products',
10981
10982            /**
10983             * @return number[]
10984             */
10985            getProductIds: function () {
10986                const startIndex = '' === '' ? 0 : 1;
10987
10988                return JSON.parse(hyva.getBrowserStorage().getItem(this.recentlyViewedProductsKey) ?? '[]')
10989                    .slice(startIndex)
10990                    .map((item) => item.id);
10991            },
10992
10993            /**
10994             * @return {void}
10995             */
10996            mutationObserver: function () {
10997                const recentlyViewedContainers = document.querySelectorAll(this.selectors.recentlyViewedContainer);
10998
10999                recentlyViewedContainers.forEach(recentlyViewedContainer => {
11000                    const mutationObserver = new MutationObserver((mutationsList, observer) => {
11001                        for(let mutation of mutationsList) {
11002                            if (mutation.type === 'childList') {
11003                                this.addLabels(recentlyViewedContainer, this.getProductIds());
11004                                observer.disconnect();
11005                            }
11006                        }
11007                    });
11008
11009                    mutationObserver.observe(recentlyViewedContainer, {childList: true});
11010                })
11011            },
11012
11013            /**
11014             * @param {HTMLElement} element
11015             * @param {Array} productIds
11016             * @return {void}
11017             */
11018            addLabels: function (element, productIds) {
11019                if (!productIds.length) {
11020                    return;
11021                }
11022
11023                const productPhotos = element.querySelectorAll(this.selectors.productPhoto);
11024
11025                window.amLabels.getLabelsHtml(productIds).then(
11026                    (result) => {
11027                        result.length && productPhotos?.forEach((productPhoto, index) => {
11028                            !!result[index] && this.appendLabel({
11029                                productPhoto: productPhoto,
11030                                labelHtml: result[index],
11031                                productId: productIds[index]
11032                            });
11033                        })
11034                    }
11035                );
11036            },
11037
11038            /**
11039             * @param {{
11040             *  productContainer: Element,
11041             *  labelHtml: string,
11042             *  productId: number,
11043             * }} labelConfig
11044             * @return {void}
11045             */
11046            appendLabel: function (labelConfig) {
11047                const {productPhoto, labelHtml, productId} = labelConfig;
11048                const labelClass = 'am-label-product-id-' + productId;
11049
11050                productPhoto.innerHTML += labelHtml;
11051                productPhoto.classList.add(labelClass);
11052                this.overrideParentLabelStyle(productPhoto);
11053                hyva.replaceDomElement(
11054                    '.' + labelClass,
11055                    productPhoto.outerHTML
11056                );
11057            },
11058
11059            /**
11060             * @param {HTMLElement} productPhoto
11061             * @return {void}
11062             */
11063            overrideParentLabelStyle: function (productPhoto) {
11064                productPhoto.classList.add('!w-auto');
11065            }
11066        };
11067
11068        window.initAmRecentlyViewedLabels.mutationObserver();
11069    })();
11070</script>
vendor: 1 bytes, line 11070
11070
11071<script>
11072    (function () {
11073        'use strict';
11074
11075        const selectors = {
11076            body: '.catalog-product-view',
11077            productItem: 'product-item',
11078            productGalleryImage: '#gallery'
11079        }
11080
11081        window.addEventListener('alpine:init', () => {
11082            Alpine.directive('amintersect', (el, { expression }, { evaluate, cleanup }) => {
11083                const observer = new IntersectionObserver(entries => {
11084                    entries.forEach(entry => {
11085                        if (entry.isIntersecting) {
11086                            evaluate(expression);
11087                            observer.disconnect();
11088                        }
11089                    })
11090                },  { threshold: 0.5 });
11091
11092                observer.observe(getElement());
11093
11094                cleanup(() => {
11095                    observer.disconnect()
11096                });
11097
11098                function getElement() {
11099                    return !!document.querySelector(selectors.body) ? getImageProductBlock(el) : getCategoryProductBlock(el);
11100                }
11101
11102                function getCategoryProductBlock(el) {
11103                    if (el.previousElementSibling === null) {
11104                        return el;
11105                    }
11106
11107                    if (!el.previousElementSibling.classList.contains(selectors.productItem)) {
11108                        return getCategoryProductBlock(el.previousElementSibling);
11109                    }
11110
11111                    return el.previousElementSibling;
11112                }
11113
11114                function getImageProductBlock(el) {
11115                    return el.parentNode.querySelector(selectors.productGalleryImage)?.parentNode ?? el.parentNode;
11116                }
11117            });
11118        });
11119    })();
11120</script>
11120
11121
11122<script>
11123    'use strict';
11124
11125    (() => {
11126        const browserStorage = hyva.getBrowserStorage();
11127        const storageKey = 'mage-banners-cache-storage';
11128        const cacheTimeoutKey = 'mage-banners-cache-timeout';
11129        const storeIdKey = 'mage-banners-storeId';
11130        const cartIdKey = 'mage-banners-cartDataId';
11131        const options = {
11132            cacheTtl: 30000,
11133            sectionLoadUrl: 'https://www.purdys.com/banner/ajax/load/'
11134        };
11135
11136        if (browserStorage && browserStorage.getItem(storageKey) === null) {
11137            browserStorage.setItem(storageKey, "{}");
11138        }
11139
11140        async function initBanners(elements) {
11141            invalidateCacheBySessionTimeOut();
11142
11143            const storageData = JSON.parse(browserStorage.getItem(storageKey));
11144            let items = [];
11145
11146            if (storageData.data) {
11147                items = getFromStorage();
11148            } else {
11149                items = await getFromServer();
11150            }
11151
11152            populateDynamicBlocks(elements, items);
11153        }
11154
11155        // Cache invalidation. Banner cache ttl is 30 sec by default.
11156        function invalidateCacheBySessionTimeOut() {
11157            const cacheEol = new Date(browserStorage.getItem(cacheTimeoutKey))
11158            const dateTo = new Date(Date.now() + options.cacheTtl);
11159            const globalStoreId = hyva.getCookie('store') || 'default';
11160            const mageCacheStorage = JSON.parse(browserStorage.getItem('mage-cache-storage'));
11161            let cartDataId = null;
11162
11163            if (browserStorage.getItem(storeIdKey) === null) {
11164                browserStorage.setItem(storeIdKey, globalStoreId);
11165            }
11166
11167            if (mageCacheStorage !== null &&
11168                mageCacheStorage.hasOwnProperty('cart')) {
11169                cartDataId = mageCacheStorage.cart['data_id'];
11170            }
11171
11172            if (cacheEol < new Date() ||
11173                browserStorage.getItem(storeIdKey) !== globalStoreId ||
11174                Number(browserStorage.getItem(cartIdKey)) !== cartDataId)
11175            {
11176                browserStorage.setItem(storageKey, "{}");
11177                browserStorage.setItem(cacheTimeoutKey, dateTo);
11178                browserStorage.setItem(storeIdKey, globalStoreId);
11179
11180                if (cartDataId) {
11181                    browserStorage.setItem(cartIdKey, cartDataId);
11182                }
11183            }
11184        }
11185
11186        async function getFromServer() {
11187            try {
11188                const url = new URL(options.sectionLoadUrl);
11189                url.searchParams.append('requesting_page_url', url.origin);
11190                url.searchParams.append('_', Date.now());
11191
11192                const response = await fetch(url.href, {
11193                    headers: {
11194                        'Content-Type': 'application/json',
11195                        'X-Requested-With': 'XMLHttpRequest'
11196                    }
11197                });
11198                const storageData = await response.json();
11199
11200                browserStorage.setItem(storageKey, JSON.stringify(storageData));
11201
11202                if (storageData.data && storageData.data.items) {
11203                    return storageData.data.items.fixed ? storageData.data.items.fixed : [];
11204                }
11205            } catch (error) {
11206                console.warn(error);
11207
11208                return [];
11209            }
11210        }
11211
11212        function getFromStorage() {
11213            const storageData = JSON.parse(browserStorage.getItem(storageKey));
11214            if (storageData.data && storageData.data.items) {
11215                return storageData.data.items.fixed || [];
11216            }
11217        }
11218
11219        function populateDynamicBlocks(elements, items) {
11220            if (!items || items.length === 0) {
11221                console.log(`No\u0020banners\u0020found`);
11222
11223                return;
11224            }
11225
11226            for (const element of elements) {
11227                // Filter IDs by those allowed for current customer segment
11228                const ids = element.getAttribute('data-ids').split(',').filter((id) => items.hasOwnProperty(id));
11229                const config = {
11230                    type: element.getAttribute('data-rotate'),
11231                    dynamicBlockId: element.getAttribute('data-banner-id'),
11232                };
11233
11234                getByType(config, element, items, ids);
11235            }
11236        }
11237
11238        function getByType(config = null, element, items, ids) {
11239            if (!config) return;
11240
11241            if (config.type === 'random') {
11242                ids = [ids[Math.floor(Math.random() * ids.length)]];
11243            }
11244
11245            if (config.type === 'series' || config.type === 'shuffle') {
11246                ids = [getNextInOrder(config, ids)];
11247            }
11248
11249            for (const id of ids) {
11250                if (items[id]) {
11251                    element.insertAdjacentHTML('beforeend', items[id].content);
11252                }
11253            }
11254        }
11255
11256        function getNextInOrder(config, ids) {
11257            const dynamicBlockId = config.dynamicBlockId;
11258            const localStorageKey = 'dynamic-block-banner-rotator';
11259            let localStorageData = JSON.parse(localStorage.getItem(localStorageKey)) || {};
11260            let nextId;
11261
11262            if (localStorageData[dynamicBlockId] && localStorageData[dynamicBlockId].length > 0) {
11263                nextId = localStorageData[dynamicBlockId].shift(0);
11264            } else {
11265                if (config.type === 'shuffle') {
11266                    ids.sort(() => Math.random() - 0.5);
11267                }
11268                nextId = ids.shift(0);
11269                localStorageData[dynamicBlockId] = ids;
11270            }
11271
11272            localStorage.setItem(
11273                localStorageKey,
11274                JSON.stringify(localStorageData)
11275            );
11276
11277            return nextId;
11278        }
11279
11280        const elements = document.querySelectorAll('[data-banner-id][data-ids]');
11281        if (elements.length > 0) {
11282            initBanners(elements);
11283        }
11284    })();
11285</script>
vendor: 1 bytes, line 11285
11285
11286<script>
11287    window.setAjaxCart = (recursive = true, parentSelector = null) => {
11288        const parent = parentSelector ? document.querySelector(parentSelector) : document;
11289
11290        if (!parent) {
11291            console.warn('No parent element found for Ajax Cart');
11292            return;
11293        }
11294
11295        const forms = parent.querySelectorAll('.product_addtocart_form, #product_addtocart_form, [data-role="tocart-form"]:not(.product_addtocart_form)');
11296
11297        forms.forEach(form => {
11298            form.addEventListener('submit', async (e) => {
11299                e.preventDefault();
11300
11301                const formData = new URLSearchParams(new FormData(form));
11302
11303                // Fix FPC form key issue: replace cached form key with fresh one
11304                if (typeof hyva !== 'undefined' && hyva.getFormKey) {
11305                    formData.set('form_key', hyva.getFormKey());
11306                } else if (window.checkoutConfig && window.checkoutConfig.formKey) {
11307                    formData.set('form_key', window.checkoutConfig.formKey);
11308                }
11309
11310                const isButtonInsideForm = !!form.querySelector('button');
11311                const button = isButtonInsideForm ?
11312                    form.querySelector('button[type="submit"], button') :
11313                    document.getElementById('product-addtocart-button');
11314                const loader = document.createElement('div');
11315
11316                loader.className = 'absolute inset-0 flex justify-center items-center loader';
11317                loader.innerHTML = `
11318<div x-data="{ isLoading: true }" class="w-full h-full absolute top-0 left-0">
11319    <div class="flex flex-row start-0 top-0 justify-center items-center w-full h-full absolute select-none z-10"
11320     style="background: rgba(255,255,255,0.5);"
11321     x-show="isLoading"
11322     x-cloak
11323     x-transition:enter="ease-out duration-200"
11324     x-transition:enter-start="opacity-0"
11325     x-transition:enter-end="opacity-100"
11326     x-transition:leave="ease-in duration-200"
11327     x-transition:leave-start="opacity-100"
11328     x-transition:leave-end="opacity-0">
11329    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
11330    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
1133012.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
11331    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
11332<title>loader</title></svg>
11333</div>
11334</div>`;
11335
11336                if (isButtonInsideForm) {
11337                    form.prepend(loader);
11338                    form.classList.add('relative');
11339                } else {
11340                    button.prepend(loader);
11341                    button.classList.add('relative')
11342                }
11343
11344                button.disabled = true;
11345
11346                try {
11347                    const response = await fetch(e.currentTarget.action, {
11348                        method: 'POST',
11349                        body: formData,
11350                        headers: {
11351                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
11352                            'X-Requested-With': 'XMLHttpRequest'
11353                        }
11354                    });
11355
11356                    if (!response.ok) {
11357                        return form.submit();
11358                    }
11359
11360                    if (response.redirected) {
11361                        return window.location.href = response.url;
11362                    }
11363
11364                    const data = await response.json();
11365
11366                    if (data.backUrl) {
11367                        return window.location.href = data.backUrl;
11368                    }
11369
11370                    if (data?.message && data?.success) {
11371                        setMessage({
11372                            text: data?.message,
11373                            type: data?.success ? 'success' : 'error'
11374                        });
11375                    } else if (data?.error && !data?.success) {
11376                        setMessage({
11377                            text: data?.error,
11378                            type: 'error'
11379                        });
11380                    }
11381
11382                    if (recursive) {
11383                        window.dispatchEvent(new CustomEvent('product-addtocart-success'));
11384                    }
11385
11386                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
11387                    if (data.checkoutConfig && data.checkoutConfig.totalsData) {
11388                        window.dispatchEvent(new CustomEvent('update-totals', {
11389                            detail: { data: data.checkoutConfig.totalsData }
11390                        }));
11391                    }
11392                } catch (err) {
11393                    console.warn(err);
11394                    window.dispatchEvent(new CustomEvent('product-addtocart-error'));
11395
11396                    setMessage({
11397                        text: 'There\u0020was\u0020a\u0020problem\u0020adding\u0020your\u0020item\u0020to\u0020the\u0020cart.',
11398                        type: 'error'
11399                    });
11400                } finally {
11401                    try {
11402                        var messages = hyva.getCookie('mage-messages');
11403                        messages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : [];
11404                        document.cookie = 'mage-messages=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
11405
11406                    } catch (error) {
11407                        console.warn('Error parsing Cookie Messages:', error);
11408                        return;
11409                    }
11410
11411                    setTimeout(() => {
11412                        loader.remove();
11413                        button.disabled = false;
11414                    }, 0);
11415                }
11416            });
11417        });
11418    }
11419
11420    /**
11421     * Set Message
11422     */
11423    function setMessage(message) {
11424        typeof window.dispatchMessages !== "undefined" &&
11425            window.dispatchMessages([message], 5000);
11426    }
11427
11428    /** Init on pageload */
11429    window.setAjaxCart();
11430</script>
11430
11431
11432<script>
11433    'use strict';
11434    (() => {
11435        function _calculateStrength({elementID, valid}) {
11436            const password = document.getElementById(elementID),
11437                emailElm = document.getElementById('email_address');
11438            let displayScore;
11439            // Display score is based on combination of whether password is empty, valid, and zxcvbn strength
11440            if (!password || !password.value) {
11441                displayScore = 0;
11442            } else {
11443                // We should only perform this check in case there is an email field on screen
11444                if (emailElm && password.value && emailElm.value &&
11445                    password.value.toLowerCase() === emailElm.value.toLowerCase()) {
11446                    displayScore = 1;
11447                } else {
11448                    const zxcvbnScore = zxcvbn(password.value).score;
11449                    displayScore = valid && zxcvbnScore > 0 ? zxcvbnScore : 1;
11450                }
11451            }
11452
11453            _displayStrength(displayScore);
11454        }
11455
11456        function _displayStrength(displayScore) {
11457            let strengthLabel = '',
11458                className;
11459
11460            switch (displayScore) {
11461                case 0:
11462                    strengthLabel = "No\u0020Password";
11463                    className = 'password-none';
11464                    break;
11465
11466                case 1:
11467                    strengthLabel = "Weak";
11468                    className = 'password-weak';
11469                    break;
11470
11471                case 2:
11472                    strengthLabel = "Medium";
11473                    className = 'password-medium';
11474                    break;
11475
11476                case 3:
11477                    strengthLabel = "Strong";
11478                    className = 'password-strong';
11479                    break;
11480
11481                case 4:
11482                    strengthLabel = "Very\u0020Strong";
11483                    className = 'password-very-strong';
11484                    break;
11485            }
11486            const meterElm = document.getElementById('password-strength-meter-container'),
11487                meterLabelElm = document.getElementById('password-strength-meter-label');
11488            meterElm.className = '';
11489            meterElm.classList.add(className);
11490            meterLabelElm.textContent = strengthLabel;
11491        }
11492
11493        let loading = false;
11494        const callbacks = [];
11495
11496        function loadZxcvbn(cb) {
11497            callbacks.push(cb);
11498            if (loading) return;
11499            loading = true;
11500
11501            const script = document.createElement('script');
11502            script.type = 'text/javascript';
11503            script.src = 'https\u003A\u002F\u002Fwww.purdys.com\u002Fstatic\u002Fversion1790083580\u002Ffrontend\u002FPurdys2\u002Fhyva\u002Fen_US\u002Fjs\u002Fzxcvbn.js';
11504            script.async = true;
11505            script.onload = () => callbacks.forEach(cb => cb());
11506            document.head.appendChild(script);
11507        }
11508
11509        window.addEventListener('password-validate', function (evt) {
11510            const meterElm = document.getElementById('password-strength-meter-container'),
11511                meterLabelElm = document.getElementById('password-strength-meter-label');
11512            if (meterElm && meterLabelElm) {
11513                if (evt.detail && evt.detail.elementID) {
11514                    const cb = () => _calculateStrength(evt.detail);
11515                    window.zxcvbn ? cb() : loadZxcvbn(cb)
11516                }
11517            }
11518        });
11519
11520
11521        document.addEventListener('DOMContentLoaded', () => {
11522            hyva && hyva.formValidation && hyva.formValidation.addRule('password-strength', function(value, options, field, context) {
11523                let counter = 0;
11524                const minCharacterSets = options.minCharacterSets !== undefined ?  options.minCharacterSets : 1;
11525                if (value.match(/\d+/)) {
11526                    counter++;
11527                }
11528
11529                if (value.match(/[a-z]+/)) {
11530                    counter++;
11531                }
11532
11533                if (value.match(/[A-Z]+/)) {
11534                    counter++;
11535                }
11536
11537                if (value.match(/[^a-zA-Z0-9]+/)) {
11538                    counter++;
11539                }
11540
11541                queueMicrotask(() => {
11542                    window.dispatchEvent(new CustomEvent('password-validate', { detail: {
11543                            elementID: field.element.id || 'password',
11544                            valid: field.state.valid
11545                        }}));
11546                });
11547
11548                if (counter < minCharacterSets) {
11549                    const missing = minCharacterSets - counter;
11550                    return hyva.str('The\u0020password\u0020must\u0020include\u0020at\u0020least\u0020\u00251\u0020or\u0020more\u0020of\u003A\u0020uppercase\u0020\u0028A\u002DZ\u0029,\u0020lowercase\u0020\u0028a\u002Dz\u0029,\u0020number\u0020and\u0020symbol.', missing);
11551                }
11552                return true;
11553            });
11554        })
11555    })();
11556
11557</script>
vendor: 1 bytes, line 11557
11557
11558<script type="text/javascript">
11559/**
11560 * Mobile Video Switcher for PageBuilder Banner Videos
11561 * Properly integrates with Jarallax video system
11562 */
11563(function() {
11564    'use strict';
11565
11566    // Store original video sources to prevent data loss
11567    const originalVideoSources = new Map();
11568
11569    /**
11570     * Switch video source based on screen size
11571     */
11572    function switchVideoSource() {
11573        const videoElements = document.querySelectorAll('[data-background-type="video"][data-video-src-mobile]');
11574        
11575        videoElements.forEach(function(element) {
11576            const mobileVideoSrc = element.getAttribute('data-video-src-mobile');
11577            const currentVideoSrc = element.getAttribute('data-video-src');
11578            
11579            // Store original video source if not already stored
11580            if (!originalVideoSources.has(element)) {
11581                originalVideoSources.set(element, currentVideoSrc);
11582            }
11583            
11584            const originalVideoSrc = originalVideoSources.get(element);
11585            
11586            // Validate video sources
11587            const targetVideoSrc = window.innerWidth <= 768 ? mobileVideoSrc : originalVideoSrc;
11588            if (!targetVideoSrc) {
11589                return;
11590            }
11591            
11592            if (window.innerWidth <= 768) {
11593                // Mobile: use mobile video source
11594                if (currentVideoSrc !== mobileVideoSrc) {
11595                    // Update the data-video-src attribute
11596                    element.setAttribute('data-video-src', mobileVideoSrc);
11597                    
11598                    // Reinitialize Jarallax
11599                    reinitializeJarallax(element, mobileVideoSrc);
11600                }
11601            } else {
11602                // Desktop: use original video source
11603                if (currentVideoSrc !== originalVideoSrc) {
11604                    // Update the data-video-src attribute
11605                    element.setAttribute('data-video-src', originalVideoSrc);
11606                    
11607                    // Reinitialize Jarallax
11608                    reinitializeJarallax(element, originalVideoSrc);
11609                }
11610            }
11611        });
11612    }
11613
11614    /**
11615     * Properly reinitialize Jarallax with new video source
11616     */
11617    function reinitializeJarallax(element, videoSrc) {
11618        // Destroy existing Jarallax instance if it exists
11619        if (element.jarallax && typeof element.jarallax.destroy === 'function') {
11620            element.jarallax.destroy();
11621        }
11622        
11623        // Remove any existing jarallax-container elements
11624        const existingContainers = element.querySelectorAll('[id^="jarallax-container-"]');
11625        existingContainers.forEach(container => {
11626            container.remove();
11627        });
11628        
11629        // Wait a bit for cleanup to complete
11630        setTimeout(() => {
11631            if (typeof window.jarallax !== 'undefined') {
11632                // Get all the original attributes for proper reinitialization
11633                const videoLoop = element.getAttribute('data-video-loop') === 'true';
11634                const videoPlayOnlyVisible = element.getAttribute('data-video-play-only-visible') === 'true';
11635                const videoLazyLoad = element.getAttribute('data-video-lazy-load') === 'true';
11636                const videoFallbackSrc = element.getAttribute('data-video-fallback-src') || '';
11637                
11638                // Ensure the element has the proper data attributes for video
11639                element.setAttribute('data-background-type', 'video');
11640                element.setAttribute('data-video-src', videoSrc);
11641                
11642                // Reinitialize Jarallax with the new video source
11643                window.jarallax(element, {
11644                    videoSrc: videoSrc,
11645                    videoLoop: videoLoop,
11646                    videoPlayOnlyVisible: videoPlayOnlyVisible,
11647                    videoLazyLoading: videoLazyLoad,
11648                    imgSrc: videoFallbackSrc
11649                });
11650                
11651                // Check if video was created successfully
11652                setTimeout(() => {
11653                    const videoContainer = element.querySelector('[id^="jarallax-container-"]');
11654                    const videoElement = videoContainer ? videoContainer.querySelector('video') : null;
11655                    
11656                    if (videoContainer && !videoElement) {
11657                        createManualVideoElement(videoContainer, videoSrc);
11658                    } else if (videoElement) {
11659                        fixVideoPositioning(videoElement);
11660                        ensureVideoPlays(videoElement);
11661                    }
11662                }, 500);
11663            }
11664        }, 200);
11665    }
11666
11667    /**
11668     * Create a manual video element if Jarallax fails to create one
11669     */
11670    function createManualVideoElement(container, videoSrc) {
11671        const video = document.createElement('video');
11672        video.setAttribute('loop', '');
11673        video.setAttribute('playsinline', '');
11674        video.setAttribute('webkit-playsinline', '');
11675        video.setAttribute('autoplay', '');
11676        video.setAttribute('muted', '');
11677        video.setAttribute('id', 'VideoWorker-' + Date.now());
11678        
11679        // Use absolute positioning to stay in place relative to container
11680        video.style.cssText = 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; max-width: none; max-height: none; pointer-events: none; transform-style: preserve-3d; backface-visibility: hidden; will-change: transform, opacity; z-index: -1; object-fit: cover;';
11681        
11682        const source = document.createElement('source');
11683        source.setAttribute('src', videoSrc);
11684        source.setAttribute('type', 'video/mp4');
11685        video.appendChild(source);
11686        
11687        container.appendChild(video);
11688        
11689        // Ensure the video plays
11690        ensureVideoPlays(video);
11691    }
11692
11693    /**
11694     * Fix video positioning to prevent scroll movement
11695     */
11696    function fixVideoPositioning(videoElement) {
11697        // Check current position
11698        const currentPosition = videoElement.style.position;
11699        
11700        // If position is fixed, change to absolute
11701        if (currentPosition === 'fixed') {
11702            videoElement.style.position = 'absolute';
11703            videoElement.style.top = '0';
11704            videoElement.style.left = '0';
11705            videoElement.style.right = 'auto';
11706            videoElement.style.bottom = 'auto';
11707        }
11708        
11709        // Ensure proper sizing and object-fit
11710        videoElement.style.width = '100%';
11711        videoElement.style.height = '100%';
11712        videoElement.style.objectFit = 'cover';
11713        videoElement.style.objectPosition = 'center';
11714    }
11715
11716    /**
11717     * Ensure video plays properly
11718     */
11719    function ensureVideoPlays(videoElement) {
11720        // Set video properties
11721        videoElement.muted = true;
11722        videoElement.loop = true;
11723        videoElement.playsInline = true;
11724        videoElement.autoplay = true;
11725        
11726        // Try to play the video
11727        const playPromise = videoElement.play();
11728        
11729        if (playPromise !== undefined) {
11730            playPromise.catch(() => {
11731                // Try again after a short delay
11732                setTimeout(() => {
11733                    videoElement.play().catch(() => {});
11734                }, 1000);
11735            });
11736        }
11737    }
11738
11739    /**
11740     * Wait for Jarallax to be ready and then switch videos
11741     */
11742    function waitForJarallaxAndSwitch() {
11743        if (typeof window.jarallax !== 'undefined') {
11744            switchVideoSource();
11745        } else {
11746            setTimeout(waitForJarallaxAndSwitch, 500);
11747        }
11748    }
11749
11750    // Initialize on DOM ready
11751    if (document.readyState === 'loading') {
11752        document.addEventListener('DOMContentLoaded', function() {
11753            setTimeout(waitForJarallaxAndSwitch, 1000);
11754        });
11755    } else {
11756        // DOM is already ready
11757        setTimeout(waitForJarallaxAndSwitch, 1000);
11758    }
11759
11760    // Handle window resize
11761    let resizeTimeout;
11762    window.addEventListener('resize', function() {
11763        clearTimeout(resizeTimeout);
11764        resizeTimeout = setTimeout(function() {
11765            waitForJarallaxAndSwitch();
11766        }, 250);
11767    });
11768})();
11769</script>
11769 
11770
11771<script>
11772    window.addEventListener('load', function () {
11773        magentoStorefrontEvents.context.setPage({
11774            pageType: "MyAccount"
11775        });
11776        magentoStorefrontEvents.context.setContext("pageExtended", {
11777            action: "login"
11778        });
11779        magentoStorefrontEvents.context.setShoppingCart({
11780            id: 0        });
11781
11782        const pageAction = magentoStorefrontEvents.context.getContext("pageExtended").action;
11783
11784        if (pageAction === "logout") {
11785            handleLogoutActions();
11786        } else if (pageAction === "login") {
11787            handleLoginActions();
11788        }
11789
11790        function handleLoginActions() {
11791            document.getElementById("customer-login-form").addEventListener("submit", function () {
11792                const email = document.getElementById("email");
11793                if (email && email.value) {
11794                    magentoStorefrontEvents.context.setAccount({ emailAddress: email.value });
11795                    magentoStorefrontEvents.publish.signIn();
11796                }
11797            });
11798        }
11799
11800        function handleLogoutActions() {
11801            let accountContext = magentoStorefrontEvents.context.getAccount() || {};
11802
11803            if (Object.entries(accountContext).length === 0) {
11804                magentoStorefrontEvents.publish.signOut();
11805                magentoStorefrontEvents.context.setShopper({ shopperId: "guest" });
11806            }
11807        }
11808    });
11809</script>
11809
11810<div x-cloak x-data="{...initAmBanners()}" x-init="initBanners()">
11811    <div class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50"
11812    style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.7);"
11813    x-show="isLoading"
11814    x-cloak
11815    x-transition:enter="ease-out duration-200"
11816    x-transition:enter-start="opacity-0"
11817    x-transition:enter-end="opacity-100"
11818    x-transition:leave="ease-in duration-200"
11819    x-transition:leave-start="opacity-100"
11820    x-transition:leave-end="opacity-0">
11821    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
11822    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
1182212.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
11823    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
11824<title>loader</title></svg>
11825</div></div>
11826<script>
11827    'use strict';
11828
11829    function initAmBanners() {
11830        return {
11831            options: {
11832                sections: [],
11833                content: [],
11834                banners: [],
11835                injectorSectionId: null,
11836                injectorParams: {}
11837            },
11838            isLoading: true,
11839            injectorResolver: {},
11840
11841            initBanners: function () {
11842                this.options = {"sections":{"14":[190,193]},"content":{"190":"\n<div data-banner-id=\"190\">\n    <a href='https:\/\/www.purdys.com\/halloween-gift-ideas'><img src='https:\/\/www.purdys.com\/media\/amasty\/ampromobanners\/banner_190_Halloween-Coffin-Gift-Box-Category-Promo.jpg' alt='' \/><\/a>    <\/div>\n","193":"\n<div data-banner-id=\"193\">\n    <a href='https:\/\/www.purdys.com\/gifts\/diwali'><img src='https:\/\/www.purdys.com\/media\/amasty\/ampromobanners\/banner_193_Diwali-Category-Promo.jpg' alt='' \/><\/a>    <\/div>\n"},"injectorParams":{"containerSelector":".products-grid .product-items:not(.amasty-banner-items)","itemSelector":".products-grid .product-items:not(.amasty-banner-items) .product-item","banners":{"190":{"afterProductRow":1,"positionInProductRow":0,"afterProductNum":4,"width":1,"priority":0,"id":190},"193":{"afterProductRow":1,"positionInProductRow":0,"afterProductNum":4,"width":1,"priority":0,"id":193}}},"banners":[],"injectorSectionId":14};
11843                this.injectorResolver = amBannerInjectorResolver?.();
11844
11845                this.insertBanners();
11846                this.isLoading = false;
11847            },
11848
11849            insertBanners: function () {
11850                document.querySelectorAll('[data-role="amasty-banner-container"]').forEach((container) => {
11851                    const sectionId = container.getAttribute('data-position');
11852
11853                    if (sectionId) {
11854                        this.loadBannerBySection(sectionId, container);
11855                    } else {
11856                        this.loadBannerByBannerId(container);
11857                    }
11858                });
11859            },
11860
11861            getBanners: function (bannerId) {
11862                if (this.options.banners.indexOf(bannerId) === -1) {
11863                    return [];
11864                }
11865                const insertedBanner = this.banners.find((element) => {
11866                    return element === bannerId;
11867                });
11868
11869                return content[insertedBanner];
11870            },
11871
11872            getSectionBanners: function (section) {
11873                if (!(section in this.options.sections)) {
11874                    return [];
11875                }
11876
11877                return this.options.sections[section].map((id) => {
11878                    return this.options.content[id];
11879                });
11880            },
11881
11882            loadBannerBySection: function (sectionId, container) {
11883                container.innerHTML = this.getSectionBanners(sectionId).join('');
11884                this.injectorResolver?.resolve(sectionId, this.options.injectorParams);
11885                this.updateSection(`[data-role="amasty-banner-container"][data-position="${sectionId}"]`, container);
11886            },
11887
11888            loadBannerByBannerId: function (container) {
11889                const bannerId = container.getAttribute('data-bannerid');
11890                container.innerHTML = (this.getBanners(bannerId));
11891                this.updateSection(`[data-role="amasty-banner-container"][data-bannerid="${bannerId}"]`, container);
11892            },
11893
11894            updateSection: function(containerSelector, container) {
11895                hyva.replaceDomElement(
11896                    containerSelector,
11897                    container.innerHTML
11898                );
11899            }
11900        }
11901    }
11902</script>
11902
11903
11904<script data-source="Purdys_CustomWeltPixelEvents / products-click-tracking.phtml">
11905	(() => {
11906		// [1] Get the utilities
11907		const utils = window.customWeltPixelEventsUtils;
11908
11909		if (!utils) {
11910			console.error('Purdys_CustomWeltPixelEvents / products-click-tracking.phtml: customWeltPixelEventsUtils is not defined');
11911			return;
11912		}
11913
11914		// [2] Wait for DOM to be fully loaded before setting up tracking
11915		utils.dom.onDomContentLoaded(() => {
11916			utils.dom.addMutationObserver(trackProductClick);
11917		})
11918
11919		/**
11920		 * Track the product click event
11921		 *
11922		 * @returns {void}
11923		 */
11924		function trackProductClick() {
11925			// Find all product links - try multiple selectors to catch different product link patterns
11926			const productLinks = document.querySelectorAll('a.product, .product-item a, .product-item-info a, [data-product-id]');
11927
11928			if (!productLinks.length) {
11929				// console.warn('Purdys_CustomWeltPixelEvents / products-click-tracking.phtml: No product links found to track select_item event');
11930				return;
11931			}
11932
11933			// Add click event listeners to each product link
11934			productLinks.forEach((link, index) => {
11935				// Skip if already has click listener to prevent duplicates
11936				if (link.hasAttribute('data-weltpixel-tracked')) {
11937					return;
11938				}
11939
11940				link.addEventListener('click', () => {
11941					// Fire the select_item event
11942					fireSelectItemEvent(link, index + 1);
11943				});
11944
11945				// Mark as tracked to prevent duplicate listeners
11946				link.setAttribute('data-weltpixel-tracked', 'true');
11947			});
11948		}
11949
11950		/**
11951		 * Get the product data and fire the select_item event
11952		 *
11953		 * @param {Element} productLink - The clicked product link element
11954		 * @param {number} index - The position of the product in the list
11955		 */
11956		async function fireSelectItemEvent(productLink, index) {
11957			// Get the product ID from the form
11958			const itemId = productLink?.closest('form')?.querySelector('input[name="product"]')?.value;
11959
11960			// If no product ID found, return
11961			if (!itemId) {
11962				// console.warn('Purdys_CustomWeltPixelEvents / products-click-tracking.phtml: No product ID found to track select_item event');
11963				return;
11964			}
11965
11966			// Get the product data
11967			const productData = await getProductData(Number(itemId));
11968
11969			// Enhance the product data
11970			const enhancedProductData = enchanceData(productData, productLink);
11971
11972			// Fire the select_item event
11973			window.dataLayer.push({
11974				event: 'select_item',
11975				ecommerce: {
11976					items: [enhancedProductData]
11977				}
11978			});
11979		}
11980
11981		/**
11982		 * Get the product data via AJAX call to PHP helper
11983		 *
11984		 * @param {string} productId - Product ID/SKU
11985		 * @returns {Promise<Object>} Product data
11986		 */
11987		async function getProductData(productId) {
11988			// SECURITY: Use GET request with query parameters (matches CSRF protection)
11989			// Use absolute URL to prevent issues on PLPs where relative URLs get resolved incorrectly
11990			const url = `/customweltpixelevents/data/products?productsIds=${productId}`;
11991			const response = await fetch(url, {
11992				method: 'GET',
11993				headers: {
11994					'X-Requested-With': 'XMLHttpRequest'
11995				}
11996			});
11997
11998			if (!response.ok) {
11999				console.error('Failed to fetch product data:', response.status, response.statusText);
12000				return {};
12001			}
12002
12003			const data = await response.json();
12004
12005			return data.products[productId] || {};
12006		}
12007
12008		/**
12009		 * Enhance the product data
12010		 *
12011		 * @param {Object} productData - Product data
12012		 * @returns {Object} Enhanced product data
12013		 */
12014		function enchanceData(productData, productLink) {
12015			// Enhance the index
12016			productData.index = getIndex(productLink);
12017
12018			// Item list name
12019			productData.item_list_name = productData.item_list_name ? productData.item_list_name : getItemListName(productLink, productData);
12020
12021			// Item list id
12022			const itemListIds = {
12023				'Seasonal Collections': 'home_page_product_sliders',
12024				'Shop Bestsellers': 'home_page_product_sliders',
12025				'Recommended Products': 'related_products',
12026				'Search Result': 'search_result'
12027			};
12028
12029			if (productData.item_list_id) {
12030				productData.item_list_id = productData.item_list_id;
12031			} else if (productData.item_list_name && itemListIds[productData.item_list_name]) {
12032				productData.item_list_id = itemListIds[productData.item_list_name];
12033			} else if (productData.item_list_name) {
12034				productData.item_list_id = productData.item_list_name.toLowerCase().replace(/ /g, '_').replace(/,/g, '');
12035			} else {
12036				productData.item_list_id = 'N/A';
12037			}
12038
12039			return productData;
12040		}
12041
12042		/**
12043		 * Get the index of the product
12044		 *
12045		 * @param {Element} productLink - The clicked product link element
12046		 * @returns {number|null} The index of the product
12047		 */
12048		function getIndex(productLink) {
12049			// [1] Get the index from the aria-label (Home Page & PDPs Product Sliders)
12050			const indexFromAriaLabel = productLink.closest('.swiper-slide')?.getAttribute('aria-label')?.split('/')[0];
12051
12052			if (indexFromAriaLabel) {
12053				return parseInt(indexFromAriaLabel);
12054			}
12055
12056			// [2] Get the index from the closest form (PLPs, Category Pages, Search Results)
12057			const closestForm = productLink.closest('form');
12058			if (closestForm) {
12059				const productForms = [...closestForm.parentElement.querySelectorAll('form')];
12060				const formIndex = productForms.indexOf(closestForm);
12061				if (formIndex !== -1) {
12062					return formIndex + 1;
12063				}
12064			}
12065
12066			return "N/A";
12067		}
12068
12069		function getItemListName(productLink, productData) {
12070			// [1] Get the item list name from the header (Ecommerce Home Page & PDPs Product Sliders)
12071			const productListContainer = productLink.closest('[x-data*="initFeaturedProducts"], [x-data*="initProductSlider"]');
12072			const itemListName = productListContainer?.querySelector('h1, h2, h3')?.innerText?.trim();
12073
12074			const itemListNames = {
12075				'Seasonal Collections': `Home Page ${itemListName}`,
12076				'Shop Bestsellers': `Home Page ${itemListName}`,
12077				'Recommended Products': getCurrentProductName() ? `Related Products From ${getCurrentProductName()}` : 'Related Products',
12078			};
12079
12080			if (itemListName) {
12081				return itemListNames[itemListName] || itemListName;
12082			}
12083
12084			// [2] Get the item list name from the header (GnF Home Page)
12085			const gnfProductListContainer = productLink.closest('.selection-container');
12086			const gnfItemListName = gnfProductListContainer?.querySelector('h1, h2, h3')?.innerText?.trim();
12087
12088			if (gnfItemListName) {
12089				return gnfItemListName;
12090			}
12091
12092			// [2] Get the item list name based on the page type (PLPs, Category Pages, Search Results)
12093			const pageTitle = document.querySelector('h1.page-title')?.innerText?.trim();
12094
12095			if (typeof pageTitle === 'string' && pageTitle.includes('Search results')) {
12096				return 'Search Result';
12097			}
12098
12099			return pageTitle || null;
12100		}
12101
12102
12103		// Get current product name for PDP context
12104		function getCurrentProductName() {
12105			// Try to get product name from sticky cart (most reliable on PDP)
12106			const stickyProductName = document.querySelector('.sticky-cart .font-bold.body-2')?.innerText?.trim();
12107			if (stickyProductName) {
12108				return stickyProductName;
12109			}
12110
12111			// Fallback: try to get from page title or other product name elements
12112			const pageTitle = document.querySelector('h1.page-title')?.innerText?.trim();
12113			if (pageTitle && !pageTitle.includes('Search results')) {
12114				return pageTitle;
12115			}
12116
12117			// Fallback: try to get from product info section
12118			const productInfoName = document.querySelector('#custom-product-info h1, #custom-product-info .product-name')?.innerText?.trim();
12119			if (productInfoName) {
12120				return productInfoName;
12121			}
12122
12123			return null;
12124		};
12125	})();
12126</script>
vendor: 1 bytes, line 12126
12126
12127<script type="text/json" id="default-section-data">
12128    {"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"requisition":[],"cart":[],"directory-data":{"AU":{"name":"Australia","regions":{"605":{"code":"ACT","name":"Australian Capital Territory"},"606":{"code":"NSW","name":"New South Wales"},"612":{"code":"NT","name":"Northern Territory"},"608":{"code":"QLD","name":"Queensland"},"609":{"code":"SA","name":"South Australia"},"610":{"code":"TAS","name":"Tasmania"},"607":{"code":"VIC","name":"Victoria"},"611":{"code":"WA","name":"Western Australia"}}},"CA":{"name":"Canada","regions":{"66":{"code":"AB","name":"Alberta"},"67":{"code":"BC","name":"British Columbia"},"68":{"code":"MB","name":"Manitoba"},"70":{"code":"NB","name":"New Brunswick"},"69":{"code":"NL","name":"Newfoundland and Labrador"},"72":{"code":"NT","name":"Northwest Territories"},"71":{"code":"NS","name":"Nova Scotia"},"73":{"code":"NU","name":"Nunavut"},"74":{"code":"ON","name":"Ontario"},"75":{"code":"PE","name":"Prince Edward Island"},"76":{"code":"QC","name":"Quebec"},"77":{"code":"SK","name":"Saskatchewan"},"78":{"code":"YT","name":"Yukon Territory"}}},"DE":{"name":"Germany","regions":{"80":{"code":"BAW","name":"Baden-W\u00fcrttemberg"},"81":{"code":"BAY","name":"Bayern"},"82":{"code":"BER","name":"Berlin"},"83":{"code":"BRG","name":"Brandenburg"},"84":{"code":"BRE","name":"Bremen"},"85":{"code":"HAM","name":"Hamburg"},"86":{"code":"HES","name":"Hessen"},"87":{"code":"MEC","name":"Mecklenburg-Vorpommern"},"79":{"code":"NDS","name":"Niedersachsen"},"88":{"code":"NRW","name":"Nordrhein-Westfalen"},"89":{"code":"RHE","name":"Rheinland-Pfalz"},"90":{"code":"SAR","name":"Saarland"},"91":{"code":"SAS","name":"Sachsen"},"92":{"code":"SAC","name":"Sachsen-Anhalt"},"93":{"code":"SCN","name":"Schleswig-Holstein"},"94":{"code":"THE","name":"Th\u00fcringen"}}},"GB":{"name":"United Kingdom"},"JP":{"name":"Japan"},"NL":{"name":"Netherlands"},"US":{"name":"United States","regions":{"1":{"code":"AL","name":"Alabama"},"2":{"code":"AK","name":"Alaska"},"3":{"code":"AS","name":"American Samoa"},"4":{"code":"AZ","name":"Arizona"},"5":{"code":"AR","name":"Arkansas"},"6":{"code":"AE","name":"Armed Forces Africa"},"7":{"code":"AA","name":"Armed Forces Americas"},"8":{"code":"AE","name":"Armed Forces Canada"},"9":{"code":"AE","name":"Armed Forces Europe"},"10":{"code":"AE","name":"Armed Forces Middle East"},"11":{"code":"AP","name":"Armed Forces Pacific"},"12":{"code":"CA","name":"California"},"13":{"code":"CO","name":"Colorado"},"14":{"code":"CT","name":"Connecticut"},"15":{"code":"DE","name":"Delaware"},"16":{"code":"DC","name":"District of Columbia"},"17":{"code":"FM","name":"Federated States Of Micronesia"},"18":{"code":"FL","name":"Florida"},"19":{"code":"GA","name":"Georgia"},"20":{"code":"GU","name":"Guam"},"21":{"code":"HI","name":"Hawaii"},"22":{"code":"ID","name":"Idaho"},"23":{"code":"IL","name":"Illinois"},"24":{"code":"IN","name":"Indiana"},"25":{"code":"IA","name":"Iowa"},"26":{"code":"KS","name":"Kansas"},"27":{"code":"KY","name":"Kentucky"},"28":{"code":"LA","name":"Louisiana"},"29":{"code":"ME","name":"Maine"},"30":{"code":"MH","name":"Marshall Islands"},"31":{"code":"MD","name":"Maryland"},"32":{"code":"MA","name":"Massachusetts"},"33":{"code":"MI","name":"Michigan"},"34":{"code":"MN","name":"Minnesota"},"35":{"code":"MS","name":"Mississippi"},"36":{"code":"MO","name":"Missouri"},"37":{"code":"MT","name":"Montana"},"38":{"code":"NE","name":"Nebraska"},"39":{"code":"NV","name":"Nevada"},"40":{"code":"NH","name":"New Hampshire"},"41":{"code":"NJ","name":"New Jersey"},"42":{"code":"NM","name":"New Mexico"},"43":{"code":"NY","name":"New York"},"44":{"code":"NC","name":"North Carolina"},"45":{"code":"ND","name":"North Dakota"},"46":{"code":"MP","name":"Northern Mariana Islands"},"47":{"code":"OH","name":"Ohio"},"48":{"code":"OK","name":"Oklahoma"},"49":{"code":"OR","name":"Oregon"},"50":{"code":"PW","name":"Palau"},"51":{"code":"PA","name":"Pennsylvania"},"52":{"code":"PR","name":"Puerto Rico"},"53":{"code":"RI","name":"Rhode Island"},"54":{"code":"SC","name":"South Carolina"},"55":{"code":"SD","name":"South Dakota"},"56":{"code":"TN","name":"Tennessee"},"57":{"code":"TX","name":"Texas"}
12128,"58":{"code":"UT","name":"Utah"},"59":{"code":"VT","name":"Vermont"},"60":{"code":"VI","name":"Virgin Islands"},"61":{"code":"VA","name":"Virginia"},"62":{"code":"WA","name":"Washington"},"63":{"code":"WV","name":"West Virginia"},"64":{"code":"WI","name":"Wisconsin"},"65":{"code":"WY","name":"Wyoming"}}},"data_id":1790365654},"captcha":[],"wishlist":{"items":[]},"company":[],"company_authorization":[],"customer-companies":[],"negotiable_quote":[],"purchase_order":[],"instant-purchase":[],"loggedAsCustomer":[],"multiplewishlist":[],"persistent":[],"review":[],"faq":[],"ammessages":[],"cart-data":[],"hyva_enterprise":[],"capi-event-ids":[],"wp_ga4":[],"yotposms-customer-behaviour":[],"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[]}</script>
12128
12129<div x-data="dataAmMessage()" x-bind="eventListeners" x-spread="eventListeners"></div>
12130<script>
12131    function dataAmMessage() {
12132        return {
12133            eventListeners: {
12134                ['@private-content-loaded.window'](event) {
12135                    const { ammessages } = event.detail.data;
12136
12137                    // Check if we're not on the 'checkout-cart-index' page and if messages exist
12138                    if (!document.body.classList.contains('checkout-cart-index') && ammessages?.messages) {
12139                        this.processMessages(ammessages.messages);
12140                    }
12141
12142                    const messages = JSON.parse(localStorage.getItem('amFreeGiftCartMessages'));
12143                    if (messages && messages.length > 0) {
12144                        messages.forEach(message => {
12145                            dispatchMessages([message], 5000);
12146                        });
12147                        localStorage.removeItem('amFreeGiftCartMessages');
12148                    }
12149                }
12150            },
12151            processMessages(messages) {
12152                if (messages.notice) {
12153                    this.handleNoticeMessage(messages.notice);
12154                }
12155            },
12156            handleNoticeMessage(notice) {
12157                if (!notice) return;
12158                const { type, text } = notice;
12159                dispatchMessages([{ type, text }]);
12160            }
12161        }
12162    }
12163</script>
12163
12164</div>
12164<script>
12165    function initAuthModal() {
12166        return {
12167            ...hyva.modal(),
12168            redirect: null,
12169            reload: false,
12170            showOrganizationModal: false,
12171            isInitializing: false,
12172            forceVisible: false,
12173            hide(value) {
12174                if (this.isInitializing) {
12175                    return;
12176                }
12177
12178                this.forceVisible = false;
12179                window.localStorage.removeItem('login_campaign_cart');
12180                this.$dispatch('set-landing', null);
12181                hyva.modal().hide.call(this, value);
12182
12183                setTimeout(() => {
12184                    this.$dispatch('set-login-title', null);
12185                    this.$dispatch('set-register-title', null);
12186                }, 800);
12187
12188                if (this.reload) {
12189                    window.location.reload();
12190                }
12191            },
12192            show(dialog, trigger) {
12193                this.isInitializing = true;
12194                this.forceVisible = true;
12195
12196                const result = hyva.modal().show.call(this, dialog, trigger);
12197                setTimeout(() => {
12198                    this.isInitializing = false;
12199                    this.forceVisible = false;
12200                }, 500);
12201
12202                return result;
12203            },
12204            handleOpenAuthModal(event) {
12205                if (event.detail) {
12206                    this.showOrganizationModal = event.detail.showOrganizationModal;
12207
12208                    // Handle tab parameter
12209                    if (event.detail.tab) {
12210                        // Dispatch event to set initial tab
12211                        this.$dispatch('set-initial-tab', { tab: event.detail.tab });
12212                    }
12213                }
12214            }
12215        };
12216    }
12217</script>
12217
12218<div
12219        x-data="initAuthModal"
12220        @set-redirect.window="redirect = $event.detail"
12221        @open-auth-modal.window="show('auth-modal', this.$event || $event); handleOpenAuthModal($event)"
12222        @close-auth-modal.window="hide('auth-modal')"
12223>
12224    <div x-cloak    data-dialog-ref-name="auth-modal"
12225    x-bind="overlay"
12226    class="fixed inset-0 bg-black bg-opacity-50 z-50">
12227    <div class="fixed flex justify-center items-center text-left z-40 items-center inset-0">
12228        <div x-ref="auth-modal" role="dialog" aria-modal="true"
12229                                                  class="inline-block bg-white shadow-xl p-6 md:p-[48px] max-h-[100dvh] w-full md:w-auto overflow-auto overscroll-y-contain rounded-none md:rounded h-fit lg:max-h-[90dvh] !rounded p-12 max-md:p-6 max-md:!w-full max-md:!rounded-none [&_.label]:mb-4 [&_.field.choice]:flex">
12230            
12231<div
12232        id="auth-modal-content"
12233        class="auth-modal-content modal-content mx-auto relative max-w-[400px] m-auto"
12234        x-data="authModalData()"
12235        :data-status="state"
12236        :class="{'max-w-none': state === 'register-success'}"
12237        @set-initial-tab.window="setInitialTab($event.detail.tab)">
12238        <button class="modal-close absolute right-0 top-2 z-20 md:top-3 text-primary hover:bg-transparent !border-transparent !bg-transparent"
12239            @click="hide"
12240            x-show="state !== 'register-success' && state !== 'beta-redirect'">
12241        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 26 24" fill="none"
12242             class="close-button-icon" role="img">
12243            <path d="M3 2L23 21.5234" stroke="currentColor" stroke-width="4" stroke-linecap="round"></path>
12244            <path d="M3 22L23 2.47665" stroke="currentColor" stroke-width="4" stroke-linecap="round"></path>
12245            <title>x</title></svg>
12246    </button>
12247    <div x-show="state === 'login'">
12248        <div class="login-modal-content text-black">
12249    <div aria-labelledby="block-customer-login-heading">
12250        <form class="form form-login"
12251              action="https://www.purdys.com/purdys-customer/AccountModal/login/" method="post"
12252              x-data="initCustomerLoginForm_6ab6cfd678bd1()"
12253              @submit.prevent="amRecaptchaModelExecute"
12254              x-on:amrecaptcha-executable-callback="submitForm"
12255              x-on:amrecaptcha-callback.window="if ($el.offsetParent !== null) amRecaptchaModelRecaptchaCallback($event)"
12256              x-on:amrecaptcha-expired-callback.window="if ($el.offsetParent !== null) amRecaptchaModelExpiredCallback($event)"
12257              id="customer-login-form-modal"
12258              data-role="customer-login-form">
12259            <div class="flex flex-row start-0 top-0 justify-center items-center w-full h-full absolute select-none z-10"
12260     style="background: rgba(255,255,255,0.5);"
12261     x-show="isLoading"
12262     x-cloak
12263     x-transition:enter="ease-out duration-200"
12264     x-transition:enter-start="opacity-0"
12265     x-transition:enter-end="opacity-100"
12266     x-transition:leave="ease-in duration-200"
12267     x-transition:leave-start="opacity-100"
12268     x-transition:leave-end="opacity-0">
12269    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
12270    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
1227012.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
12271    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
12272<title>loader</title></svg>
12273</div>
12274            <input type="hidden" name="form_key" :value="hyva.getFormKey()" />
12275            <input type="text" name="login[redirect]" x-model="redirect" hidden>
12276            <fieldset class="fieldset login">
12277                <legend class="mb-8">
12278                    <h2 class="text-2xl md:text-h2-lg !font-bold text-black max-w-[310px] font-richmond"
12279                        @set-login-title.window="customTitle = $event.detail" x-text="customTitle ?? defaultTitle">
12280                    </h2>
12281                </legend>
12282                <div class="text-black mb-8">
12283                    If you already have an account with us, sign in with your email address.                </div>
12284                <div class="field email required" :class="{'field-error': wrongCredentials}">
12285                    <label class="label !font-normal after:!m-0" for="email">
12286                        <span>Email Address</span>
12287                    </label>
12288                    <div class="control">
12289                        <input name="email" class="form-input w-full" required x-model="email"
12290                            autocomplete="off" id="email"
12291                            type="email" placeholder="Enter&#x20;your&#x20;email&#x20;address"
12292                            title="Email&#x20;Address" />
12293                    </div>
12294                </div>
12295                <div class="field password required mb-3" :class="{'field-error': wrongCredentials}">
12296                    <label for="pass after:!m-0 !font-normal" class="label">
12297                        <span>Password</span>
12298                    </label>
12299                    <div class="control flex items-center relative">
12300                        <div class="sr-only" aria-live="polite">
12301                            <template x-if="!showPassword">
12302                                <span>
12303                                    Password hidden                                </span>
12304                            </template>
12305                            <template x-if="showPassword">
12306                                <span>
12307                                    Password shown                                </span>
12308                            </template>
12309                        </div>
12310                        <input name="password" class="form-input w-full" required
12311                            :type="showPassword ? 'text' : 'password'" x-model="password"
12312                            placeholder="Enter&#x20;your&#x20;password"
12313                            autocomplete="off"
12314                            id="pass" title="Password" />
12315                        <button type="button" @click.stop="showPassword = !showPassword"
12316                            :aria-pressed="showPassword ? 'true' : 'false'" class="px-4 py-3 absolute right-0 !border-transparent h-full !bg-transparent"
12317                            :aria-label="showPassword ? 'Hide\u0020Password' : 'Show\u0020Password'">
12318                            <template x-if="!showPassword">
12319                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
12320  <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
12321  <path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
12322<title>eye</title></svg>
12323                            </template>
12324                            <template x-if="showPassword">
12325                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
12326  <path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/>
12327  <path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/>
12328<title>
12328eye-off</title></svg>
12329                            </template>
12330                        </button>
12331                    </div>
12332                </div>
12333
12334                <span class="text-[14px] leading-[18px] text-red contents" x-show="wrongCredentials">
12335                    Incorrect email or password. Try again or                    <a href="#" class="underline mb-4 !text-red"
12336                        @click.prevent="setState('forgotPassword', { email: email })">
12337                        <span class="font-bold">Forgot your password?</span>
12338                    </a>
12339                </span>
12340
12341                <a href="#" x-show="!wrongCredentials" class="underline block mb-4"
12342                    @click.prevent="setState('forgotPassword', { email: email })">
12343                    <span class="text-base font-bold">Forgot your password?</span>
12344                </a>
12345
12346                                                <div class="pt-4 pb-2">
12347                    <button type="submit" class="btn btn-primary disabled:opacity-75 w-full h-11" name="send"
12348                        :disabled="!email || !password || isLoading" >
12349                        <span class="body-2 leading-[22px]">Log In</span></button>
12350                </div>
12351                <div>
12352                    <template x-if="displayErrorMessage">
12353                        <p class="text-red flex items-center">
12354                            <span class="inline-block w-8 h-8 mr-3">
12355                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" role="img">
12356  <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
12357<title>exclamation-circle</title></svg>
12358                            </span>
12359                            <template x-for="errorMessage in errorMessages">
12360                                <span x-html="errorMessage"></span>
12361                            </template>
12362                        </p>
12363                    </template>
12364                </div>
12365            </fieldset>
12366        </form>
12367    </div>
12368    <div class="w-full">
12369            </div>
12370    
12370<script>
12371        // Stub function to prevent amRecaptchaModelExecute error
12372        if (typeof window.amRecaptchaModelExecute === 'undefined') {
12373            window.amRecaptchaModelExecute = function() {
12374                // Stub function - does nothing
12375                return true;
12376            };
12377        }
12378
12379        function initCustomerLoginForm_6ab6cfd678bd1() {
12380        return {
12381            defaultTitle: 'Sign in or create an account to continue',
12382            customTitle: null,
12383            errors: 0,
12384            hasCaptchaToken: 0,
12385            showPassword: false,
12386            displayErrorMessage: false,
12387            errorMessages: [],
12388            email: '',
12389            password: '',
12390            isLoading: false,
12391            wrongCredentials: false,
12392            isSubmitting: false,
12393            submitTimeout: null,
12394            captchaTimeout: null,
12395            setErrorMessages(messages) {
12396                this.errorMessages = [messages]
12397                this.displayErrorMessage = this.errorMessages.length
12398            },
12399                            submitForm() {
12400                    console.log('LOGIN submitForm called, isLoading:', this.isLoading, 'isSubmitting:', this.isSubmitting, 'formId: customer-login-form-modal');
12401
12402                // Bouncer: prevent multiple rapid submissions
12403                if (this.isSubmitting) {
12404                    console.log('Form already submitting, returning. isLoading:', this.isLoading, 'isSubmitting:', this.isSubmitting);
12405                    return;
12406                }
12407
12408                // Clear any existing timeouts
12409                if (this.submitTimeout) {
12410                    clearTimeout(this.submitTimeout);
12411                }
12412                if (this.captchaTimeout) {
12413                    clearTimeout(this.captchaTimeout);
12414                    this.captchaTimeout = null;
12415                }
12416
12417                // Set submitting state and timeout
12418                this.isSubmitting = true;
12419                this.submitTimeout = setTimeout(() => {
12420                    console.log('Submit timeout reached, resetting isSubmitting');
12421                    this.isSubmitting = false;
12422                    // Also reset loading state as a safety measure
12423                    if (this.isLoading) {
12424                        console.log('Also resetting stuck isLoading state');
12425                        this.isLoading = false;
12426                    }
12427                }, 15000); // 15 second timeout (longer to allow for network delays)
12428
12429                this.wrongCredentials = false;
12430                const $form = document.querySelector('#customer-login-form-modal');
12431                
12432                if (this.errors === 0) {
12433                    this.isLoading = true;
12434                    fetch('https://www.purdys.com/purdys-customer/AccountModal/login/', {
12435                            method: 'POST',
12436                            body: new FormData($form)
12437                        })
12438                        .then(response => response.json())
12439                        .then(data => {
12440                            if (data.success) {
12441                                localStorage.setItem('showLoginSuccess', 'true');
12442                                if (data.customer) {
12443                                    localStorage.setItem('customerData', JSON.stringify(data.customer));
12444                                }
12445
12446                                const cartData = window.localStorage.getItem('login_campaign_cart');
12447
12448                                this.$dispatch('reload-customer-section-data');
12449
12450                                if (cartData) {
12451                                    window.localStorage.removeItem('login_campaign_cart');
12452                                    const {
12453                                        product,
12454                                        campaign,
12455                                        qty = 1
12456                                    } = JSON.parse(cartData);
12457                                    this.hide('auth-modal');
12458                                    this.$dispatch('campaign-add-to-cart', {
12459                                        product,
12460                                        qty,
12461                                        campaign,
12462                                        referral: true
12463                                    });
12464                                    return;
12465                                }
12466
12467                                if (this.redirect) {
12468                                    window.location.href = this.redirect;
12469                                    return;
12470                                }
12471
12472                                if (this.showOrganizationModal) {
12473                                    this.setState('organization');
12474                                    this.reload = true;
12475                                    return;
12476                                }
12477
12478                                if (data.redirectToDashboard && window.location.pathname.includes('/fr')) {
12479                                    window.location.href = 'https://www.purdys.com/customer/account/';
12480                                    return;
12481                                }
12482
12483                                if (data.redirectToDashboard) {
12484                                    window.location.href = 'https://www.purdys.com/customer/campaigns/';
12485                                    return;
12486                                }
12487
12488                                window.location.reload();
12489                                return;
12490                            }
12491
12492                            if (data.error && data.type === 'auth') {
12493                                this.wrongCredentials = true;
12494                                return;
12495                            }
12496
12497                            window.dispatchMessages([{
12498                                type: 'error',
12499                                text: data.error
12500                            }], 10000);
12501                        })
12502                        .catch(error => {
12503
12504                        })
12505                        .finally(() => {
12506                            this.isLoading = false;
12507                            this.isSubmitting = false;
12508                        });
12509                }
12510            },
12511            // Initialize Amasty captcha integration
12512            init() {
12513                console.log('Login modal form initialized');
12514
12515                // Add our form to Amasty's forms list after it's initialized
12516                const addFormToAmasty = () => {
12517                    if (window.amRecaptchaModel && window.amRecaptchaModel.formsToProtect !== undefined) {
12518                        const currentForms = window.amRecaptchaModel.formsToProtect || '';
12519                        const ourFormSelector = '#customer-login-form-modal';
12520
12521                        if (!currentForms.includes(ourFormSelector)) {
12522                            window.amRecaptchaModel.formsToProtect = currentForms ?
12523                                currentForms + ',' + ourFormSelector : ourFormSelector;
12524                            console.log('Added our form to Amasty protection:', window.amRecaptchaModel.formsToProtect);
12525                        }
12526
12527                        return true;
12528                    }
12529                    return false;
12530                };
12531
12532                // Try immediately and then keep trying
12533                if (!addFormToAmasty()) {
12534                    const interval = setInterval(() => {
12535                        if (addFormToAmasty()) {
12536                            clearInterval(interval);
12537                        }
12538                    }, 100);
12539
12540                    // Stop trying after 5 seconds
12541                    setTimeout(() => clearInterval(interval), 5000);
12542                }
12543
12544                // Check what forms Amasty is configured to protect
12545                setTimeout(() => {
12546                    if (window.amRecaptchaModel) {
12547                        console.log('Final Amasty forms to protect:', window.amRecaptchaModel.formsToProtect);
12548                        console.log('Our form element:', this.$el.id, this.$el.getAttribute('data-role'));
12549                    }
12550                }, 2000);
12551            },
12552
12553            // Amasty captcha methods - these will be overridden by the form submit handler
12554            amRecaptchaModelExecute($event) {
12555                // Prevent multiple rapid executions
12556                if (this.isLoading) {
12557                    console.log('Already processing captcha, ignoring duplicate call');
12558                    return;
12559                }
12560
12561                console.log('amRecaptchaModelExecute called');
12562                this.isLoading = true;
12563
12564                // Clear any existing timeout
12565                if (this.captchaTimeout) {
12566                    clearTimeout(this.captchaTimeout);
12567                }
12568
12569                // Set a timeout to prevent infinite loading if captcha fails
12570                this.captchaTimeout = setTimeout(() => {
12571                    if (this.isLoading) {
12572                        console.log('Captcha timeout reached, submitting form anyway');
12573                        this.isLoading = false;
12574                        this.isSubmitting = false; // Reset submitting state
12575                        this.submitForm();
12576                    }
12577                }, 10000); // 10 second timeout
12578
12579                // Check if Amasty captcha is properly initialized
12580                if (window.amRecaptchaModel && typeof window.amRecaptchaModel.execute === 'function') {
12581                    console.log('Calling Amasty execute method');
12582                    try {
12583                        window.amRecaptchaModel.execute($event);
12584                    } catch (error) {
12585                        console.error('Captcha execution failed:', error);
12586                        this.isLoading = false;
12587                        this.isSubmitting = false; // Reset submitting state
12588                        this.submitForm();
12589                    }
12590                } else {
12591                    console.log('Amasty not properly initialized, using fallback');
12592                    this.submitForm();
12593                }
12594            },
12595
12596                            amRecaptchaModelRecaptchaCallback($event, $el) {
12597                    console.log('LOGIN amRecaptchaModelRecaptchaCallback called - should submit form now', {
12598                        formId: 'customer-login-form-modal',
12599                        visible: $el ? $el.offsetParent !== null : 'unknown',
12600                        event: $event
12601                    });
12602
12603                    // Clear the timeout since captcha succeeded
12604                    if (this.captchaTimeout) {
12605                        clearTimeout(this.captchaTimeout);
12606                        this.captchaTimeout = null;
12607                    }
12608
12609                    // This callback means captcha validation passed, so submit the form
12610                    this.submitForm();
12611                },
12612
12613            amRecaptchaModelExpiredCallback($event, $el) {
12614                console.log('amRecaptchaModelExpiredCallback called - captcha expired');
12615
12616                // Clear the timeout and reset loading state
12617                if (this.captchaTimeout) {
12618                    clearTimeout(this.captchaTimeout);
12619                    this.captchaTimeout = null;
12620                }
12621
12622                // Reset loading state and show error
12623                this.isLoading = false;
12624                this.isSubmitting = false;
12625
12626                                // Show user-friendly error message
12627                window.dispatchMessages([{
12628                    type: 'error',
12629                    text: 'Security\u0020verification\u0020expired.\u0020Please\u0020try\u0020again.'
12630                }], 5000);
12631
12632                // Reset the form to allow retry
12633                this.wrongCredentials = false;
12634            },
12635
12636            // Cleanup method to clear timeouts
12637            destroy() {
12638                if (this.captchaTimeout) {
12639                    clearTimeout(this.captchaTimeout);
12640                    this.captchaTimeout = null;
12641                }
12642                if (this.submitTimeout) {
12643                    clearTimeout(this.submitTimeout);
12644                    this.submitTimeout = null;
12645                }
12646            }
12647        }
12648    }
12649
12650    document.addEventListener('DOMContentLoaded', function() {
12651        if (localStorage.getItem('showLoginSuccess') === 'true') {
12652            const customerData = JSON.parse(localStorage.getItem('customerData') || '{}');
12653            const firstName = customerData.firstname || '';
12654
12655            let welcomeMessage = 'You\u0020have\u0020successfully\u0020logged\u0020in.';
12656            if (firstName) {
12657                welcomeMessage = `You\u0020have\u0020successfully\u0020logged\u0020in,\u0020\u00251\u0021`
12658                    .replace('%1', firstName);
12659            }
12660
12661            window.dispatchMessages([{
12662                type: 'success',
12663                text: welcomeMessage
12664            }], 5000);
12665
12666            localStorage.removeItem('showLoginSuccess');
12667            localStorage.removeItem('customerData');
12668        }
12669    });
12670    </script>
12670
12671</div>
12672        <div class="text-center mt-6">
12673            <p>Don't have an account?</p>
12674            <a href="#" class="underline" @click.prevent="setState('register')">
12675                <span class="text-base font-bold">Create one now</span>
12676            </a>
12677        </div>
12678    </div>
12679    <div x-show="state === 'forgotPassword'">
12680        <div class="password-modal-content">
12681    <div aria-labelledby="block-customer-password-heading">
12682        <form class="form form-password"
12683              action="https://www.purdys.com/scandiweb-customer/AccountModal/forgotPassword/"
12684              method="post"
12685              x-data="initForgotPasswordForm()"
12686                              @submit.prevent="amRecaptchaModelExecute"
12687                x-on:amrecaptcha-executable-callback="submitForm"
12688                x-on:amrecaptcha-callback.window="if ($el.offsetParent !== null) amRecaptchaModelRecaptchaCallback($event)"
12689                x-on:amrecaptcha-expired-callback.window="if ($el.offsetParent !== null) amRecaptchaModelExpiredCallback($event)"
12690
12691              id="user_forgotpassword">
12692            <input type="hidden" name="form_key" :value="hyva.getFormKey()" />
12693            <input type="hidden" name="formId" value="user_forgotpassword"/>
12694            <fieldset class="fieldset password">
12695                <legend class="mb-8">
12696                    <h2 class="text-2xl md:text-h2-lg !font-bold text-black pr-16">
12697                        Forgot your password?                    </h2>
12698                </legend>
12699                <div class=" mb-8">
12700                    Please enter your email address below to receive a password reset link.                </div>
12701
12702                <!-- Error Message Display -->
12703                <div class="mb-4" x-show="displayErrorMessage">
12704                    <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
12705                        <span class="block sm:inline" x-text="errorMessages[0] || 'An\u0020error\u0020occurred.\u0020Please\u0020try\u0020again.'"></span>
12706                    </div>
12707                </div>
12708
12709                <div class="field email required">
12710                    <label for="email_address" class="label after:!m-0">
12711                        <span>Email</span>
12712                    </label>
12713                    <div class="control">
12714                        <input type="email"
12715                               name="email"
12716                               alt="email"
12717                               id="forgot_password_email_address"
12718                               class="form-input w-full"
12719                               autocomplete="off"
12720                               required
12721                               value="">
12722                    </div>
12723                </div>
12724                                                                <div class="pt-4 pb-2">
12725                    <button type="submit" class="btn btn-primary disabled:opacity-75 w-full h-11"
12726                            :disabled="isLoading"
12727                            >
12728                        <span class="body-2 leading-[22px]">RESET MY PASSWORD</span>
12729                    </button>
12730                </div>
12731            </fieldset>
12732        </form>
12733    </div>
12734    <div class="w-full">
12735            </div>
12736    
12736<script>
12737        function initForgotPasswordForm() {
12738            return {
12739                errors: 0,
12740                hasCaptchaToken: 0,
12741                displayErrorMessage: false,
12742                errorMessages: [],
12743                isSubmitting: false,
12744                submitTimeout: null,
12745                captchaTimeout: null,
12746                setErrorMessages(messages) {
12747                    this.errorMessages = [messages]
12748                    this.displayErrorMessage = this.errorMessages.length
12749                },
12750                // Initialize Amasty captcha integration
12751                init() {
12752                    console.log('Forgot password modal form initialized');
12753
12754                    // Add our form to Amasty's forms list after it's initialized
12755                    const addFormToAmasty = () => {
12756                        if (window.amRecaptchaModel && window.amRecaptchaModel.formsToProtect !== undefined) {
12757                            const currentForms = window.amRecaptchaModel.formsToProtect || '';
12758                            const ourFormSelector = '#user_forgotpassword';
12759
12760                            if (!currentForms.includes(ourFormSelector)) {
12761                                window.amRecaptchaModel.formsToProtect = currentForms ?
12762                                    currentForms + ',' + ourFormSelector : ourFormSelector;
12763                                console.log('Added forgot password form to Amasty protection:', window.amRecaptchaModel.formsToProtect);
12764                            }
12765
12766                            return true;
12767                        }
12768                        return false;
12769                    };
12770
12771                    // Try immediately and then keep trying
12772                    if (!addFormToAmasty()) {
12773                        const interval = setInterval(() => {
12774                            if (addFormToAmasty()) {
12775                                clearInterval(interval);
12776                            }
12777                        }, 100);
12778
12779                        // Stop trying after 5 seconds
12780                        setTimeout(() => clearInterval(interval), 5000);
12781                    }
12782
12783                    // Check what forms Amasty is configured to protect
12784                    setTimeout(() => {
12785                        if (window.amRecaptchaModel) {
12786                            console.log('Final Amasty forms to protect:', window.amRecaptchaModel.formsToProtect);
12787                            console.log('Our forgot password form element:', this.$el.id);
12788                        }
12789                    }, 2000);
12790                },
12791
12792                // Amasty captcha methods
12793                amRecaptchaModelExecute($event) {
12794                    // Prevent multiple rapid executions
12795                    if (this.isLoading) {
12796                        console.log('Already processing captcha, ignoring duplicate call');
12797                        return;
12798                    }
12799
12800                    console.log('Forgot password amRecaptchaModelExecute called');
12801                    this.isLoading = true;
12802
12803                    // Clear any existing timeout
12804                    if (this.captchaTimeout) {
12805                        clearTimeout(this.captchaTimeout);
12806                    }
12807
12808                    // Set a timeout to prevent infinite loading if captcha fails
12809                    this.captchaTimeout = setTimeout(() => {
12810                        if (this.isLoading) {
12811                            console.log('Forgot password captcha timeout reached, submitting form anyway');
12812                            this.isLoading = false;
12813                            this.isSubmitting = false; // Reset submitting state
12814                            this.submitForm();
12815                        }
12816                    }, 10000); // 10 second timeout
12817
12818                    // Check if Amasty captcha is properly initialized
12819                    if (window.amRecaptchaModel && typeof window.amRecaptchaModel.execute === 'function') {
12820                        console.log('Calling Amasty execute method for forgot password');
12821                        try {
12822                            window.amRecaptchaModel.execute($event);
12823                        } catch (error) {
12824                            console.error('Forgot password captcha execution failed:', error);
12825                            this.isLoading = false;
12826                            this.isSubmitting = false; // Reset submitting state
12827                            this.submitForm();
12828                        }
12829                    } else {
12830                        console.log('Amasty not properly initialized, using fallback for forgot password');
12831                        this.submitForm();
12832                    }
12833                },
12834
12835                amRecaptchaModelRecaptchaCallback($event, $el) {
12836                    console.log('FORGOT PASSWORD amRecaptchaModelRecaptchaCallback called - should submit form now', {
12837                        formId: 'user_forgotpassword',
12838                        visible: $el ? $el.offsetParent !== null : 'unknown',
12839                        event: $event
12840                    });
12841
12842                    // Clear the timeout since captcha succeeded
12843                    if (this.captchaTimeout) {
12844                        clearTimeout(this.captchaTimeout);
12845                        this.captchaTimeout = null;
12846                    }
12847
12848                    // This callback means captcha validation passed, so submit the form
12849                    this.submitForm();
12850                },
12851
12852                amRecaptchaModelExpiredCallback($event, $el) {
12853                    console.log('Forgot password amRecaptchaModelExpiredCallback called - captcha expired');
12854
12855                    // Clear the timeout and reset loading state
12856                    if (this.captchaTimeout) {
12857                        clearTimeout(this.captchaTimeout);
12858                        this.captchaTimeout = null;
12859                    }
12860
12861                    // Reset loading state and show error
12862                    this.isLoading = false;
12863                    this.isSubmitting = false;
12864
12865                    // Show user-friendly error message
12866                    window.dispatchMessages([{
12867                        type: 'error',
12868                        text: 'Security\u0020verification\u0020expired.\u0020Please\u0020try\u0020again.'
12869                    }], 5000);
12870                },
12871                submitForm() {
12872                    console.log('FORGOT PASSWORD submitForm called, formId:', 'user_forgotpassword');
12873
12874                    // Bouncer: prevent multiple rapid submissions
12875                    if (this.isSubmitting) {
12876                        console.log('Forgot password form already submitting, returning. isLoading:', this.isLoading, 'isSubmitting:', this.isSubmitting);
12877                        return;
12878                    }
12879
12880                    // Clear any existing timeouts
12881                    if (this.submitTimeout) {
12882                        clearTimeout(this.submitTimeout);
12883                    }
12884                    if (this.captchaTimeout) {
12885                        clearTimeout(this.captchaTimeout);
12886                        this.captchaTimeout = null;
12887                    }
12888
12889                    // Clear error state when submitting
12890                    this.displayErrorMessage = false;
12891                    this.errorMessages = [];
12892
12893                    // Set submitting state and timeout
12894                    this.isSubmitting = true;
12895                    this.submitTimeout = setTimeout(() => {
12896                        console.log('Forgot password submit timeout reached, resetting isSubmitting');
12897                        this.isSubmitting = false;
12898                        // Also reset loading state as a safety measure
12899                        if (this.isLoading) {
12900                            console.log('Also resetting stuck isLoading state for forgot password');
12901                            this.isLoading = false;
12902                        }
12903                    }, 15000); // 15 second timeout (longer to allow for network delays)
12904
12905                    const $form = document.querySelector('#user_forgotpassword');
12906                    
12907                    if (this.errors === 0) {
12908                        this.isLoading = true;
12909
12910                        // Use fetch to submit the form and handle JSON response
12911                        const formData = new FormData($form);
12912
12913                        fetch($form.action, {
12914                            method: 'POST',
12915                            body: formData,
12916                            headers: {
12917                                'X-Requested-With': 'XMLHttpRequest'
12918                            }
12919                        })
12920                            .then(response => response.json())
12921                            .then(data => {
12922                                this.isLoading = false;
12923                                this.isSubmitting = false;
12924
12925                                if (data.success) {
12926                                    // Clear error state on success
12927                                    this.displayErrorMessage = false;
12928                                    this.errorMessages = [];
12929
12930                                    // Close the modal using the event dispatch approach
12931                                    const modalContent = document.querySelector('#auth-modal-content');
12932
12933                                    if (modalContent && modalContent.__x) {
12934                                        // First set state to login
12935                                        modalContent.__x.$data.setState('login');
12936                                    }
12937
12938                                    // Dispatch the close event that the modal is listening for
12939                                    window.dispatchEvent(new CustomEvent('close-auth-modal'));
12940
12941                                    // Show success message using multiple methods to ensure it appears
12942                                    if (typeof window.dispatchMessages !== "undefined") {
12943                                        window.dispatchMessages([{
12944                                            type: 'success',
12945                                            text: data.message
12946                                        }], 5000);
12947                                    } else if (window.hyva && window.hyva.messages) {
12948                                        window.hyva.messages.addMessage('success', data.message);
12949                                    } else {
12950                                        // Fallback: dispatch custom event
12951                                        window.dispatchEvent(new CustomEvent('messages-loaded', {
12952                                            detail: {
12953                                                messages: [{
12954                                                    type: 'success',
12955                                                    text: data.message
12956                                                }],
12957                                                hideAfter: 5000
12958                                            }
12959                                        }));
12960                                    }
12961
12962                                    // Clear the form
12963                                    $form.reset();
12964                                } else {
12965                                    // Show error message in the form
12966                                    this.setErrorMessages(data.error || 'An\u0020error\u0020occurred.\u0020Please\u0020try\u0020again.');
12967
12968                                    // Show error message using multiple methods to ensure it appears
12969                                    if (typeof window.dispatchMessages !== "undefined") {
12970                                        window.dispatchMessages([{
12971                                            type: 'error',
12972                                            text: data.error
12973                                        }], 8000);
12974                                    } else if (window.hyva && window.hyva.messages) {
12975                                        window.hyva.messages.addMessage('error', data.error);
12976                                    } else {
12977                                        // Fallback: dispatch custom event
12978                                        window.dispatchEvent(new CustomEvent('messages-loaded', {
12979                                            detail: {
12980                                                messages: [{
12981                                                    type: 'error',
12982                                                    text: data.error
12983                                                }],
12984                                                hideAfter: 8000
12985                                            }
12986                                        }));
12987                                    }
12988                                }
12989                            })
12990                            .catch(error => {
12991                                this.isLoading = false;
12992                                if (typeof window.dispatchMessages !== "undefined") {
12993                                    window.dispatchMessages([{
12994                                        type: 'error',
12995                                        text: 'An\u0020error\u0020occurred.\u0020Please\u0020try\u0020again.'
12996                                    }], 8000);
12997                                } else if (window.hyva && window.hyva.messages) {
12998                                    window.hyva.messages.addMessage('error', 'An\u0020error\u0020occurred.\u0020Please\u0020try\u0020again.');
12999                                } else {
13000                                    // Fallback: dispatch custom event
13001                                    window.dispatchEvent(new CustomEvent('messages-loaded', {
13002                                        detail: {
13003                                            messages: [{
13004                                                type: 'error',
13005                                                text: 'An\u0020error\u0020occurred.\u0020Please\u0020try\u0020again.'
13006                                            }],
13007                                            hideAfter: 8000
13008                                        }
13009                                    }));
13010                                }
13011                                console.error('Error:', error);
13012                            });
13013                    } else {
13014                        this.isLoading = false;
13015                    }
13016                },
13017
13018                // Cleanup method to clear timeouts
13019                destroy() {
13020                    if (this.captchaTimeout) {
13021                        clearTimeout(this.captchaTimeout);
13022                        this.captchaTimeout = null;
13023                    }
13024                    if (this.submitTimeout) {
13025                        clearTimeout(this.submitTimeout);
13026                        this.submitTimeout = null;
13027                    }
13028                }
13029            }
13030        }
13031    </script>
13031
13032</div>
13033        <div class="text-center mt-6">
13034            <a href="#" class="underline uppercase" @click.prevent="setState('login')">
13035                <span class="text-base font-bold">Back</span>
13036            </a>
13037        </div>
13038        <div class="text-center mt-6">
13039            <p>Don't have an account?</p>
13040            <a href="#" class="underline" @click.prevent="setState('register')">
13041                <span class="text-base font-bold">Then create one now.</span>
13042            </a>
13043        </div>
13044    </div>
13045    <div x-show="state === 'register'">
13046        <div class="mb-4">
13047            <form class="form create account form-create-account text-black !min-w-0 !w-full"
13048          action="https://www.purdys.com/purdys-customer/AccountModal/Create/"
13049          x-data="Object.assign(hyva.formValidation($el), initRegisterModalForm6ab6cfd67accc())"
13050          id="accountcreate-modal6ab6cfd67accc"
13051          @submit.prevent="amRecaptchaModelExecute"
13052          x-on:amrecaptcha-executable-callback="submitForm"
13053          x-on:amrecaptcha-callback.window="if ($el.offsetParent !== null) amRecaptchaModelRecaptchaCallback($event)"
13054          x-on:amrecaptcha-expired-callback.window="if ($el.offsetParent !== null) amRecaptchaModelExpiredCallback($event)"
13055          method="post" id="form-validate" enctype="multipart/form-data" autocomplete="off"
13056    >
13057                    <div class="flex flex-row start-0 top-0 justify-center items-center w-full h-full absolute select-none z-10"
13058     style="background: rgba(255,255,255,0.5);"
13059     x-show="isLoading"
13060     x-cloak
13061     x-transition:enter="ease-out duration-200"
13062     x-transition:enter-start="opacity-0"
13063     x-transition:enter-end="opacity-100"
13064     x-transition:leave="ease-in duration-200"
13065     x-transition:leave-start="opacity-100"
13066     x-transition:leave-end="opacity-0">
13067    <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 56 56" fill="none" class="animate-[spin_2s_linear_infinite] text-primary" role="img">
13068    <path d="M52.5 28C52.5 31.2174 51.8663 34.4033 50.6351 37.3757C49.4038 40.3482 47.5992 43.0491 45.3241 45.3241C43.0491 47.5992 40.3482 49.4038 37.3757 50.635C34.4033 51.8663 31.2174 52.5 28 52.5C24.7826 52.5 21.5967 51.8663 18.6243 50.635C15.6518 49.4038 12.9509 47.5991 10.6759 45.3241C8.40085 43.0491 6.59619 40.3482 5.36495 37.3757C4.13371 34.4033 3.5 31.2174 3.5 28C3.5 24.7826 4.13371 21.5967 5.36496 18.6242C6.5962 15.6518 8.40086 12.9509 10.6759 10.6759C12.9509 8.40084 15.6518 6.59619 18.6243 5.36495C21.5967 4.13371 24.7826 3.5 28 3.5C31.2174 3.5 34.4033 4.13371 37.3758 5.36496C40.3482 6.5962 43.0491 8.40086 45.3241 10.6759C47.5992 
1306812.9509 49.4038 15.6518 50.6351 18.6243C51.8663 21.5967 52.5 24.7826 52.5 28L52.5 28Z" stroke="#EEEAF4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
13069    <path d="M52.5 28C52.5 24.7826 51.8663 21.5967 50.6351 18.6243C49.4038 15.6518 47.5992 12.9509 45.3241 10.6759C43.0491 8.40085 40.3482 6.59619 37.3757 5.36495C34.4033 4.13371 31.2174 3.5 28 3.5" stroke="#532E91" stroke-width="6" stroke-linecap="square"/>
13070<title>loader</title></svg>
13071</div>
13072        <input type="hidden" name="form_key" :value="hyva.getFormKey()"/>
13073        <input type="text" name="redirect" x-model="redirect" hidden>
13074                        <div class="w-full">
13075            <fieldset class="fieldset register !m-0">
13076                <legend class="mb-3">
13077                    <h2 class="text-2xl md:text-h2-lg !font-bold text-black max-w-[235px]"
13078                        @set-register-title.window="customTitle = $event.detail"
13079                        x-text="getTitle()"
13080                        x-init="updateContentBasedOnContext()"
13081                    ></h2>
13082                </legend>
13083
13084                <!-- Dynamic description based on context -->
13085                <div class="mb-6 text-center" x-show="showDescription" x-text="getDescription()"></div>
13086
13087                <!-- Error Message Display -->
13088                <div class="mb-4" x-show="registrationError">
13089                    <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
13090                        <span class="block sm:inline" x-text="errorMessages[0] || 'Registration\u0020failed.\u0020Please\u0020try\u0020again.'"></span>
13091                    </div>
13092                </div>
13093
13094                <input type="hidden" name="success_url" value="">
13095                <input type="hidden" name="error_url" value="">
13096                <div class="field field-reserved required">
13097                    <label for="firstname" class="label !mb-3 !font-normal">
13098                        <span>First Name</span>
13099                    </label>
13100                    <div class="control !m-0">
13101                        <input
13102                                type="text"
13103                                name="firstname"
13104                                id="firstname"
13105                                required
13106                                value=""
13107                                title="First&#x20;Name"
13108                                placeholder="First&#x20;Name"
13109                                class="form-input"
13110                                @input.debounce="onChange"
13111                        />
13112                        <ul class="messages !m-0" aria-live="polite"></ul>
13113                    </div>
13114                </div>
13115                <div class="field field-reserved required">
13116                    <label for="lastname" class="label !mb-3 !font-normal after:!m-0">
13117                        <span>Last Name</span>
13118                    </label>
13119                    <div class="control !m-0">
13120                        <input
13121                                type="text"
13122                                name="lastname"
13123                                id="lastname"
13124                                required
13125                                value=""
13126                                title="Last&#x20;Name"
13127                                placeholder="Last&#x20;Name"
13128                                class="form-input"
13129                                @input.debounce="onChange"
13130                        />
13131                    </div>
13132                </div>
13133                <div class="field field-reserved required">
13134                    <label for="email_address" class="label !mb-3 !font-normal after:!m-0">
13135                        <span>Email</span>
13136                    </label>
13137                    <div class="control !m-0">
13138                        <input
13139                                type="email"
13140                                name="email"
13141                                autocomplete="email"
13142                                id="register_email_address"
13143                                required
13144                                value=""
13145                                title="Email"
13146                                class="form-input"
13147                                placeholder="Enter&#x20;your&#x20;email&#x20;address"
13148                                @input.debounce="onChange"
13149                        />
13150                    </div>
13151                </div>
13152                <div class="field field-reserved required">
13153                    <label for="password" class="label !mb-3 !font-normal after:!m-0">
13154                        <span>Password</span>
13155                    </label>
13156                    <div class="flex flex-wrap gap-4">
13157                        <div class="control !m-0 flex items-center w-full relative">
13158                                                        <div class="sr-only" aria-live="polite">
13159                                <template x-if="!showPassword">
13160                                    <span>
13161                                        Password hidden                                    </span>
13162                                </template>
13163                                <template x-if="showPassword">
13164                                    <span>
13165                                        Password shown                                    </span>
13166                                </template>
13167                            </div>
13168                            <input
13169                                    :type="showPassword ? 'text' : 'password'"
13170                                    type="password"
13171                                    id="password"
13172                                    name="password"
13173                                    title="Password"
13174                                    minlength="8"
13175                                    class="form-input placeholder:tracking-normal"
13176                                    required
13177                                    placeholder="Enter your password"
13178                                    data-validate='{"password-strength": {"minCharacterSets": 3}}'
13179                                    @input.debounce="onChange"
13180                                    autocomplete="off"
13181                            >
13182                            <button
13183                                    type="button"
13184                                    :aria-pressed="showPassword ? true : false"
13185                                    @click.stop="showPassword = !showPassword"
13186                                    class="px-4 py-3 absolute right-0 h-full !bg-transparent !border-transparent"
13187                                    :aria-label="showPassword ? 'Hide\u0020Password' : 'Show\u0020Password'"
13188                            >
13189                                <template x-if="!showPassword">
13190                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
13191  <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
13192  <path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
13193<title>eye</title></svg>
13194                                </template>
13195                                <template x-if="showPassword">
13196                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
13197  <path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/>
13198  <path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/>
13199<title>eye-off</title></svg>
13200                                </template>
13201                            </button>
13202                        </div>
13203                    </div>
13204                </div>
13205                <div class="field field-reserved required">
13206                    <label for="password-confirmation" class="label !mb-3 !font-normal after:!m-0">
13207                        <span>Confirm Password</span>
13208                    </label>
13209                    <div class="control !m-0 flex items-center relative">
13210                        <div class="sr-only" aria-live="polite">
13211                            <template x-if="!showPasswordConfirm">
13212                                <span>
13213                                    Confirm password hidden                                </span>
13214                            </template>
13215                            <template x-if="showPasswordConfirm">
13216                                <span>
13217                                    confirm password shown                                </span>
13218                            </template>
13219                        </div>
13220                        <input
13221                                :type="showPasswordConfirm ? 'text' : 'password'"
13222                                type="password"
13223                                name="password_confirmation"
13224                                title="Confirm&#x20;Password"
13225                                id="password-confirmation"
13226                                data-validate='{"equalTo": "password"}'
13227                                @input.debounce="onChange"
13228                                required
13229                                placeholder="Re-enter your password"
13230                                class="form-input placeholder:tracking-normal"
13231                                autocomplete="off"
13232                        >
13233                        <button
13234                                type="button"
13235                                @click.stop="showPasswordConfirm = !showPasswordConfirm"
13236                                :aria-pressed="showPasswordConfirm ? true : false"
13237                                class="px-4 py-3 absolute right-0 h-full !bg-transparent !border-transparent"
13238                                :aria-label="
13239                                showPasswordConfirm ? 'Hide\u0020Password' : 'Show\u0020Password'
13240                            "
13241                        >
13242                            <template x-if="!showPasswordConfirm">
13243                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
13244  <path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
13245  <path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
13246<title>eye</title></svg>
13247                            </template>
13248                            <template x-if="showPasswordConfirm">
13249                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img">
13250  <path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/>
13251  <path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/>
13252<title>eye-off</title></svg>
13253                            </template>
13254                        </button>
13255                    </div>
13256                </div>
13257                <!-- Promotional Email Checkbox -->
13258                                    <div class="field choice newsletter !m-0 !mt-0 !gap-6">
13259                        <input type="checkbox"
13260                               name="is_subscribed"
13261                               title="Sign&#x20;me&#x20;up&#x20;to&#x20;receive&#x20;promotional&#x20;emails&#x20;from&#x20;Purdys&#x20;Chocolatier."
13262                               value="1"
13263                               id="is_subscribed_modal_6ab6cfd67accc"
13264                                                               class="checked:!bg-primary focus:checked:!bg-primary !m-0 !mt-[5px]">
13265                        <label for="is_subscribed_modal_6ab6cfd67accc" class="label !mb-0">
13266                            <span>Sign me up to receive promotional emails from Purdys Chocolatier.</span>
13267                        </label>
13268                    </div>
13269                
13270                <!-- Text Messages Checkbox -->
13271                <div class="field choice newsletter !m-0 !mt-0 !gap-6">
13272                    <input type="checkbox"
13273                           name="text_messages_subscription"
13274                           title="Sign&#x20;me&#x20;up&#x20;to&#x20;receive&#x20;text&#x20;messages&#x20;from&#x20;Purdys&#x20;Chocolatier."
13275                           value="1"
13276                           id="text_messages_subscription_modal_6ab6cfd67accc"
13277                           class="checked:!bg-primary focus:checked:!bg-primary !m-0 !mt-[3px]">
13278                    <label for="text_messages_subscription_modal_6ab6cfd67accc"
13279                           class="label !font-normal after:!m-0">
13280                        <span>Sign me up to receive text messages from Purdys Chocolatier.</span>
13281                    </label>
13282                </div>
13283
13284                <!-- Terms and Conditions Disclaimer -->
13285                <div class="field choice !mb-2.5 !ms-10 term-cond">
13286                    <p>*By selecting, you agree to receive emails and newsletters, also to our                        <a href="https://www.purdys.com/terms-of-use/" target="_blank"
13287                           class="text-primary underline">Terms &amp; Conditions</a>
13288                        and                        <a href="https://www.purdys.com/privacy-policy/" target="_blank"
13289                           class="text-primary underline">Privacy Policy</a>.
13290                        This is protected by reCAPTCHA</p>
13291                </div>
13292
13293                            </fieldset>
13294        </div>
13295        <div class="pt-4 pb-2">
13296            <button type="submit" class="action submit !primary !btn !btn-primary disabled:opacity-75 w-full h-11"
13297                    title="Create&#x20;Account"
13298                                        :disabled="isCreateAccountButtonDisabled || isLoading">
13299                <span class="body-2 leading-[22px]">Create Account</span>
13300            </button>
13301        </div>
13302    </form>
13303    
13303<script>
13304        function initRegisterModalForm6ab6cfd67accc() {
13305            return {
13306                defaultTitle: 'Create\u0020your\u0020account.',
13307                customTitle: null,
13308                showDescription: false,
13309                isInMainContent: false,
13310                errors: 0,
13311                hasCaptchaToken: 0,
13312                showPassword: false,
13313                showPasswordConfirm: false,
13314                isCreateAccountButtonDisabled: true,
13315                isLoading: false,
13316                isSubmitting: false,
13317                submitTimeout: null,
13318                captchaTimeout: null,
13319                displayErrorMessage: false,
13320                errorMessages: [],
13321                registrationError: false,
13322                updateContentBasedOnContext() {
13323                    // Check if form is inside #maincontent
13324                    const form = document.querySelector('#accountcreate\u002Dmodal6ab6cfd67accc');
13325                    this.isInMainContent = form && form.closest('#maincontent') !== null;
13326                    this.showDescription = this.isInMainContent;
13327                },
13328                getTitle() {
13329                    if (this.customTitle) {
13330                        return this.customTitle;
13331                    }
13332                    return this.isInMainContent ? 'Create\u0020New\u0020Customer\u0020Account' : this.defaultTitle;
13333                },
13334                getDescription() {
13335                    return this.isInMainContent ? 'If\u0020you\u0020have\u0020an\u0020account,\u0020sign\u0020in\u0020with\u0020your\u0020email\u0020address.' : '';
13336                },
13337                // Initialize Amasty captcha integration
13338                init() {
13339                    console.log('Register modal form initialized');
13340
13341                    // Add our form to Amasty's forms list after it's initialized
13342                    const addFormToAmasty = () => {
13343                        if (window.amRecaptchaModel && window.amRecaptchaModel.formsToProtect !== undefined) {
13344                            const currentForms = window.amRecaptchaModel.formsToProtect || '';
13345                            const ourFormSelector = '#accountcreate\u002Dmodal6ab6cfd67accc';
13346
13347                            if (!currentForms.includes(ourFormSelector)) {
13348                                window.amRecaptchaModel.formsToProtect = currentForms ?
13349                                    currentForms + ',' + ourFormSelector : ourFormSelector;
13350                                console.log('Added register form to Amasty protection:', window.amRecaptchaModel.formsToProtect);
13351                            }
13352
13353                            return true;
13354                        }
13355                        return false;
13356                    };
13357
13358                    // Try immediately and then keep trying
13359                    if (!addFormToAmasty()) {
13360                        const interval = setInterval(() => {
13361                            if (addFormToAmasty()) {
13362                                clearInterval(interval);
13363                            }
13364                        }, 100);
13365
13366                        // Stop trying after 5 seconds
13367                        setTimeout(() => clearInterval(interval), 5000);
13368                    }
13369
13370                    // Check what forms Amasty is configured to protect
13371                    setTimeout(() => {
13372                        if (window.amRecaptchaModel) {
13373                            console.log('Final Amasty forms to protect:', window.amRecaptchaModel.formsToProtect);
13374                            console.log('Our register form element:', this.$el.id);
13375                        }
13376                    }, 2000);
13377                },
13378
13379                // Amasty captcha methods
13380                amRecaptchaModelExecute($event) {
13381                    // Prevent multiple rapid executions
13382                    if (this.isLoading) {
13383                        console.log('Already processing captcha, ignoring duplicate call');
13384                        return;
13385                    }
13386
13387                    console.log('Register amRecaptchaModelExecute called');
13388                    this.isLoading = true;
13389
13390                    // Clear any existing timeout
13391                    if (this.captchaTimeout) {
13392                        clearTimeout(this.captchaTimeout);
13393                    }
13394
13395                    // Set a timeout to prevent infinite loading if captcha fails
13396                    this.captchaTimeout = setTimeout(() => {
13397                        if (this.isLoading) {
13398                            console.log('Register captcha timeout reached, submitting form anyway');
13399                            this.isLoading = false;
13400                            this.isSubmitting = false; // Reset submitting state
13401                            this.submitForm();
13402                        }
13403                    }, 10000); // 10 second timeout
13404
13405                    // Check if Amasty captcha is properly initialized
13406                    if (window.amRecaptchaModel && typeof window.amRecaptchaModel.execute === 'function') {
13407                        console.log('Calling Amasty execute method for register');
13408                        try {
13409                            window.amRecaptchaModel.execute($event);
13410                        } catch (error) {
13411                            console.error('Register captcha execution failed:', error);
13412                            this.isLoading = false;
13413                            this.isSubmitting = false; // Reset submitting state
13414                            this.submitForm();
13415                        }
13416                    } else {
13417                        console.log('Amasty not properly initialized, using fallback for register');
13418                        this.submitForm();
13419                    }
13420                },
13421
13422                amRecaptchaModelRecaptchaCallback($event, $el) {
13423                    console.log('REGISTER amRecaptchaModelRecaptchaCallback called - should submit form now', {
13424                        formId: 'accountcreate\u002Dmodal6ab6cfd67accc',
13425                        visible: $el ? $el.offsetParent !== null : 'unknown',
13426                        event: $event
13427                    });
13428
13429                    // Clear the timeout since captcha succeeded
13430                    if (this.captchaTimeout) {
13431                        clearTimeout(this.captchaTimeout);
13432                        this.captchaTimeout = null;
13433                    }
13434
13435                    // This callback means captcha validation passed, so submit the form
13436                    this.submitForm();
13437                },
13438
13439                amRecaptchaModelExpiredCallback($event, $el) {
13440                    console.log('Register amRecaptchaModelExpiredCallback called - captcha expired');
13441
13442                    // Clear the timeout and reset loading state
13443                    if (this.captchaTimeout) {
13444                        clearTimeout(this.captchaTimeout);
13445                        this.captchaTimeout = null;
13446                    }
13447
13448                    // Reset loading state and show error
13449                    this.isLoading = false;
13450                    this.isSubmitting = false;
13451
13452                    // Show user-friendly error message
13453                    window.dispatchMessages([{
13454                        type: 'error',
13455                        text: 'Security\u0020verification\u0020expired.\u0020Please\u0020try\u0020again.'
13456                    }], 5000);
13457
13458                    // Reset the form to allow retry
13459                    this.registrationError = false;
13460                    this.errorMessages = [];
13461                },
13462                submitForm() {
13463                    console.log('REGISTER submitForm called, formId:', 'accountcreate\u002Dmodal6ab6cfd67accc');
13464
13465                    // Bouncer: prevent multiple rapid submissions
13466                    if (this.isSubmitting) {
13467                        console.log('Register form already submitting, returning. isLoading:', this.isLoading, 'isSubmitting:', this.isSubmitting);
13468                        return;
13469                    }
13470
13471                    // Clear any existing timeouts
13472                    if (this.submitTimeout) {
13473                        clearTimeout(this.submitTimeout);
13474                    }
13475                    if (this.captchaTimeout) {
13476                        clearTimeout(this.captchaTimeout);
13477                        this.captchaTimeout = null;
13478                    }
13479
13480                    // Clear error state when submitting
13481                    this.registrationError = false;
13482                    this.errorMessages = [];
13483
13484                    // Set submitting state and timeout
13485                    this.isSubmitting = true;
13486                    this.submitTimeout = setTimeout(() => {
13487                        console.log('Register submit timeout reached, resetting isSubmitting');
13488                        this.isSubmitting = false;
13489                        // Also reset loading state as a safety measure
13490                        if (this.isLoading) {
13491                            console.log('Also resetting stuck isLoading state for register');
13492                            this.isLoading = false;
13493                        }
13494                    }, 15000); // 15 second timeout (longer to allow for network delays)
13495
13496                    const $form = document.querySelector('#accountcreate\u002Dmodal6ab6cfd67accc');
13497
13498                    if (this.errors === 0) {
13499                        this.isLoading = true;
13500
13501                        fetch('https://www.purdys.com/purdys-customer/AccountModal/Create/', {
13502                            method: 'POST',
13503                            body: new FormData($form)
13504                        })
13505                            .then(response => {
13506                                console.log('Response received:', response);
13507                                return response.json();
13508                            })
13509                            .then(data => {
13510                                console.log('Data received:', data);
13511                                if (data.success) {
13512                                    // Clear any error state on success
13513                                    this.registrationError = false;
13514                                    this.errorMessages = [];
13515
13516                                    const localStorage = window.localStorage;
13517                                    const cartData = localStorage.getItem('login_campaign_cart');
13518
13519                                    this.$dispatch('reload-customer-section-data');
13520                                    hyva.setCookie('isNewlyCreatedAccount', 1);
13521
13522                                    // Handle cart data if exists
13523                                    if (cartData) {
13524                                        window.localStorage.removeItem('login_campaign_cart');
13525
13526                                        const {product, campaign, qty = 1} = JSON.parse(cartData);
13527
13528                                        this.$dispatch('campaign-add-to-cart', {
13529                                            product,
13530                                            qty,
13531                                            campaign,
13532                                        });
13533                                    }
13534
13535                                    // Wait for session synchronization before redirect
13536                                    setTimeout(() => {
13537                                        // Force reload customer data sections to ensure session sync
13538                                        if (window.customerData) {
13539                                            window.customerData.reload(['customer', 'cart'], false);
13540                                        }
13541                                        
13542                                        // Small additional delay to ensure session is written
13543                                        setTimeout(() => {
13544                                            // Use location.replace to avoid back button issues and clear any form state
13545                                            window.location.replace('https://www.purdys.com/customer/account/?registered=1');
13546                                        }, 100);
13547                                    }, 300);
13548                                } else {
13549                                    console.log('Registration failed:', data.error);
13550
13551                                    // Show the error message in the form
13552                                    this.registrationError = true;
13553                                    this.errorMessages = [data.error || 'Registration\u0020failed.\u0020Please\u0020try\u0020again.'];
13554
13555                                    // Also show global message
13556                                    window.dispatchMessages([
13557                                        {
13558                                            type: 'error',
13559                                            text: data.error || 'Registration\u0020failed.\u0020Please\u0020try\u0020again.'
13560                                        }
13561                                    ], 10000);
13562                                }
13563                            })
13564                            .catch(error => {
13565                                console.error('Error submitting form:', error);
13566                                window.dispatchMessages([
13567                                    {
13568                                        type: 'error',
13569                                        text: 'Oops\u0020something\u0020went\u0020wrong,\u0020Please\u0020try\u0020again.'
13570                                    }
13571                                ], 10000);
13572                            })
13573                            .finally(() => {
13574                                this.isLoading = false;
13575                                this.isSubmitting = false;
13576                            });
13577                    } else {
13578                        console.log('Form validation failed with', this.errors, 'errors');
13579                        this.isLoading = false;
13580                    }
13581                },
13582                validate() {
13583                    return new Promise((resolve, reject) => {
13584                        this.errors = 0;
13585                        const formFields = document.querySelectorAll('#accountcreate\u002Dmodal6ab6cfd67accc input, #accountcreate\u002Dmodal6ab6cfd67accc select, #accountcreate\u002Dmodal6ab6cfd67accc textarea');
13586
13587                        formFields.forEach(field => {
13588                            // Clear previous custom validity
13589                            field.setCustomValidity('');
13590
13591                            // Manually trigger Hyva validation for fields with data-validate
13592                            const validateAttr = field.getAttribute('data-validate');
13593                            if (validateAttr && window.hyva && window.hyva.formValidation && window.hyva.formValidation.rules) {
13594                                try {
13595                                    const rules = JSON.parse(validateAttr);
13596                                    for (const [ruleName, options] of Object.entries(rules)) {
13597                                        if (window.hyva.formValidation.rules[ruleName]) {
13598                                            const result = window.hyva.formValidation.rules[ruleName](field.value, options, {element: field}, {});
13599                                            if (result !== true) {
13600                                                field.setCustomValidity(result);
13601                                                break;
13602                                            }
13603                                        }
13604                                    }
13605                                } catch (e) {
13606                                    console.warn('Error parsing validation rules for field:', field.name, e);
13607                                }
13608                            }
13609
13610                            if (!field.checkValidity()) {
13611                                this.errors++;
13612                            }
13613                        });
13614
13615                        this.isCreateAccountButtonDisabled = this.errors > 0;
13616                        if (this.errors === 0) {
13617                            resolve();
13618                        } else {
13619                            reject(formFields);
13620                        }
13621                    });
13622                },
13623                init() {
13624                    const formFields = document.querySelectorAll('#accountcreate\u002Dmodal6ab6cfd67accc input, #accountcreate\u002Dmodal6ab6cfd67accc select, #accountcreate\u002Dmodal6ab6cfd67accc textarea');
13625                    formFields.forEach(field => {
13626                        field.addEventListener('input', this.validate.bind(this));
13627                    });
13628                },
13629
13630                // Cleanup method to clear timeouts
13631                destroy() {
13632                    if (this.captchaTimeout) {
13633                        clearTimeout(this.captchaTimeout);
13634                        this.captchaTimeout = null;
13635                    }
13636                    if (this.submitTimeout) {
13637                        clearTimeout(this.submitTimeout);
13638                        this.submitTimeout = null;
13639                    }
13640                }
13641            }
13642        }
13643
13644        document.addEventListener('DOMContentLoaded', function () {
13645            const form = initRegisterModalForm6ab6cfd67accc();
13646            form.init();
13647        });
13648    </script>
13648
13649    
13650<script>
13651    'use strict';
13652    (() => {
13653        function _calculateStrength({elementID, valid}) {
13654            const password = document.getElementById(elementID),
13655                emailElm = document.getElementById('email_address');
13656            let displayScore;
13657            // Display score is based on combination of whether password is empty, valid, and zxcvbn strength
13658            if (!password || !password.value) {
13659                displayScore = 0;
13660            } else {
13661                // We should only perform this check in case there is an email field on screen
13662                if (emailElm && password.value && emailElm.value &&
13663                    password.value.toLowerCase() === emailElm.value.toLowerCase()) {
13664                    displayScore = 1;
13665                } else {
13666                    const zxcvbnScore = zxcvbn(password.value).score;
13667                    displayScore = valid && zxcvbnScore > 0 ? zxcvbnScore : 1;
13668                }
13669            }
13670
13671            _displayStrength(displayScore);
13672        }
13673
13674        function _displayStrength(displayScore) {
13675            let strengthLabel = '',
13676                className;
13677
13678            switch (displayScore) {
13679                case 0:
13680                    strengthLabel = "No\u0020Password";
13681                    className = 'password-none';
13682                    break;
13683
13684                case 1:
13685                    strengthLabel = "Weak";
13686                    className = 'password-weak';
13687                    break;
13688
13689                case 2:
13690                    strengthLabel = "Medium";
13691                    className = 'password-medium';
13692                    break;
13693
13694                case 3:
13695                    strengthLabel = "Strong";
13696                    className = 'password-strong';
13697                    break;
13698
13699                case 4:
13700                    strengthLabel = "Very\u0020Strong";
13701                    className = 'password-very-strong';
13702                    break;
13703            }
13704            const meterElm = document.getElementById('password-strength-meter-container'),
13705                meterLabelElm = document.getElementById('password-strength-meter-label');
13706            meterElm.className = '';
13707            meterElm.classList.add(className);
13708            meterLabelElm.textContent = strengthLabel;
13709        }
13710
13711        let loading = false;
13712        const callbacks = [];
13713
13714        function loadZxcvbn(cb) {
13715            callbacks.push(cb);
13716            if (loading) return;
13717            loading = true;
13718
13719            const script = document.createElement('script');
13720            script.type = 'text/javascript';
13721            script.src = 'https\u003A\u002F\u002Fwww.purdys.com\u002Fstatic\u002Fversion1790083580\u002Ffrontend\u002FPurdys2\u002Fhyva\u002Fen_US\u002Fjs\u002Fzxcvbn.js';
13722            script.async = true;
13723            script.onload = () => callbacks.forEach(cb => cb());
13724            document.head.appendChild(script);
13725        }
13726
13727        window.addEventListener('password-validate', function (evt) {
13728            const meterElm = document.getElementById('password-strength-meter-container'),
13729                meterLabelElm = document.getElementById('password-strength-meter-label');
13730            if (meterElm && meterLabelElm) {
13731                if (evt.detail && evt.detail.elementID) {
13732                    const cb = () => _calculateStrength(evt.detail);
13733                    window.zxcvbn ? cb() : loadZxcvbn(cb)
13734                }
13735            }
13736        });
13737
13738
13739        document.addEventListener('DOMContentLoaded', () => {
13740            hyva && hyva.formValidation && hyva.formValidation.addRule('password-strength', function(value, options, field, context) {
13741                let counter = 0;
13742                const minCharacterSets = options.minCharacterSets !== undefined ?  options.minCharacterSets : 1;
13743                if (value.match(/\d+/)) {
13744                    counter++;
13745                }
13746
13747                if (value.match(/[a-z]+/)) {
13748                    counter++;
13749                }
13750
13751                if (value.match(/[A-Z]+/)) {
13752                    counter++;
13753                }
13754
13755                if (value.match(/[^a-zA-Z0-9]+/)) {
13756                    counter++;
13757                }
13758
13759                queueMicrotask(() => {
13760                    window.dispatchEvent(new CustomEvent('password-validate', { detail: {
13761                            elementID: field.element.id || 'password',
13762                            valid: field.state.valid
13763                        }}));
13764                });
13765
13766                if (counter < minCharacterSets) {
13767                    const missing = minCharacterSets - counter;
13768                    return hyva.str('The\u0020password\u0020must\u0020include\u0020at\u0020least\u0020\u00251\u0020or\u0020more\u0020of\u003A\u0020uppercase\u0020\u0028A\u002DZ\u0029,\u0020lowercase\u0020\u0028a\u002Dz\u0029,\u0020number\u0020and\u0020symbol.', missing);
13769                }
13770                return true;
13771            });
13772        })
13773    })();
13774
13775</script>
13775
13776</div>
13777        <div class="text-center mt-4">
13778            <p>Already have an account?</p>
13779            <a href="#" class="underline" @click.prevent="setState('login')">
13780                <span class="text-base font-bold">Login now</span>
13781            </a>
13782        </div>
13783    </div>
13784    <div x-show="state === 'register-success'"
13785         @open-register-success-modal.window="setState('register-success', event.detail)">
13786        
13787<div class="flex gap-x-10">
13788    <img src="https&#x3A;&#x2F;&#x2F;www.purdys.com&#x2F;static&#x2F;version1790083580&#x2F;frontend&#x2F;Purdys2&#x2F;hyva&#x2F;en_US&#x2F;images&#x2F;register-success-img.png"
13789         class="hidden md:block h-[250px] w-[250px] lg:h-[390px] lg:w-[390px] rounded-lg"
13790         loading="lazy"
13791    >
13792    <div class="md:max-w-[250px] lg:max-w-[390px] flex flex-col gap-y-6 md:gap-y-10 items-center">
13793        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 98 98" fill="none" class="w-24 h-24" role="img">
13794    <path d="M31.75 50.9418L43.452 63L66.75 36" stroke="#B09FCC" stroke-width="8" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
13795    <path d="M49.0761 1C75.5483 1 97 22.6038 97 49.0761C97 75.5483 75.3962 97 48.9239 97C22.4517 97 1.15214 75.5483 1 49.0761C1 22.6038 22.4517 1 48.9239 1H49.0761Z" stroke="#532E91" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round"/>
13796<title>rounded-checkmark</title></svg>
13797        <legend>
13798            <h2 class="font-bold text-center !max-w-full">Your Purdys account has been created!</h2>
13799            <p class="font-bold text-center" x-show="requireEmailConfirmation">Please check your email</p>
13800        </legend>
13801        <button
13802            @click="showOrganizationModal && !requireEmailConfirmation ? setState('organization') : hide();"
13803            class="w-full btn btn-primary px-12 max-h-[44px] uppercase"
13804            x-html="requireEmailConfirmation ? 'close' : 'get started'"
13805        ></button>
13806    </div>
13807</div>
13808    </div>
13809    <div x-show="state === 'beta-redirect'"
13810         x-intersect.once="setTimeout(() => window.location.href = 'https://www.purdys.com/', 3500)"
13811         class="p-6 text-center">
13812        <h3>Our Winter Season will start soon! Come back on August 18th to start your fundraiser.</h3>
13813        <p class="m-4">In the meantime you will be redirected to shop at purdys.com</p>
13814    </div>
13815    <div x-show="state === 'organization'" class="min-h-[512px]">
13816        
13817<!-- Organization Modal Placeholder -->
13818<div class="organization-modal-content">
13819    <h2>Organization Setup</h2>
13820    <p>Organization modal content will be implemented here.</p>
13821</div> 
13822        <div class="text-center mt-6">
13823            <a href="https://www.purdys.com/customer/account/" class="underline">
13824                <span class="text-base font-bold">Go to my account</span>
13825            </a>
13826        </div>
13827    </div>
13828</div>
13829
13830<script>
13831    function authModalData() {
13832        return {
13833            isLoading: false,
13834            state: 'login',
13835            requireEmailConfirmation: false,
13836            initialTab: null,
13837            modalInitialized: false,
13838            async init() {
13839                try {
13840                    const newState = await this.initState();
13841                    this.state = newState;
13842                    this.modalInitialized = true;
13843                } catch (error) {
13844                    console.error('Error initializing auth modal:', error);
13845                    this.state = 'login';
13846                    this.modalInitialized = true;
13847                }
13848            },
13849            setInitialTab(tab) {
13850                this.initialTab = tab;
13851                if (tab && this.modalInitialized) {
13852                    this.setState(tab);
13853                } else if (tab) {
13854                    this.state = tab;
13855                }
13856            },
13857            async checkIfUserHasAccess() {
13858                try {
13859                    const response = await fetch(BASE_URL + 'purdys_gnfbeta/beta/checkIfUserHasAccess', {
13860                        headers: {accept: 'application/json'}
13861                    });
13862
13863                    const data = await response.json();
13864                    const {hasAccess} = data;
13865
13866                    return hasAccess ? 'organization' : 'beta-redirect';
13867                } catch (error) {
13868                    console.error('Error checking user access:', error);
13869                    return 'organization';
13870                }
13871            },
13872            async initState() {
13873                const loggedIn = false;
13874
13875                // If initial tab is set, use it for non-logged-in users
13876                if (!loggedIn && this.initialTab) {
13877                    return this.initialTab;
13878                }
13879
13880                if (loggedIn) {
13881                    if (localStorage.getItem('isBetaEnabled')) {
13882                        return await this.checkIfUserHasAccess();
13883                    } else {
13884                        return 'organization';
13885                    }
13886                } else {
13887                    return 'login';
13888                }
13889            },
13890            updateOrganizationFormKey() {
13891                const formKeyInput = document.querySelector('.organization-modal-content form input[name="form_key"]');
13892
13893                if (formKeyInput) {
13894                    formKeyInput.value = hyva.getFormKey();
13895                }
13896            },
13897            setIsLoading(isLoading) {
13898                this.isLoading = isLoading;
13899            },
13900            async setState(state, data = {}) {
13901                this.state = state;
13902
13903                if ((state === 'register' || state === 'forgotPassword') && data.email) {
13904                    const emailInputId = state.replace('P', '_p') + '_email_address';
13905                    const emailInput = document.getElementById(emailInputId);
13906                    if (emailInput) {
13907                        emailInput.value = data.email;
13908                    }
13909                }
13910
13911                if (state === 'organization') {
13912                    //to make sure that customer is in beta list
13913                    if (localStorage.isBetaEnabled) {
13914                        const newState = await this.checkIfUserHasAccess();
13915                        if (newState !== state) {
13916                            this.state = newState;
13917                            return;
13918                        }
13919                    }
13920
13921                    this.updateOrganizationFormKey();
13922                }
13923
13924                if (data.requireEmailConfirmation) {
13925                    this.requireEmailConfirmation = data.requireEmailConfirmation;
13926                }
13927
13928                if (data.showOrganizationModal) {
13929                    this.showOrganizationModal = data.showOrganizationModal;
13930                }
13931            }
13932        }
13933    }
13934</script>
13934
13935        </div>
13936    </div>
13937    </div>
13938
13939    <form action="recpatcha-holder"></form>
13940</div>
13941    
13941<script>
13942        const wpGA4ServerSide = {
13943            pushClick: function(productId, listId, listName, index, elm) {
13944                if (elm && elm.hasAttribute('onclick')) {
13945                    var requestUrl = 'https://www.purdys.com/weltpixel_ga4/track/productclick/';
13946                    if (productId && listId && listName) {
13947                        fetch(requestUrl, {
13948                            method: 'POST',
13949                            headers: {
13950                                'Content-Type': 'application/x-www-form-urlencoded',
13951                                'X-Requested-With': 'XMLHttpRequest'
13952                            },
13953                            body: 'product_id=' + productId + '&list_id=' + listId +'&list_name=' + listName + '&index=' + index
13954                        })
13955                        .then(res => res.json())
13956                        .then(data => {
13957                        });
13958                    }
13959                }
13960            },
13961
13962            pushViewItemList: function(hashId) {
13963                if (hashId && document.getElementById('wp_ga4_server_side_view_item_list')) {
13964                    var requestUrl = 'https://www.purdys.com/weltpixel_ga4/track/viewitemlist/';
13965                    fetch(requestUrl, {
13966                        method: 'POST',
13967                        headers: {
13968                            'Content-Type': 'application/x-www-form-urlencoded',
13969                            'X-Requested-With': 'XMLHttpRequest'
13970                        },
13971
13972                        body: 'hash_id='+hashId
13973                    })
13974                    .then(res => res.json())
13975                    .then(data => {
13976                    });
13977                }
13978            }
13979        };
13980
13981        window.wpGA4ServerSide = wpGA4ServerSide;
13982
13983        let allowGa4Services = window.ga4AllowServices ?? true;
13984
13985        if (allowGa4Services) {
13986            let selectedShippingMethod = '';
13987            let selectedPaymentMethod = '';
13988
13989            const {fetch: originalFetch} = window;
13990            window.fetch = async (...args) => {
13991                let [resource, config] = args;
13992                let response = await originalFetch(resource, config);
13993                let ajaxContentBody = false;
13994
13995                if ((typeof resource == 'string') &&
13996                    ((resource.search('post/livewire/message/checkout.shipping.methods') > 0) || (resource.search('post/livewire/message/checkout.payment.methods') > 0))) {
13997                    var jsonBody = false;
13998                    if (config.body) {
13999                        try {
14000                            jsonBody = JSON.parse(config.body);
14001                        } catch (e) {}
14002                    }
14003
14004                    if (jsonBody && jsonBody.updates && jsonBody.updates[0] && jsonBody.updates[0].payload && jsonBody.updates[0].payload.value) {
14005                        if (resource.search('checkout.shipping.methods') > 0) {
14006                            if (selectedShippingMethod != jsonBody.updates[0].payload.value) {
14007                                selectedShippingMethod = jsonBody.updates[0].payload.value;
14008                                ajaxContentBody = 'step=1&option=' + selectedShippingMethod;
14009                            }
14010                        }
14011                        if (resource.search('checkout.payment.methods') > 0) {
14012                            if (selectedPaymentMethod != jsonBody.updates[0].payload.value) {
14013                                selectedPaymentMethod = jsonBody.updates[0].payload.value;
14014                                ajaxContentBody = 'step=2&option=' + selectedPaymentMethod;
14015                            }
14016                        }
14017
14018                        if (ajaxContentBody) {
14019                                fetch('https://www.purdys.com/weltpixel_ga4/track/hyva/', {
14020                                    method: 'POST',
14021                                    headers: {
14022                                        'Content-Type': 'application/x-www-form-urlencoded',
14023                                        'X-Requested-With': 'XMLHttpRequest'
14024                                    },
14025                                    body: ajaxContentBody
14026                                })
14027                                    .then(res => res.json())
14028                                    .then(data => {
14029                                        if (data) {
14030                                            window.dataLayer.push({ecommerce: null});
14031                                            window.dataLayer.push(data);
14032                                        }
14033                                    });
14034                        }
14035                    }
14036                }
14037
14038                if ((typeof resource == 'string') && resource.search('/customer\/section\/load/') > 0) {
14039                    response.clone().json().then(data => {
14040                        if (data?.wp_ga4?.datalayer) {
14041                            const dataLayerData = JSON.parse(data.wp_ga4.datalayer);
14042                            dataLayerData.forEach((dataLayerItem) => {
14043                                window.dataLayer.push({ecommerce: null});
14044                                window.dataLayer.push(dataLayerItem);
14045                            });
14046                        }
14047                    });
14048                }
14049                return response;
14050            };
14051        }
14052
14053    </script>
vendor: 1 bytes, line 14053
14053
14054<script type="text/javascript">window.NREUM||(NREUM={});NREUM.info={"beacon":"bam.nr-data.net","licenseKey":"NRJS-8c25a1a7b460fa8b963","applicationID":"1118134761","transactionName":"ZwcBNxNUDRIEAkRRDl5NIgAVXAwPSgJFSxVfDwYRTlQAAgoUXkxOXA0ECg8=","queueTime":0,"applicationTime":833,"atts":"S0ACQVtOHhw=","errorBeacon":"bam.nr-data.net","agent":""}</script>
14054</body>
14055</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.