1"use strict";class EventBus{constructor(){this.events=new Map}on(event,callback){return this.events.has(event)||this.events.set(event,new Set),this.events.get(event).add(callback),()=>this.off(event,callback)}once(event,callback){const unsubscribe=this.on(event,(...args)=>{unsubscribe(),callback(...args)});return unsubscribe}off(event,callback){this.events.has(event)&&(this.events.get(event).delete(callback),this.events.get(event).size===0&&this.events.delete(event))}emit(event,...args){this.events.has(event)&&this.events.get(event).forEach(callback=>{try{callback(...args)}catch(error){console.error(`Error in event handler for "${event}":`,error)}})}clear(){this.events.clear()}getEventNames(){return Array.from(this.events.keys())}getListenerCount(event){return this.events.has(event)?this.events.get(event).size:0}}window.EventBus=EventBus;function ready(callback){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",callback):callback()}function debounce(func,wait,immediate=!1){let timeout;return function(...args){const later=()=>{timeout=null,immediate||func(...args)},callNow=immediate&&!timeout;clearTimeout(timeout),timeout=setTimeout(later,wait),callNow&&func(...args)}}function throttle(func,limit){let inThrottle;return function(...args){inThrottle||(func.apply(this,args),inThrottle=!0,setTimeout(()=>inThrottle=!1,limit))}}function $(selector,context=document){return context.querySelector(selector)}function $$(selector,context=document){return context.querySelectorAll(selector)}function on(target,event,handler,delegate){const element=typeof target=="string"?$(target):target;element&&(delegate?element.addEventListener(event,e=>{e.target.matches(delegate)&&handler.call(e.target,e)}):element.addEventListener(event,handler))}function off(target,event,handler){const element=typeof target=="string"?$(target):target;element&&element.removeEventListener(event,handler)}function matches(element,selector){return element.matches(selector)}function closest(element,selector){return element.closest(selector)}function addClass(target,className){const element=typeof target=="string"?$(target):target;element&&element.classList.add(className)}function removeClass(target,className){const element=typeof target=="string"?$(target):target;element&&element.classList.remove(className)}function toggleClass(target,className){const element=typeof target=="string"?$(target):target;return element?element.classList.toggle(className):!1}function hasClass(target,className){const element=typeof target=="string"?$(target):target;return element?element.classList.contains(className):!1}function attr(target,name,value){const element=typeof target=="string"?$(target):target;if(!element)return null;if(value!==void 0)element.setAttribute(name,value);else return element.getAttribute(name)}function removeAttr(target,name){const element=typeof target=="string"?$(target):target;element&&element.removeAttribute(name)}function data(target,name,value){return attr(target,`data-${name}`,value)}function createElement(tag,attributes={},content=""){const element=document.createElement(tag);return Object.entries(attributes).forEach(([key,value])=>{element.setAttribute(key,value)}),typeof content=="string"?element.textContent=content:content instanceof Element&&element.appendChild(content),element}function isMobile(){return window.innerWidth<768}function isTablet(){return window.innerWidth>=768&&window.innerWidth<1024}function isDesktop(){return window.innerWidth>=1024}function getViewport(){return{width:window.innerWidth,height:window.innerHeight}}function scrollToElement(target,options={}){const element=typeof target=="string"?$(target):target;element&&element.scrollIntoView({behavior:"smooth",block:"start",...options})}function waitForElementStability(element,timeout=3e3){return new Promise(resolve=>{let lastHeight=element.offsetHeight,lastTop=element.getBoundingClientRect().top,stableCount=0;const requiredStableChecks=3,checkInterval=100;let totalWaitTime=0;const checkStability=setInterval(()=>{const currentHeight=element.offsetHeight,currentTop=element.getBoundingClientRect().top;currentHeight===lastHeight&&Math.abs(currentTop-lastTop)<1?(stableCount++,stableCount>=requiredStableChecks&&(clearInterval(checkStability),resolve(!0))):(stableCount=0,lastHeight=currentHeight,lastTop=currentTop),totalWaitTime+=checkInterval,totalWaitTime>=timeout&&(clearInterval(checkStability),console.warn("waitForElementStability: Timeout reached, proceeding anyway"),resolve(!1))},checkInterval)})}function scrollToWithOffset(target,offset=-20,options={}){return new Promise(async resolve=>{const element=typeof target=="string"?$(target):target;if(!element){console.warn("scrollToWithOffset: Target element not found",target),resolve(!1);return}const{updateHash=!1,focus=!0,waitForStability=!0,stabilityTimeout=3e3}=options;waitForStability&&(console.log("\u23F3 Waiting for element stability before scrolling..."),await waitForElementStability(element,stabilityTimeout),console.log("\u2705 Element is stable, scrolling now"));const offsetPosition=element.getBoundingClientRect().top+window.pageYOffset+offset;window.scrollTo({top:offsetPosition,behavior:"smooth"}),setTimeout(()=>
1{if(updateHash&&element.id&&history.pushState(null,null,`#${element.id}`),focus){const originalTabIndex=element.getAttribute("tabindex"),hadTabIndex=element.hasAttribute("tabindex");hadTabIndex||element.setAttribute("tabindex","-1"),element.focus({preventScroll:!0}),hadTabIndex?originalTabIndex!==null&&element.setAttribute("tabindex",originalTabIndex):element.removeAttribute("tabindex")}resolve(!0)},600)})}function initSmoothAnchorScrolling(config={}){const{offset=-20,selector='a[href*="#"]',updateHash=!0,initialLoadDelay=500,stabilityTimeout=3e3,onScroll=null}=config;document.addEventListener("click",e=>{const link=e.target.closest(selector);if(!link)return;const href=link.getAttribute("href");if(!href||href==="#")return;const url=new URL(href,window.location.href);if(url.pathname!==window.location.pathname||!url.hash)return;const targetId=url.hash.slice(1),targetElement=document.getElementById(targetId);if(!targetElement)return;e.preventDefault();const customOffset=link.getAttribute("data-scroll-offset"),scrollOffset=customOffset?parseInt(customOffset,10):offset;scrollToWithOffset(targetElement,scrollOffset,{updateHash,focus:!0,waitForStability:!0,stabilityTimeout}).then(success=>{success&&onScroll&&onScroll(targetElement,link)})});const originalHash=window.__smoothScrollHash||window.location.hash;if(console.log("\u{1F50D} [INIT] Checking for hash..."),console.log("\u{1F50D} [INIT] window.__smoothScrollHash:",window.__smoothScrollHash),console.log("\u{1F50D} [INIT] window.location.hash:",window.location.hash),console.log("\u{1F50D} [INIT] originalHash:",originalHash),originalHash){const targetId=originalHash.slice(1);console.log("\u{1F517} [INIT] Processing stored hash:",originalHash),console.log("\u{1F517} [INIT] Target ID:",targetId),ready(()=>{console.log("\u{1F4C4} [READY] DOM is ready, looking for element:",targetId);const targetElement=document.getElementById(targetId);if(targetElement){console.log("\u2705 [READY] Target element found:",targetElement);const scrollToTarget=()=>{console.log("\u{1F310} [LOAD] Window loaded, waiting",initialLoadDelay,"ms before scrolling"),setTimeout(()=>{console.log("\u{1F4CD} [SCROLL] Starting scroll to target element:",targetId),document.documentElement.style.scrollBehavior="",scrollToWithOffset(targetElement,offset,{updateHash:!1,focus:!0,waitForStability:!0,stabilityTimeout}).then(success=>{success?(history.replaceState(null,null,originalHash),console.log("\u2705 [COMPLETE] Scroll complete, hash restored:",originalHash)):console.warn("\u26A0\uFE0F [COMPLETE] Scroll completed with warnings"),delete window.__smoothScrollHash,delete window.__smoothScrollPrevented})},initialLoadDelay)};document.readyState==="complete"?(console.log("\u26A1 [READY] Page already loaded, scrolling now"),scrollToTarget()):(console.log("\u23F3 [READY] Waiting for window.load event"),window.addEventListener("load",scrollToTarget))}else console.error("\u274C [READY] Target element not found:",targetId),console.log("\u{1F50D} [DEBUG] Available elements with IDs:",Array.from(document.querySelectorAll("[id]")).map(el=>el.id).slice(0,20)),originalHash&&history.replaceState(null,null,originalHash),document.documentElement.style.scrollBehavior="",delete window.__smoothScrollHash,delete window.__smoothScrollPrevented})}else console.log("\u2139\uFE0F [INIT] No hash to process");console.log("\u2728 Smooth anchor scrolling initialized with offset:",offset)}function formatMoney(cents,format="${{amount}}"){typeof cents=="string"&&(cents=cents.replace(".",""));const value=(cents/100).toFixed(2);return format.replace("{{amount}}",value).replace("{{amount_no_decimals}}",Math.floor(cents/100)).replace("{{amount_with_comma_separator}}",value.replace(".",","))}function observeIntersection(element,callback,options={}){const defaultOptions={root:null,rootMargin:"50px",threshold:.1},observer=new IntersectionObserver(entries=>{entries.forEach(entry=>{entry.isIntersecting&&(callback(entry.target),observer.unobserve(entry.target))})},{...defaultOptions,...options});return observer.observe(element),observer}function preloadResource(href,as,type=null){const link=document.createElement("link");link.rel="preload",link.href=href,link.as=as,type&&(link.type=type),document.head.appendChild(link)}function prefetchResource(href){const link=document.createElement("link");link.rel="prefetch",link.href=href,document.head.appendChild(link)}class WebVitals{constructor(){this.metrics=new Map,this.init()}init(){this.observeLCP(),this.observeFID(),this.observeCLS()}observeLCP(){"PerformanceObserver"in window&&new PerformanceObserver(list=>{const entries=list.getEntries(),lastEntry=entries[entries.length-1];this.metrics.set("LCP",lastEntry.startTime)}).observe({entryTypes:["largest-contentful-paint"]})}observeFID(){"PerformanceObserver"in window&&new PerformanceObserver(list=>
1{list.getEntries().forEach(entry=>{this.metrics.set("FID",entry.processingStart-entry.startTime)})}).observe({entryTypes:["first-input"]})}observeCLS(){if("PerformanceObserver"in window){let clsValue=0;new PerformanceObserver(list=>{list.getEntries().forEach(entry=>{entry.hadRecentInput||(clsValue+=entry.value,this.metrics.set("CLS",clsValue))})}).observe({entryTypes:["layout-shift"]})}}getMetrics(){return Object.fromEntries(this.metrics)}}class ResourceHints{static preconnect(origin){const link=document.createElement("link");link.rel="preconnect",link.href=origin,link.crossOrigin="anonymous",document.head.appendChild(link)}static dnsPrefetch(origin){const link=document.createElement("link");link.rel="dns-prefetch",link.href=origin,document.head.appendChild(link)}static modulePreload(href){const link=document.createElement("link");link.rel="modulepreload",link.href=href,document.head.appendChild(link)}}function loadCriticalCSS(href){const link=document.createElement("link");link.rel="stylesheet",link.href=href,link.media="print",link.onload=function(){this.media="all"},document.head.appendChild(link)}function lazyLoadImages(selector="img[data-src]"){const images=document.querySelectorAll(selector);"loading"in HTMLImageElement.prototype?images.forEach(img=>{img.src=img.dataset.src,img.removeAttribute("data-src")}):images.forEach(img=>{observeIntersection(img,target=>{target.src=target.dataset.src,target.removeAttribute("data-src"),target.classList.add("loaded")})})}class PerformanceBudget{constructor(budgets={}){this.budgets={lcp:2500,fid:100,cls:.1,...budgets}}check(metrics){const violations=[];return Object.entries(this.budgets).forEach(([metric,budget])=>{metrics[metric]&&metrics[metric]>budget&&violations.push({metric,value:metrics[metric],budget,exceeded:metrics[metric]-budget})}),violations}}function initPerformanceMonitoring(){const webVitals=new WebVitals,budget=new PerformanceBudget;ResourceHints.preconnect("https://cdn.shopify.com"),ResourceHints.dnsPrefetch("https://fonts.googleapis.com"),window.addEventListener("load",()=>{setTimeout(()=>{const metrics=webVitals.getMetrics(),violations=budget.check(metrics);violations.length>0&&console.warn("Performance budget violations:",violations),window.gtag&&Object.entries(metrics).forEach(([metric,value])=>{window.gtag("event","web_vitals",{metric_name:metric,metric_value:Math.round(value),custom_parameter:"custom_value"})})},1e3)})}class AgeGateManager{constructor(options={}){this.config={storageKey:"theme:age-verified",sessionKey:"session:age-verified",modalId:"age-gate-modal",minAge:18,cookieDays:30,declineUrl:"https://www.google.com",enabled:!0,...options},this.modal=null,this.isVerified=!1,this.init()}init(){if(console.log("\u{1F51E} Age Gate Manager initializing..."),this.modal=document.getElementById(this.config.modalId),!this.modal){console.warn("Age Gate: Modal element not found");return}if(this.readConfigFromModal(),!this.config.enabled){console.log("Age Gate: Disabled via settings");return}if(this.checkVerification()){console.log("\u2705 Age Gate: User already verified"),this.isVerified=!0;return}this.showModal(),this.bindEvents(),console.log("\u2705 Age Gate Manager initialized")}readConfigFromModal(){if(!this.modal)return;const minAge=this.modal.getAttribute("data-min-age"),cookieDays=this.modal.getAttribute("data-cookie-days"),declineUrl=this.modal.getAttribute("data-decline-url");minAge&&(this.config.minAge=parseInt(minAge)),cookieDays&&(this.config.cookieDays=parseInt(cookieDays)),declineUrl&&(this.config.declineUrl=declineUrl)}bindEvents(){if(!this.modal)return;const confirmBtn=this.modal.querySelector("[data-age-gate-confirm]");confirmBtn&&confirmBtn.addEventListener("click",()=>this.handleConfirm());const declineBtn=this.modal.querySelector("[data-age-gate-decline]");declineBtn&&declineBtn.addEventListener("click",()=>this.handleDecline());const overlay=this.modal.querySelector(".modal__overlay");overlay&&overlay.addEventListener("click",e=>{e.stopPropagation(),e.preventDefault()}),this.escapeHandler=e=>{e.key==="Escape"&&this.modal.hasAttribute("open")&&(e.stopPropagation(),e.preventDefault())},document.addEventListener("keydown",this.escapeHandler,!0)}showModal(){this.modal&&(document.documentElement.classList.add("lock-all"),this.modal.setAttribute("open",""),this.modal.open!==void 0&&(this.modal.open=!0),this.emitEvent("show"))}hideModal(){this.modal&&(document.documentElement.classList.remove("lock-all"),this.modal.removeAttribute("open"),this.modal.open!==void 0&&(this.modal.open=!1),this.escapeHandler&&document.removeEventListener("keydown",this.escapeHandler,!0),this.emitEvent("hide"))}handleConfirm(){console.log("\u2705 Age Gate: User confirmed age"),this.setVerified(),this.isVerified=!0,this.hideModal(),this.emitEvent("verified",{age:this.config.minAge,timestamp:new Date().getTime()})}handleDecline(){console.log("\u274C Age Gate: User declined age verification"),this.emitEvent("declined",{age:this.config.minAge,redirectUrl:this.config.declineUrl}),setTimeout(()=>{window.location.href=this.config.declineUrl},300)}checkVerification(){return!!(this.checkLocalStorage()||this.checkSessionStorage())}checkLocalStorage(){try{const stored=localStorage.getItem(this.config.storageKey);if(!stored)return!1;const data2=JSON.parse(stored),now=new Date().getTime();return data2.verified&&data2.expires&&data2.expires>now?!0:(localStorage.removeItem(this.config.storageKey),!1)}catch(e){return console.warn("Age Gate: localStorage not available",e),!1}}checkSessionStorage(){try{return sessionStorage.getItem(this.config.sessionKey)==="true"}catch(e){return console.warn("Age Gate: sessionStorage not available",e),!1}}setVerified(){const now=new Date().getTime(),expires=now+this.config.cookieDays*24*60*60*1e3,data2={verified:!0,timestamp:now,expires,minAge:this.config.minAge};try{localStorage.setItem(this.config.storageKey,JSON.stringify(data2))}catch(e){console.warn("Age Gate: Could not save to localStorage, using sessionStorage",e);
1try{sessionStorage.setItem(this.config.sessionKey,"true")}catch(e2){console.error("Age Gate: Could not save verification",e2)}}}clearVerification(){try{localStorage.removeItem(this.config.storageKey),sessionStorage.removeItem(this.config.sessionKey),console.log("\u{1F9F9} Age Gate: Verification cleared")}catch(e){console.warn("Age Gate: Could not clear verification",e)}}emitEvent(eventName,detail={}){document.dispatchEvent(new CustomEvent(`age-gate:${eventName}`,{detail:{...detail,manager:this}}))}getStatus(){return{isVerified:this.isVerified,minAge:this.config.minAge,cookieDays:this.config.cookieDays,enabled:this.config.enabled}}}window.AgeGateManager=AgeGateManager;class ColorSystem{constructor(){this.settings=window.CustomThemeSettings||{},this.colors=this.settings.colors||{},this.features=this.settings.features||{},this.contrastRatios={AA_NORMAL:4.5,AA_LARGE:3,AAA_NORMAL:7,AAA_LARGE:4.5},this.init()}init(){console.log("\u{1F3A8} Color System initializing..."),this.features.livePreview&&this.initLivePreview(),this.features.contrastChecker&&this.initContrastChecker(),this.features.colorPaletteGenerator!=="disabled"&&this.generateColorPalette(this.features.colorPaletteGenerator),this.features.accessibilityMode&&this.enableAccessibilityMode(),this.bindEvents(),console.log("\u2705 Color System initialized")}initLivePreview(){window.Shopify&&window.Shopify.designMode&&(document.addEventListener("shopify:section:load",()=>{this.updateColorsFromSettings()}),document.addEventListener("shopify:section:unload",()=>{this.updateColorsFromSettings()}))}updateColorsFromSettings(){const newColors=(window.CustomThemeSettings||{}).colors||{};Object.entries(newColors).forEach(([key,value])=>{const cssVar=`--color-custom-${this.camelToKebab(key)}`;document.documentElement.style.setProperty(cssVar,value)}),this.colors=newColors,document.dispatchEvent(new CustomEvent("colorSystem:updated",{detail:{colors:newColors}}))}initContrastChecker(){this.checkAllContrasts(),document.addEventListener("colorSystem:updated",()=>{this.checkAllContrasts()})}checkAllContrasts(){const results=[];return results.push(this.checkContrast(this.colors.primary,"#ffffff","Primary on White")),results.push(this.checkContrast(this.colors.primary,"#000000","Primary on Black")),results.push(this.checkContrast(this.colors.success,"#ffffff","Success on White")),results.push(this.checkContrast(this.colors.error,"#ffffff","Error on White")),results.push(this.checkContrast(this.colors.warning,"#000000","Warning on Black")),window.Shopify&&window.Shopify.designMode&&(console.group("\u{1F50D} Contrast Check Results"),results.forEach(result=>{const icon=result.passes.AA?"\u2705":"\u274C";console.log(`${icon} ${result.label}: ${result.ratio.toFixed(2)}:1`)}),console.groupEnd()),results}checkContrast(color1,color2,label=""){const ratio=this.calculateContrastRatio(color1,color2);return{label,ratio,passes:{AA:ratio>=this.contrastRatios.AA_NORMAL,AAA:ratio>=this.contrastRatios.AAA_NORMAL,AA_LARGE:ratio>=this.contrastRatios.AA_LARGE,AAA_LARGE:ratio>=this.contrastRatios.AAA_LARGE}}}calculateContrastRatio(color1,color2){const lum1=this.getLuminance(color1),lum2=this.getLuminance(color2),brightest=Math.max(lum1,lum2),darkest=Math.min(lum1,lum2);return(brightest+.05)/(darkest+.05)}getLuminance(color){const rgb=this.hexToRgb(color);if(!rgb)return 0;const[r,g,b]=[rgb.r,rgb.g,rgb.b].map(c=>(c=c/255,c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4)));return .2126*r+.7152*g+.0722*b}generateColorPalette(type){const primaryHsl=this.hexToHsl(this.colors.primary);if(!primaryHsl)return;let palette=[];switch(type){case"monochromatic":palette=this.generateMonochromaticPalette(primaryHsl);break;case"analogous":palette=this.generateAnalogousPalette(primaryHsl);break;case"complementary":palette=this.generateComplementaryPalette(primaryHsl);break;case"triadic":palette=this.generateTriadicPalette(primaryHsl);break;case"tetradic":palette=this.generateTetradicPalette(primaryHsl);break}return this.applyGeneratedPalette(palette),palette}generateMonochromaticPalette(hsl){const{h,s,l}=hsl;return[this.hslToHex({h,s,l:Math.max(0,l-.3)}),this.hslToHex({h,s,l:Math.max(0,l-.15)}),this.hslToHex({h,s,l}),this.hslToHex({h,s,l:Math.min(1,l+.15)}),this.hslToHex({h,s,l:Math.min(1,l+.3)})]}
1generateAnalogousPalette(hsl){const{h,s,l}=hsl;return[this.hslToHex({h:(h-60+360)%360,s,l}),this.hslToHex({h:(h-30+360)%360,s,l}),this.hslToHex({h,s,l}),this.hslToHex({h:(h+30)%360,s,l}),this.hslToHex({h:(h+60)%360,s,l})]}generateComplementaryPalette(hsl){const{h,s,l}=hsl,complementary=(h+180)%360;return[this.hslToHex({h,s,l}),this.hslToHex({h:complementary,s,l}),this.hslToHex({h,s:s*.7,l:l*1.2}),this.hslToHex({h:complementary,s:s*.7,l:l*1.2}),this.hslToHex({h,s:s*.5,l:l*.8})]}generateTriadicPalette(hsl){const{h,s,l}=hsl;return[this.hslToHex({h,s,l}),this.hslToHex({h:(h+120)%360,s,l}),this.hslToHex({h:(h+240)%360,s,l}),this.hslToHex({h,s:s*.7,l:l*1.1}),this.hslToHex({h:(h+120)%360,s:s*.7,l:l*1.1})]}generateTetradicPalette(hsl){const{h,s,l}=hsl;return[this.hslToHex({h,s,l}),this.hslToHex({h:(h+90)%360,s,l}),this.hslToHex({h:(h+180)%360,s,l}),this.hslToHex({h:(h+270)%360,s,l}),this.hslToHex({h,s:s*.6,l:l*1.15})]}applyGeneratedPalette(palette){palette.length>=3&&(this.updateColor("secondary",palette[1]),this.updateColor("accent",palette[2]),palette.length>=5&&(this.updateColor("surface",palette[3]),this.updateColor("neutralLight",palette[4])))}updateColor(colorName,hexValue){const cssVar=`--color-custom-${this.camelToKebab(colorName)}`;document.documentElement.style.setProperty(cssVar,hexValue),this.colors[colorName]=hexValue}enableAccessibilityMode(){document.documentElement.classList.add("accessibility-mode"),this.enhanceContrast(),this.enhanceFocusIndicators()}enhanceContrast(){const enhancedColors={};Object.entries(this.colors).forEach(([key,value])=>{const hsl=this.hexToHsl(value);hsl&&(hsl.s=Math.min(1,hsl.s*1.2),hsl.l=hsl.l>.5?Math.min(1,hsl.l*1.1):Math.max(0,hsl.l*.8),enhancedColors[key]=this.hslToHex(hsl))}),Object.entries(enhancedColors).forEach(([key,value])=>{this.updateColor(key,value)})}enhanceFocusIndicators(){const style=document.createElement("style");style.textContent=` 2 .accessibility-mode *:focus { 3 outline: 3px solid var(--color-custom-primary) !important; 4 outline-offset: 2px !important; 5 } 6 7 .accessibility-mode button:focus, 8 .accessibility-mode a:focus, 9 .accessibility-mode input:focus, 10 .accessibility-mode select:focus, 11 .accessibility-mode textarea:focus { 12 box-shadow: 0 0 0 3px var(--color-custom-primary) !important; 13 } 14 `,document.head.appendChild(style)}bindEvents(){document.addEventListener("custom-theme:settings-loaded",e=>{this.settings=e.detail,this.colors=this.settings.colors||{},this.features=this.settings.features||{}})}camelToKebab(str){return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase()}hexToRgb(hex){const result=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);return result?{r:parseInt(result[1],16),g:parseInt(result[2],16),b:parseInt(result[3],16)}:null}hexToHsl(hex){const rgb=this.hexToRgb(hex);if(!rgb)return null;const r=rgb.r/255,g=rgb.g/255,b=rgb.b/255,max=Math.max(r,g,b),min=Math.min(r,g,b);let h,s,l=(max+min)/2;if(max===min)h=s=0;else{const d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s,l}}hslToHex({h,s,l}){h=h/360;const hue2rgb=(p,q,t)=>(t<0&&(t+=1),t>1&&(t-=1),t<1/6?p+(q-p)*6*t:t<1/2?q:t<2/3?p+(q-p)*(2/3-t)*6:p);let r,g,b;if(s===0)r=g=b=l;else{const q=l<.5?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}const toHex=c=>{const hex=Math.round(c*255).toString(16);return hex.length===1?"0"+hex:hex};return`#${toHex(r)}${toHex(g)}${toHex(b)}`}}window.ColorSystem=ColorSystem;class FormValidator{constructor(){this.forms=new Map,this.rules=new Map,this.init()}init(){this.setupDefaultRules(),this.bindEvents(),this.initializeForms(),console.log("\u2705 Form Validator initialized")}setupDefaultRules(){this.addRule("required",value=>value.trim().length>0,"This field is required"),this.addRule("email",value=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),"Please enter a valid email address"),this.addRule("min",(value,param)=>value.length>=parseInt(param),"Must be at least {param} characters"),this.addRule("max",(value,param)=>value.length<=parseInt(param),"Must be no more than {param} characters"),this.addRule("pattern",(value,param)=>new RegExp(param).test(value),"Please match the required format"),this.addRule("match",(value,param,form)=>{const matchField=form.querySelector(`[name="${param}"]`);return matchField?value===matchField.value:!1},"Fields do not match")}bindEvents(){document.addEventListener("submit",e=>{e.target.matches("[data-validate]")&&(this.validateForm(e.target)||e.preventDefault())}),document.addEventListener("blur",e=>{e.target.matches("[data-rules]")&&this.validateField(e.target)},!0),document.addEventListener("input",e=>{e.target.matches("[data-rules]")&&hasClass(e.target,"is-invalid")&&this.validateField(e.target)})}initializeForms(){$$("[data-validate]").forEach(form=>{this.initializeForm(form)})}initializeForm(form){const formId=form.id||`form-${Date.now()}`;form.id||(form.id=formId),this.forms.set(formId,{element:form,fields:new Map}),$$("[data-rules]",form).forEach(field=>{this.initializeField(field,formId)})}initializeField(field,formId){const fieldName=field.name||field.id,rules=data(field,"rules").split("|"),formData=this.forms.get(formId);formData&&formData.fields.set(fieldName,{element:field,rules})}addRule(name,validator,message){this.rules.set(name,{validator,message})}validateForm(form){const formId=form.id,formData=this.forms.get(formId);if(!formData)return this.initializeForm(form),this.validateForm(form);let isValid=!0;return formData.fields.forEach(fieldData=>{this.validateField(fieldData.element)||(isValid=!1)}),document.dispatchEvent(new CustomEvent("form:validate",{detail:{form,isValid}})),isValid}validateField(field){const rules=data(field,"rules");if(!rules)return!0;const value=field.value,ruleList=rules.split("|"),form=field.closest("form");let isValid=!0,errorMessage="";for(const ruleString of ruleList){const[ruleName,param]=ruleString.split(":"),rule=this.rules.get(ruleName);if(rule&&!rule.validator(value,param,form)){isValid=!1,errorMessage=rule.message.replace("{param}",param);break}}return this.updateFieldState(field,isValid,errorMessage),document.dispatchEvent(new CustomEvent("field:validate",{detail:{field,isValid,errorMessage}})),isValid}updateFieldState(field,isValid,errorMessage){const formGroup=field.closest(".form-group")||field.parentElement;isValid?(removeClass(field,"is-invalid"),addClass(field,"is-valid"),removeClass(formGroup,"has-error")):(removeClass(field,"is-valid"),addClass(field,"is-invalid"),addClass(formGroup,"has-error")),this.updateErrorMessage(field,errorMessage)}updateErrorMessage(field,message){const formGroup=field.closest(".form-group")||field.parentElement;let feedback=formGroup.querySelector(".form-feedback");feedback||(feedback=document.createElement("div"),feedback.className="form-feedback",formGroup.appendChild(feedback)),message?(feedback.textContent=message,addClass(feedback,"is-invalid"),removeClass(feedback,"is-valid")):(feedback.textContent="",removeClass(feedback,"is-invalid"),addClass(feedback,"is-valid"))}clearFieldState(field){removeClass(field,"is-valid"),removeClass(field,"is-invalid");const formGroup=field.closest(".form-group")||field.parentElement;removeClass(formGroup,"has-error");const feedback=formGroup.querySelector(".form-feedback");feedback&&(feedback.textContent="",removeClass(feedback,"is-valid"),removeClass(feedback,"is-invalid"))}clearFormState(form){$$("[data-rules]",form).forEach(field=>{this.clearFieldState(field)})}getFormState(form){const fields=$$("[data-rules]",form),state={isValid:!0,fields:{}};return fields.forEach(field=>{const isValid=!hasClass(field,"is-invalid");state.fields[field.name||field.id]=isValid,isValid||(state.isValid=!1)}),state}}window.FormValidator=FormValidator;class LivePreview{constructor(){this.settings=window.CustomThemeSettings||{},this.isThemeEditor=window.Shopify&&window.Shopify.designMode,this.updateQueue=new Map,this.updateTimer=null,this.updateDelay=16,this.init()}init(){if(console.log("\u{1F504} Live Preview initializing..."),!this.settings.features?.livePreview){console.log("\u23F8\uFE0F Live Preview disabled in settings");return}this.setupThemeEditorIntegration(),this.setupMutationObserver(),this.setupPerformanceOptimization(),this.bindEvents(),console.log("\u2705 Live Preview initialized")}setupThemeEditorIntegration(){this.isThemeEditor&&(document.addEventListener("shopify:section:load",e=>{this.handleSectionChange(e.detail)}),document.addEventListener("shopify:section:unload",e=>{this.handleSectionChange(e.detail)}),document.addEventListener("shopify:section:select",e=>{this.handleSectionChange(e.detail)}),document.addEventListener("shopify:section:deselect",e=>{this.handleSectionChange(e.detail)}),document.addEventListener("shopify:block:select",e=>{this.handleBlockChange(e.detail)}),document.addEventListener("shopify:block:deselect",e=>{this.handleBlockChange(e.detail)}))}setupMutationObserver(){this.observer=new MutationObserver(mutations=>{mutations.forEach(mutation=>
14{mutation.type==="childList"&&mutation.addedNodes.forEach(node=>{node.nodeType===Node.ELEMENT_NODE&&(node.tagName==="STYLE"||node.querySelector("style"))&&this.handleStyleChange()}),mutation.type==="attributes"&&mutation.attributeName==="style"&&this.handleInlineStyleChange(mutation.target)})}),this.observer.observe(document.head,{childList:!0,subtree:!0}),this.observer.observe(document.documentElement,{attributes:!0,attributeFilter:["style"]})}setupPerformanceOptimization(){this.scheduleUpdate=()=>{this.updateTimer||(this.updateTimer=requestAnimationFrame(()=>{this.processUpdateQueue(),this.updateTimer=null}))}}handleSectionChange(detail){console.log("\u{1F504} Section changed:",detail),this.updateCustomSchemaVariables(),this.updateColorSystem(),document.dispatchEvent(new CustomEvent("livePreview:sectionChanged",{detail}))}handleBlockChange(detail){console.log("\u{1F504} Block changed:",detail),this.updateBlockStyling(detail),document.dispatchEvent(new CustomEvent("livePreview:blockChanged",{detail}))}handleStyleChange(){this.queueUpdate("styles",()=>{this.updateCustomSchemaVariables(),this.updateColorSystem()})}handleInlineStyleChange(element){element===document.documentElement&&this.queueUpdate("rootStyles",()=>{this.updateColorSystem()})}updateCustomSchemaVariables(){const schemaScript=document.querySelector("script[data-custom-theme-settings]")||Array.from(document.scripts).find(script=>script.textContent.includes("window.CustomThemeSettings"));if(schemaScript)try{const scriptContent=schemaScript.textContent,settingsMatch=scriptContent.match(/window\.CustomThemeSettings\s*=\s*({[\s\S]*?});/);if(settingsMatch){const newSettings=eval(`(${settingsMatch[1]})`);window.CustomThemeSettings=newSettings,this.settings=newSettings,document.dispatchEvent(new CustomEvent("livePreview:settingsUpdated",{detail:newSettings}))}}catch(error){console.warn("Failed to update custom theme settings:",error)}}updateColorSystem(){this.settings.colors&&(Object.entries(this.settings.colors).forEach(([key,value])=>{const cssVar=`--color-custom-${this.camelToKebab(key)}`;getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim()!==value&&document.documentElement.style.setProperty(cssVar,value)}),this.settings.borderRadius&&Object.entries(this.settings.borderRadius).forEach(([key,value])=>{const cssVar=`--border-radius-custom-${key}`;document.documentElement.style.setProperty(cssVar,`${value}px`)}),this.settings.spacing&&Object.entries(this.settings.spacing).forEach(([key,value])=>{if(typeof value=="number"){const cssVar=`--spacing-custom-${key}`;document.documentElement.style.setProperty(cssVar,`${value}px`)}}),document.dispatchEvent(new CustomEvent("livePreview:colorsUpdated",{detail:this.settings.colors})))}updateBlockStyling(detail){const blockElement=document.querySelector(`[data-block-id="${detail.blockId}"]`);blockElement&&this.queueUpdate(`block-${detail.blockId}`,()=>{blockElement.dispatchEvent(new CustomEvent("block:updated",{detail,bubbles:!0}))})}queueUpdate(key,updateFunction){this.updateQueue.set(key,updateFunction),this.scheduleUpdate()}processUpdateQueue(){this.updateQueue.size!==0&&(this.updateQueue.forEach((updateFunction,key)=>{try{updateFunction()}catch(error){console.warn(`Failed to execute update for ${key}:`,error)}}),this.updateQueue.clear(),document.dispatchEvent(new CustomEvent("livePreview:batchUpdateComplete")))}triggerFullUpdate(){this.updateCustomSchemaVariables(),this.updateColorSystem(),document.dispatchEvent(new CustomEvent("livePreview:fullUpdateComplete"))}setEnabled(enabled){this.settings.features=this.settings.features||{},this.settings.features.livePreview=enabled,enabled?(this.setupThemeEditorIntegration(),this.setupMutationObserver()):this.observer&&this.observer.disconnect(),document.dispatchEvent(new CustomEvent("livePreview:enabledChanged",{detail:{enabled}}))}getState(){return{enabled:this.settings.features?.livePreview||!1,isThemeEditor:this.isThemeEditor,queueSize:this.updateQueue.size,settings:this.settings}}bindEvents(){document.addEventListener("custom-theme:settings-loaded",e=>{this.settings=e.detail,this.triggerFullUpdate()}),document.addEventListener("livePreview:requestUpdate",()=>{this.triggerFullUpdate()}),document.addEventListener("visibilitychange",()=>{document.hidden?this.updateTimer&&(cancelAnimationFrame(this.updateTimer),this.updateTimer=null):this.updateQueue.size>0&&this.scheduleUpdate()})}destroy(){this.observer&&this.observer.disconnect(),this.updateTimer&&cancelAnimationFrame(this.updateTimer),this.updateQueue.clear()}camelToKebab(str){return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase()}}window.LivePreview=LivePreview;class ModalManager{constructor(){this.activeModals=new Set,this.scrollPosition=0,this.init()}init(){this.bindEvents(),console.log("\u{1F532} Modal Manager initialized")}bindEvents(){document.addEventListener("click",e=>{if(e.target.matches("[data-modal-open]")){e.preventDefault();
14const modalId=data(e.target,"modal-open");this.openModal(modalId)}if(e.target.matches("[data-modal-close]")){e.preventDefault();const modalId=data(e.target,"modal-close");modalId?this.closeModal(modalId):this.closeTopModal()}if(e.target.matches(".modal-backdrop")){const modal=e.target.nextElementSibling;if(modal&&hasClass(modal,"modal")){const modalId=modal.id;data(modal,"backdrop-static")||this.closeModal(modalId)}}}),document.addEventListener("keydown",e=>{e.key==="Escape"&&this.activeModals.size>0&&this.closeTopModal()})}openModal(modalId,options={}){const modal=$(`#${modalId}`);if(!modal){console.warn(`Modal with ID "${modalId}" not found`);return}this.activeModals.size===0&&(this.scrollPosition=window.pageYOffset,this.preventBodyScroll());let backdrop=modal.previousElementSibling;(!backdrop||!hasClass(backdrop,"modal-backdrop"))&&(backdrop=this.createBackdrop(),modal.parentNode.insertBefore(backdrop,modal)),this.activeModals.add(modalId),addClass(backdrop,"show"),addClass(modal,"show"),modal.setAttribute("aria-hidden","false"),this.trapFocus(modal),document.dispatchEvent(new CustomEvent("modal:open",{detail:{modalId,modal}})),console.log(`\u{1F4D6} Modal "${modalId}" opened`)}closeModal(modalId){const modal=$(`#${modalId}`);if(!modal||!this.activeModals.has(modalId))return;this.activeModals.delete(modalId),removeClass(modal,"show"),modal.setAttribute("aria-hidden","true");const backdrop=modal.previousElementSibling;backdrop&&hasClass(backdrop,"modal-backdrop")&&(removeClass(backdrop,"show"),setTimeout(()=>{backdrop.parentNode&&backdrop.parentNode.removeChild(backdrop)},300)),this.activeModals.size===0&&this.restoreBodyScroll(),this.restoreFocus(),document.dispatchEvent(new CustomEvent("modal:close",{detail:{modalId,modal}})),console.log(`\u{1F4D5} Modal "${modalId}" closed`)}closeTopModal(){if(this.activeModals.size>0){const modalIds=Array.from(this.activeModals),topModalId=modalIds[modalIds.length-1];this.closeModal(topModalId)}}closeAllModals(){Array.from(this.activeModals).forEach(modalId=>this.closeModal(modalId))}createBackdrop(){const backdrop=document.createElement("div");return backdrop.className="modal-backdrop",backdrop}preventBodyScroll(){addClass(document.body,"modal-open"),document.body.style.top=`-${this.scrollPosition}px`}restoreBodyScroll(){removeClass(document.body,"modal-open"),document.body.style.top="",window.scrollTo(0,this.scrollPosition)}trapFocus(modal){const focusableElements=modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(focusableElements.length===0)return;const firstElement=focusableElements[0],lastElement=focusableElements[focusableElements.length-1];firstElement.focus();const handleTabKey=e=>{e.key==="Tab"&&(e.shiftKey?document.activeElement===firstElement&&(e.preventDefault(),lastElement.focus()):document.activeElement===lastElement&&(e.preventDefault(),firstElement.focus()))};modal.addEventListener("keydown",handleTabKey),modal._focusTrapHandler=handleTabKey}restoreFocus(){}isModalOpen(modalId){return this.activeModals.has(modalId)}getActiveModals(){return new Set(this.activeModals)}}window.ModalManager=ModalManager;class DescriptionFormatter{constructor(options={}){this.options={containerSelectors:[".metafields-collection-description__container .boxed-text",".metafields-products-additional__container .boxed-text",".metafields-product-description__container .boxed-text"],alternateDirection:!0,mobileBreakpoint:750,...options},this.containers=[]}init(){this.normalizeContainers(),(Array.isArray(this.options.containerSelectors)?this.options.containerSelectors:[this.options.containerSelectors]).forEach(selector=>{document.querySelectorAll(selector).forEach(container=>{this.containers.push(container),this.formatContainer(container)})}),this.containers.length>0&&this.setupResponsiveHandler()}formatContainer(container){try{this.cleanInlineStyles(container),this.unwrapExistingLayouts(container),this.unwrapImageWrappers(container),this.processContent(container)}catch(error){console.error("[DescriptionFormatter] Error:",error)}}normalizeContainers(){document.querySelectorAll(".metafields-collection-description__container").forEach(outer=>{outer.querySelectorAll(".metafields-collection-description__container").forEach(inner=>{if(inner===outer)return;const parent=inner.parentNode;for(;inner.firstChild;)parent.insertBefore(inner.firstChild,inner);inner.remove()})}),document.querySelectorAll(".metafields-collection-description__container .liquid").forEach(el=>{const parent=el.parentNode;for(;el.firstChild;)parent.insertBefore(el.firstChild,el);el.remove()})}cleanInlineStyles(container){container.querySelectorAll("img").forEach(img=>{img.style.float="",img.style.textAlign="",img.style.margin="",img.style.padding=""}),container.querySelectorAll("div[style]").forEach(div=>{div.removeAttribute("style")})}unwrapExistingLayouts(container){[".description-flex-layout",".collection-flex-layout",".description-section",".collection-section",".description-block",".description-sections",'[class*="flex-layout"]','[class*="image-column"]','[class*="text-column"]'].forEach(selector=>{container.querySelectorAll(selector).forEach(el=>{const parent=el.parentNode;
14Array.from(el.children).forEach(child=>{parent.insertBefore(child.cloneNode(!0),el)}),el.remove()})}),container.querySelectorAll("*").forEach(el=>{el.style.clear=""})}unwrapImageWrappers(container){let hasChanges=!0;for(;hasChanges;){hasChanges=!1;const divs=container.querySelectorAll("div");for(let i=0;i<divs.length;i++){const div=divs[i];if(div.children.length===1){const child=div.children[0];if(child.tagName==="IMG"){div.parentNode.insertBefore(child,div),div.remove(),hasChanges=!0;break}}}}container.querySelectorAll("p").forEach(p=>{if(p.children.length===1){const child=p.children[0];child.tagName==="IMG"&&(p.parentNode.insertBefore(child,p),p.remove())}})}processContent(container){const children=Array.from(container.children);if(children.length===0)return;let imageCount=0;children.forEach(child=>{const tagName=child.tagName.toUpperCase();if(tagName==="IMG"){this.applyFloatToImage(child,imageCount),imageCount++;return}const imgInChild=child.querySelector("img");if(imgInChild){this.applyFloatToImage(imgInChild,imageCount),imageCount++;const textClone=child.cloneNode(!0);textClone.querySelector("img").remove(),textClone.textContent.trim().length>0&&child.parentNode.insertBefore(textClone,child);return}if(tagName==="TABLE"){child.classList.add("full-width-table");return}}),container.querySelectorAll("img").forEach(img=>{img.classList.contains("float-image")||(this.applyFloatToImage(img,imageCount),imageCount++)})}applyFloatToImage(img,imageIndex){const direction=imageIndex%2===0?"left":"right";img.classList.add("float-image"),this.options.alternateDirection?img.classList.add("float-"+direction):img.classList.add("float-left")}setupResponsiveHandler(){let resizeTimeout;window.addEventListener("resize",()=>{clearTimeout(resizeTimeout),resizeTimeout=setTimeout(()=>this.handleResize(),100)})}handleResize(){const isMobile2=window.innerWidth<this.options.mobileBreakpoint;this.containers.forEach(container=>{container.querySelectorAll(".float-image").forEach(el=>{el.classList.toggle("mobile-full",isMobile2)})})}}function initDescriptionFormatter(){return new DescriptionFormatter().init()}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",initDescriptionFormatter):initDescriptionFormatter()),typeof module<"u"&&module.exports&&(module.exports=DescriptionFormatter);class ThemeManager{constructor(){this.currentTheme=this.getStoredTheme()||this.getSystemTheme(),this.colorScheme=this.getStoredColorScheme()||"default",this.init()}init(){this.applyTheme(this.currentTheme),this.applyColorScheme(this.colorScheme),this.bindEvents(),console.log("\u{1F3A8} Theme Manager initialized")}bindEvents(){document.addEventListener("click",e=>{if(e.target.matches("[data-theme-toggle]")&&(e.preventDefault(),this.toggleTheme()),e.target.matches("[data-color-scheme]")){e.preventDefault();const scheme=data(e.target,"color-scheme");this.setColorScheme(scheme)}}),window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{this.currentTheme==="auto"&&this.applyTheme("auto")})}getSystemTheme(){return window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}getStoredTheme(){return localStorage.getItem("theme")}getStoredColorScheme(){return localStorage.getItem("colorScheme")}setTheme(theme){this.currentTheme=theme,this.applyTheme(theme),this.storeTheme(theme),document.dispatchEvent(new CustomEvent("theme:change",{detail:{theme,resolvedTheme:this.getResolvedTheme()}}))}applyTheme(theme){const resolvedTheme=this.getResolvedTheme(theme);removeClass(document.documentElement,"theme-light"),removeClass(document.documentElement,"theme-dark"),addClass(document.documentElement,`theme-${resolvedTheme}`),document.documentElement.setAttribute("data-theme",resolvedTheme),this.updateThemeToggles()}getResolvedTheme(theme=this.currentTheme){return theme==="auto"?this.get
14SystemTheme():theme}toggleTheme(){const newTheme=this.getResolvedTheme()==="light"?"dark":"light";this.setTheme(newTheme)}setColorScheme(scheme){this.colorScheme=scheme,this.applyColorScheme(scheme),this.storeColorScheme(scheme),document.dispatchEvent(new CustomEvent("colorScheme:change",{detail:{colorScheme:scheme}}))}applyColorScheme(scheme){document.documentElement.className=document.documentElement.className.replace(/color-scheme-\w+/g,""),scheme!=="default"&&addClass(document.documentElement,`color-scheme-${scheme}`),document.documentElement.setAttribute("data-color-scheme",scheme),this.updateColorSchemeButtons()}storeTheme(theme){localStorage.setItem("theme",theme)}storeColorScheme(scheme){localStorage.setItem("colorScheme",scheme)}updateThemeToggles(){const toggles=document.querySelectorAll("[data-theme-toggle]"),currentTheme=this.getResolvedTheme();toggles.forEach(toggle=>{const isDark=currentTheme==="dark";toggle.setAttribute("aria-pressed",isDark);const lightText=data(toggle,"light-text")||"Light",darkText=data(toggle,"dark-text")||"Dark";toggle.textContent.trim()&&(toggle.textContent=isDark?lightText:darkText)})}updateColorSchemeButtons(){document.querySelectorAll("[data-color-scheme]").forEach(button=>{const isActive=data(button,"color-scheme")===this.colorScheme;button.setAttribute("aria-pressed",isActive),isActive?addClass(button,"active"):removeClass(button,"active")})}getCurrentTheme(){return this.currentTheme}getCurrentColorScheme(){return this.colorScheme}isDarkMode(){return this.getResolvedTheme()==="dark"}}window.ThemeManager=ThemeManager;class CustomButton{constructor(element){this.element=element,this.isLoading=!1,this.originalText=element.textContent.trim(),this.loadingText=data(element,"loading-text")||"Loading...",this.init()}init(){this.bindEvents(),console.log("\u{1F518} Custom Button initialized")}bindEvents(){this.element.addEventListener("click",e=>{this.handleClick(e)});const observer=new MutationObserver(mutations=>{mutations.forEach(mutation=>{if(mutation.type==="attributes"&&mutation.attributeName==="data-loading"){const isLoading=data(this.element,"loading")==="true";isLoading!==this.isLoading&&(isLoading?this.showLoading():this.hideLoading())}})});observer.observe(this.element,{attributes:!0,attributeFilter:["data-loading"]}),this.observer=observer}handleClick(e){if(this.isLoading){e.preventDefault();return}if(data(this.element,"auto-loading")==="true"){this.showLoading();const timeout=parseInt(data(this.element,"loading-timeout"))||3e3;setTimeout(()=>{this.hideLoading()},timeout)}this.element.dispatchEvent(new CustomEvent("button:click",{detail:{button:this.element}}))}showLoading(){this.isLoading||(this.isLoading=!0,addClass(this.element,"btn-loading"),this.element.disabled=!0,attr(this.element,"aria-busy","true"),this.loadingText&&(this.element.textContent=this.loadingText),this.element.dispatchEvent(new CustomEvent("button:loading:start",{detail:{button:this.element}})))}hideLoading(){this.isLoading&&(this.isLoading=!1,removeClass(this.element,"btn-loading"),this.element.disabled=!1,attr(this.element,"aria-busy","false"),this.element.textContent=this.originalText,this.element.dispatchEvent(new CustomEvent("button:loading:end",{detail:{button:this.element}})))}setLoading(loading){loading?this.showLoading():this.hideLoading()}setText(text){this.originalText=text,this.isLoading||(this.element.textContent=text)}setLoadingText(text){this.loadingText=text,this.isLoading&&(this.element.textContent=text)}enable(){this.element.disabled=!1,removeClass(this.element,"disabled")}disable(){this.element.disabled=!0,addClass(this.element,"disabled")}isLoadingState(){return this.isLoading}destroy(){this.observer&&this.observer.disconnect(),this.element.removeEventListener("click",this.handleClick),this.hideLoading(),this.enable()}}window.CustomButton=CustomButton;class NavigationMenu{constructor(element){this.element=element,this.isMobile=window.innerWidth<768,this.activeDropdown=null,this.mobileMenuOpen=!1,this.init()}init(){this.bindEvents(),this.setupAccessibility(),console.log("\u{1F9ED} Navigation Menu initialized")}bindEvents(){on(this.element,"click",e=>{e.target.matches("[data-mobile-menu-toggle]")&&(e.preventDefault(),this.toggleMobileMenu())}),on(this.element,"click",e=>{e.target.matches("[data-dropdown-toggle]")&&(e.preventDefault(),this.toggleDropdown(e.target))}),this.isMobile||this.setupDesktopHover(),on(this.element,"keydown",e=>{this.handleKeyboardNavigation(e)}),document.addEventListener("click",e=>{this.element.contains(e.target)||this.closeAllDropdowns()}),window.addEventListener("resize",()=>{const wasMobile=this.isMobile;this.isMobile=window.innerWidth<768,wasMobile!==this.isMobile&&this.handleResponsiveChange()}),document.addEventListener("keydown",e=>{e.key==="Escape"&&(this.mobileMenuOpen?this.closeMobileMenu():this.closeAllDropdowns())})}setupDesktopHover(){$$("[data-dropdown-toggle]",this.element).forEach(trigger=>{const dropdown=this.getDropdownForTrigger(trigger);if(!dropdown)return;let hoverTimeout;trigger.addEventListener("mouseenter",()=>{clearTimeout(hoverTimeout),this.openDropdown(trigger)}),trigger.addEventListener("mouseleave",()=>{hoverTimeout=setTimeout(()=>{this.closeDropdown(trigger)},300)}),dropdown.addEventListener("mouseenter",()=>{clearTimeout(hoverTimeout)}),dropdown.addEventListener("mouseleave",()=>{hoverTimeout=setTimeout(()=>{this.closeDropdown(trigger)},300)})})}setupAccessibility(){$$("[data-dropdown-toggle]",this.element).forEach(trigger=>{const dropdown=this.getDropdownForTrigger(trigger);if(dropdown){const dropdownId=dropdown.id||`dropdown-${Date.now()}`;dropdown.id=dropdownId,trigger.setAttribute("aria-haspopup","true"),trigger.setAttribute("aria-expanded","fal
14se"),trigger.setAttribute("aria-controls",dropdownId),dropdown.setAttribute("aria-hidden","true")}})}toggleMobileMenu(){this.mobileMenuOpen?this.closeMobileMenu():this.openMobileMenu()}openMobileMenu(){this.mobileMenuOpen=!0,addClass(this.element,"mobile-menu-open"),addClass(document.body,"mobile-menu-open");const toggle=$("[data-mobile-menu-toggle]",this.element);toggle&&toggle.setAttribute("aria-expanded","true"),document.dispatchEvent(new CustomEvent("navigation:mobile:open",{detail:{menu:this.element}}))}closeMobileMenu(){this.mobileMenuOpen=!1,removeClass(this.element,"mobile-menu-open"),removeClass(document.body,"mobile-menu-open");const toggle=$("[data-mobile-menu-toggle]",this.element);toggle&&toggle.setAttribute("aria-expanded","false"),this.closeAllDropdowns(),document.dispatchEvent(new CustomEvent("navigation:mobile:close",{detail:{menu:this.element}}))}toggleDropdown(trigger){const dropdown=this.getDropdownForTrigger(trigger);if(!dropdown)return;hasClass(dropdown,"show")?this.closeDropdown(trigger):this.openDropdown(trigger)}openDropdown(trigger){const dropdown=this.getDropdownForTrigger(trigger);dropdown&&(this.closeAllDropdowns(),addClass(dropdown,"show"),addClass(trigger,"active"),trigger.setAttribute("aria-expanded","true"),dropdown.setAttribute("aria-hidden","false"),this.activeDropdown={trigger,dropdown},document.dispatchEvent(new CustomEvent("navigation:dropdown:open",{detail:{trigger,dropdown}})))}closeDropdown(trigger){const dropdown=this.getDropdownForTrigger(trigger);dropdown&&(removeClass(dropdown,"show"),removeClass(trigger,"active"),trigger.setAttribute("aria-expanded","false"),dropdown.setAttribute("aria-hidden","true"),this.activeDropdown&&this.activeDropdown.trigger===trigger&&(this.activeDropdown=null),document.dispatchEvent(new CustomEvent("navigation:dropdown:close",{detail:{trigger,dropdown}})))}closeAllDropdowns(){$$(".dropdown.show",this.element).forEach(dropdown=>{const trigger=$(`[aria-controls="${dropdown.id}"]`,this.element);trigger&&this.closeDropdown(trigger)})}getDropdownForTrigger(trigger){const dropdownId=trigger.getAttribute("aria-controls")||data(trigger,"dropdown-target");return dropdownId?$(`#${dropdownId}`):trigger.nextElementSibling}handleKeyboardNavigation(e){const{key}=e,activeElement=document.activeElement;(key==="Enter"||key===" ")&&activeElement.matches("[data-dropdown-toggle]")&&(e.preventDefault(),this.toggleDropdown(activeElement)),key==="ArrowDown"&&(e.preventDefault(),this.focusNextItem(activeElement)),key==="ArrowUp"&&(e.preventDefault(),this.focusPreviousItem(activeElement))}focusNextItem(currentElement){const focusableElements=$$('a, button, [tabindex]:not([tabindex="-1"])',this.element),nextIndex=(Array.from(focusableElements).indexOf(currentElement)+1)%focusableElements.length;focusableElements[nextIndex].focus()}focusPreviousItem(currentElement){const focusableElements=$$('a, button, [tabindex]:not([tabindex="-1"])',this.element),currentIndex=Array.from(focusableElements).indexOf(currentElement),previousIndex=currentIndex===0?focusableElements.length-1:currentIndex-1;focusableElements[previousIndex].focus()}handleResponsiveChange(){this.isMobile?this.closeAllDropdowns():(this.closeMobileMenu(),this.setupDesktopHover())}destroy(){this.closeAllDropdowns(),this.closeMobileMenu(),off(this.element,"click"),off(this.element,"keydown")}}window.NavigationMenu=NavigationMenu;class ProductCard{constructor(element){this.element=element,this.productId=data(element,"product-id"),this.variantId=data(element,"variant-id"),this.isLoading=!1,this.init()}init(){this.bindEvents(),this.setupQuickActions(),console.log(`\u{1F6CD}\uFE0F Product Card initialized for product ${this.productId}`)}bindEvents(){on(this.element,"click",e=>{e.target.matches("[data-quick-add]")&&(e.preventDefault(),this.handleQuickAdd())}),on(this.element,"click",e=>{e.target.matches("[data-quick-view]")&&(e.preventDefault(),this.handleQuickView())}),on(this.element,"click",e=>{e.target.matches("[data-wishlist-toggle]")&&(e.preventDefault(),this.handleWishlistToggle())}),on(this.element,"click",e=>{e.target.matches("[data-compare-toggle]")&&(e.preventDefault(),this.handleCompareToggle())}),on(this.element,"change",e=>{e.target.matches("[data-variant-select]")&&this.handleVariantChange(e.target)}),this.setupImageHover()}setupQuickActions(){const quickActions=$(".product-card__quick-actions",this.element);quickActions&&(this.element.addEventListener("mouseenter",()=>{addClass(quickActions,"show")}),this.element.addEventListener("mouseleave",()=>{removeClass(quickActions,"show")}))}setupImageHover(){const images=$$(".product-card__image img",this.element);if(images.length>1){const primaryImage=images[0],hoverImage=images[1];this.element.addEventListener("mouseenter",()=>{addClass(primaryImage,"fade-out"),addClass(hoverImage,"fade-in")}),this.element.addEventListener("mouseleave",()=>{removeClass(primaryImage,"fade-out"),removeClass(hoverImage,"fade-in")})}}async handleQuickAdd(){if(!this.isLoading){this.setLoading(!0);try{const formData=new FormData;formData.append("id",this.variantId),formData.append("quantity",1);const response=await fetch("/cart/add.js",{method:"POST",body:formData});if(response.ok){const result=await response.json();this.showSuccess("Added to cart!"),document.dispatchEvent(new CustomEvent("cart:add",{detail:{product:result,productId:this.productId}}))}else throw new Error("Failed to add to cart")}catch(error){console.error("Quick add error:",error),this.showError("Failed to add to cart")}finally{this.setLoading(!1)}}}handleQuickView(){document.dispatchEvent(new CustomEvent("product:quickview",{detail:{productId:this.productId,element:this.element}}))}handleWishlistToggle(){const button=$("[data-wishlist-toggle]",this.element),isInWishlist=hasClass(button,"active");isInWishlist?(removeClass(button,"active"),this.showSuccess("Removed from wishlist")):(addClass(button,"active"),this.showSuccess("Added to wishlist")),document.dispatchEvent(new CustomEvent("wishlist:toggle",{detail:{productId:this.productId,action:isInWishlist?"remove":"add",element:this.element}}))}handleCompareToggle(){const button=$("[data-compare-toggle]",this.element),isInCompare=hasClass(button,"active");isInCompare?(removeClass(button,"active"),this.showSuccess("Removed from compare")):(addClass(button,"active"),this.showSuccess("Added to compare")),document.dispatchEvent(new CustomEvent("compare:toggle",{detail:{productId:this.productId,action:isInCompare?"remove":"add",element:this.element}}))}async handleVariantChange(select){const newVariantId=select.value;this.variantId=newVariantId,await this.updateProductData(newVariantId),document.dispatchEvent(new CustomEvent("product:variant:change",{detail:{productId:this.productId,variantId:newVariantId,element:this.element}}))}async updateProductData(variantId){try{const variant=(await(await fetch(`/
14products/${this.productId}.js`)).json()).variants.find(v=>v.id==variantId);if(variant){const priceElement=$(".product-card__price",this.element);priceElement&&(priceElement.textContent=this.formatMoney(variant.price));const availabilityElement=$(".product-card__availability",this.element);availabilityElement&&(variant.available?(removeClass(availabilityElement,"unavailable"),addClass(availabilityElement,"available"),availabilityElement.textContent="In stock"):(removeClass(availabilityElement,"available"),addClass(availabilityElement,"unavailable"),availabilityElement.textContent="Out of stock"));const quickAddButton=$("[data-quick-add]",this.element);quickAddButton&&(quickAddButton.disabled=!variant.available)}}catch(error){console.error("Failed to update product data:",error)}}setLoading(loading){this.isLoading=loading,loading?addClass(this.element,"loading"):removeClass(this.element,"loading")}showSuccess(message){this.showMessage(message,"success")}showError(message){this.showMessage(message,"error")}showMessage(message,type="info"){let messageElement=$(".product-card__message",this.element);messageElement||(messageElement=document.createElement("div"),messageElement.className="product-card__message",this.element.appendChild(messageElement)),messageElement.textContent=message,messageElement.className=`product-card__message ${type}`,addClass(messageElement,"show"),setTimeout(()=>{removeClass(messageElement,"show")},3e3)}formatMoney(cents){return(cents/100).toFixed(2)}destroy(){this.element.removeEventListener("mouseenter",this.handleMouseEnter),this.element.removeEventListener("mouseleave",this.handleMouseLeave)}}window.ProductCard=ProductCard;class VariantConfirmationModal extends HTMLElement{constructor(){super(),this.formId=this.getAttribute("data-form-id"),this.form=null,this.confirmed=!1,this.boundHandler=this.handleButtonClick.bind(this)}connectedCallback(){if(this.form=document.getElementById(this.formId),!this.form){console.warn("VariantConfirmationModal: Form not found:",this.formId);return}this.bindEvents(),this.observeNewButtons()}bindEvents(){this.bindSubmitButtons(),this.querySelector('[data-action="close"]')?.addEventListener("click",()=>this.close()),this.querySelector('[data-action="cancel"]')?.addEventListener("click",()=>this.close()),this.querySelector('[data-action="confirm"]')?.addEventListener("click",()=>this.confirm()),this.querySelector(".variant-confirmation-modal__overlay")?.addEventListener("click",()=>this.close()),document.addEventListener("keydown",e=>{e.key==="Escape"&&!this.hidden&&this.close()})}bindSubmitButtons(){document.querySelectorAll(`[form="${this.formId}"][type="submit"], #${this.formId} [type="submit"]`).forEach(btn=>{btn.hasAttribute("data-confirmation-bound")||(btn.setAttribute("data-confirmation-bound","true"),btn.addEventListener("click",this.boundHandler,!0))})}observeNewButtons(){new MutationObserver(()=>{this.bindSubmitButtons()}).observe(document.body,{childList:!0,subtree:!0})}handleButtonClick(e){if(this.confirmed){this.confirmed=!1;return}return e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.clickedButton=e.currentTarget,this.open(),!1}open(){this.updateVariantInfo(),this.hidden=!1,document.body.style.overflow="hidden",setTimeout(()=>{this.querySelector('[data-action="cancel"]')?.focus()},100)}close(){this.hidden=!0,document.body.style.overflow=""}confirm(){this.confirmed=!0,this.close(),this.clickedButton&&this.clickedButton.click()}updateVariantInfo(){const variantInput=this.form.querySelector('input[name="id"]');if(!variantInput)return;const variantId=variantInput.value,productData=this.getProductData();if(!productData)return;const variant=productData.variants.find(v=>v.id==variantId);if(!variant)return;const titleEl=this.querySelector("[data-variant-title]"),priceEl=this.querySelector("[data-variant-price]");titleEl&&(titleEl.textContent=variant.title),priceEl&&(priceEl.textContent=this.formatMoney(variant.price))}getProductData(){const productJson=this.form.closest("[data-product-json]")?.querySelector('script[type="application/json"]');if(productJson)try{return JSON.parse(productJson.textContent)}catch{return null}return null}formatMoney(cents){const amount=(cents/100).toFixed(2);return new Intl.NumberFormat("de-DE",{style:"currency",currency:window.Shopify?.currency?.active||"EUR"}).format(amount)}}customElements.get("variant-confirmation-modal")||customElements.define("variant-confirmation-modal",VariantConfirmationModal);class App{constructor(){this.eventBus=new EventBus,this.modules=new Map,this.components=new Map,this.init()}init(){ready(()=>{window.CustomThemeSettings?this.initWithSettings():document.addEventListener("custom-theme:settings-loaded",()=>{this.initWithSettings()})})}initWithSettings(){this.settings=window.CustomThemeSettings,console.log("\u2699\uFE0F Theme settings loaded:",this.settings),this.initModules(),this.initComponents(),this.bindEvents(),this.initPerformanceFeatures(),this.eventBus.emit("app:ready",{settings:this.settings}),console.log("\u{1F680} DeSight Shopify X v1.0 initialized")}initModules(){this.modules.set("theme",new ThemeManager),this.modules.set("modal",new ModalManager),this.modules.set("validator",new FormValidator),(this.settings.features?.livePreview||this.settings.features?.contrastChecker||this.settings.features?.colorPaletteGenerator!=="disabled")&&this.modules.set("colorSystem",new ColorSystem),this.settings.features?.livePreview&&this.modules.set("livePreview",new LivePreview),this.modules.set("descriptionFormatter",new DescriptionFormatter)}initComponents(){document.querySelectorAll("[data-custom-button]").forEach(element=>{this.components.set(element,new CustomButton(element))}),document.querySelectorAll("[data-product-card]").forEach(element=>{this.components.set(element,new ProductCard(element))}),document.querySelectorAll("[data-navigation-menu]").forEach(element=>{this.components.set(element,new NavigationMenu(element))})}bindEvents(){window.addEventListener("resize",throttle(()=>{this.eventBus.emit("window:resize")},250)),window.addEventListener("scroll",throttle(()=>{this.eventBus.emit("window:scroll")},100)),window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{this.eventBus.emit("theme:change",{isDark:e.matches})}),document.addEventListener("shopify:section:load",event=>{this.handleSectionLoad(event.detail.sectionId)}),document.addEventListener("shopify:section:unload",event=>{this.handleSectionUnload(event.detail.sectionId)}),typeof initSmoothAnchorScrolling=="function"&&initSmoothAnchorScrolling({offset:-150,updateHash:!0,initialLoadDelay:1e3,stabilityTimeout:5e3,onScroll:(targetElement,link)=>{this.eventBus.emit("anchor:scroll",{targetElement,link}),console.log("\u2705 Scrolled to element:",targetElement.id)}})}handleSectionLoad(sectionId){const section=document.getElementById(`shopify-section-${sectionId}`);section&&(this.initComponentsInSection(section),this.eventBus.emit("section:load",{sectionId,section}))}handleSectionUnload(sectionId){this.cleanupComponentsInSection(sectionId),this.eventBus.emit("section:unload",{sectionId})}initComponentsInSection(section){section.querySelectorAll("[data-custom-button]").forEach(element=>{this.components.has(element)||this.components.set(element,new CustomButton(element))}),section.querySelectorAll("[data-product-card]").forEach(element=>{this.components.has(element)||this.components.set(element,new ProductCard(element))}),section.querySelectorAll("[data-navigation-menu]").forEach(element=>{this.components.has(element)||this.components.set(element,new NavigationMenu(element))})}cleanupComponentsInSection(sectionId){const section=document.getElementById(`shopify-section-${sectionId}`);
14section&&this.components.forEach((component,element)=>{section.contains(element)&&(typeof component.destroy=="function"&&component.destroy(),this.components.delete(element))})}getModule(name){return this.modules.get(name)}getEventBus(){return this.eventBus}initPerformanceFeatures(){this.settings&&(this.settings.features.webVitalsTracking&&typeof initPerformanceMonitoring=="function"&&initPerformanceMonitoring(),this.settings.features.lazyLoading&&typeof lazyLoadImages=="function"&&lazyLoadImages(),this.settings.features.preloadCriticalResources&&typeof ResourceHints=="function"&&(ResourceHints.preconnect("https://cdn.shopify.com"),ResourceHints.dnsPrefetch("https://fonts.googleapis.com")),this.settings.features.performanceMode&&document.documentElement.classList.add("performance-mode"))}}const app=new App;typeof window<"u"&&(window.CustomThemeApp=app),window.addEventListener("error",event=>{if(event.filename&&event.filename.includes("mBhmrhArhzk8L2OyGtue1BEH8ihIMkje"))return console.warn("\u{1F507} Suppressed Growave error:",event.message),event.preventDefault(),!1}); 15//# sourceMappingURL=/cdn/shop/t/27/assets/desight.js.map?v=151626695667814882061778606011
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.