<!-- 2026-06-03T13:47:13.4764974Z -->
<style>.shoplift-hide { opacity: 0 !important; }</style>
<style id="sl-preview-bar-hide">#preview-bar-iframe, #PBarNextFrameWrapper { display: none !important; }</style>
<script type="text/javascript">(function(rootPath, template, themeRole, themeId, isThemePreview){ /* Generated on 2026-06-06T05:31:11.7725685Z */(function(){"use strict";var tt=document.createElement("style");tt.textContent=`#shoplift-preview-control{position:fixed;max-width:332px;height:56px;background-color:#141414;z-index:9999;bottom:20px;display:flex;border-radius:8px;box-shadow:13px 22px 7px #0000,9px 14px 7px #00000003,5px 8px 6px #0000000d,2px 4px 4px #00000017,1px 1px 2px #0000001a,0 0 #0000001a;align-items:center;margin:0 auto;left:16px;right:16px;opacity:0;transform:translateY(20px);visibility:hidden;transition:opacity .4s ease-in-out,transform .4s ease-in-out,visibility 0s .4s}#shoplift-preview-control.visible{opacity:1;transform:translateY(0);visibility:visible;transition:opacity .4s ease-in-out,transform .4s ease-in-out,visibility 0s 0s}#shoplift-preview-control *{font-family:Inter,sans-serif;color:#fff;box-sizing:border-box;font-size:16px}#shoplift-preview-variant-title{font-weight:400;line-height:140%;font-size:16px;text-align:start;letter-spacing:-.16px;flex-grow:1;text-wrap:nowrap;overflow:hidden;text-overflow:ellipsis}#shoplift-preview-variant-selector{position:relative;display:block;padding:6px 0;height:100%;min-width:0;flex:1 1 auto}#shoplift-preview-variant-menu-trigger{border:none;cursor:pointer;width:100%;background-color:transparent;padding:0 16px;border-left:1px solid #333;border-right:1px solid #333;height:100%;display:flex;align-items:center;justify-content:start;gap:8px}#shoplift-preview-variant-selector .menu-variant-label{width:24px;height:24px;border-radius:50%;padding:6px;display:flex;justify-content:center;align-items:center;font-size:12px;font-style:normal;font-weight:600;line-height:100%;letter-spacing:-.12px;flex-shrink:0}#shoplift-preview-variant-selector .preview-variant-menu{position:absolute;bottom:110%;transform:translate3d(0,20px,0);visibility:hidden;pointer-events:none;opacity:0;cursor:pointer;background-color:#141414;border:1px solid #141414;border-radius:6px;width:100%;max-height:156px;overflow-y:auto;box-shadow:0 8px 16px #0003;z-index:1;transition:opacity .3s ease-in-out,transform .3s ease-in-out,visibility 0s .3s}#shoplift-preview-variant-selector .preview-variant-menu.preview-variant-menu__visible{visibility:visible;pointer-events:auto;opacity:100;transform:translateZ(0);transition:opacity .3s ease-in-out,transform .3s ease-in-out,visibility 0s 0s}@media screen and (max-width:400px){#shoplift-preview-variant-selector .preview-variant-menu{position:fixed;left:0;right:0;width:auto;bottom:110%}}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item{padding:12px 16px;display:flex;overflow:hidden}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item .menu-variant-label{margin-right:6px}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item span{overflow:hidden;text-overflow:ellipsis;text-wrap:nowrap;white-space:nowrap;color:#f6f6f6;font-size:14px;font-style:normal;font-weight:500}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:hover{background-color:#545454}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:last-of-type{border-bottom-left-radius:6px;border-bottom-right-radius:6px}#shoplift-preview-variant-selector .preview-variant-menu .preview-variant-menu--item:first-of-type{border-top-left-radius:6px;border-top-right-radius:6px}#shoplift-preview-control div:has(#shoplift-exit-preview-button){padding:0 16px}#shoplift-exit-preview-button{padding:6px 8px;font-weight:500;line-height:75%;border-radius:4px;background-color:transparent;border:none;text-decoration:none}#shoplift-exit-preview-button:hover{cursor:pointer;background-color:#333}#shoplift-preview-subscription-warning{position:relative;display:flex;align-items:center;gap:6px;padding:6px 10px;margin:0 4px;border-left:1px solid #333;cursor:help;outline:none}#shoplift-preview-subscription-warning__icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background-color:#f59e0b;color:#141414!important;font-weight:700;font-size:12px!important;line-height:1;flex-shrink:0}#shoplift-preview-subscription-warning__label{font-size:13px!important;font-weight:500;color:#fbbf24!important;text-wrap:nowrap;white-space:nowrap}#shoplift-preview-subscription-warning__tooltip{position:absolute;bottom:calc(100% + 8px);right:0;max-width:320px;width:max-content;padding:10px 12px;border-radius:6px;background-color:#1f1f1f;color:#fff!important;font-size:12px!important;line-height:1.4!important;box-shadow:0 8px 16px #0000004d;z-index:10000;opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .2s ease-in-out,transform .2s ease-in-out,visibility 0s .2s;pointer-events:none}#shoplift-preview-subscription-warning__tooltip.shoplift-preview-subscription-warning__tooltip--visible{opacity:1;visibility:visible;transform:translateY(0);transition:opacity .2s ease-in-out,transform .2s ease-in-out,visibility 0s 0s}#shoplift-preview-subscription-warning:focus-visible{box-shadow:inset 0 0 0 2px #f59e0b;border-radius:4px}#shoplift-preview-control:has(#shoplift-preview-subscription-warning){max-width:480px}/*$vite$:1*/`,document.head.appendChild(tt);var ht=" daum[ /]| deusu/| yadirectfetcher|(?:^|[^g])news(?!sapphire)|(?<! (?:channel/|google/))google(?!(app|/google| pixel))|(?<! cu)bots?(?:\\b|_)|(?<!(?: ya| yandex|^job|inapp;) ?)search|(?<!(?:lib))http|(?<![hg]m)score|@[a-z][\\w-]+\\.|\\(\\)|\\.com|\\b\\d{13}\\b|^<|^[\\w \\.\\-\\(?:\\):]+(?:/v?\\d+(?:\\.\\d+)?(?:\\.\\d{1,10})*?)?(?:,|$)|^[^ ]{50,}$|^\\d+\\b|^\\w+/[\\w\\(\\)]*$|^active|^ad muncher|^amaya|^avsdevicesdk/|^biglotron|^bot|^bw/|^clamav[ /]|^client/|^cobweb/|^custom|^ddg[_-]android|^discourse|^dispatch/\\d|^downcast/|^duckduckgo|^facebook|^getright/|^gozilla/|^hobbit|^hotzonu|^hwcdn/|^jeode/|^jetty/|^jigsaw|^microsoft bits|^movabletype|^mozilla/\\d\\.\\d \\(compatible;?\\)$|^mozilla/\\d\\.\\d \\w*$|^navermailapp|^netsurf|^offline|^owler|^postman|^python|^rank|^read|^reed|^rest|^rss|^snapchat|^space bison|^svn|^swcd |^taringa|^thumbor/|^track|^valid|^w3c|^webbandit/|^webcopier|^wget|^whatsapp|^wordpress|^xenu link sleuth|^yahoo|^yandex|^zdm/\\d|^zoom marketplace/|^{{.*}}$|admin|analyzer|archive|ask jeeves/teoma|bit\\.ly/|bluecoat drtr|browsex|burpcollaborator|capture|catch|check|chrome-lighthouse|chromeframe|classifier|clean|cloud|crawl|cypress/|dareboost|datanyze|dejaclick|detect|dmbrowser|download|evc-batch/|feed|firephp|gomezagent|headless|httrack|hubspot marketing grader|hydra|ibisbrowser|images|insight|inspect|iplabel|ips-agent|java(?!;)|library|mail\\.ru/|manager|measure|neustar wpm|node|nutch|offbyone|optimize|pageburst|pagespeed|parser|perl|phantomjs|pingdom|powermarks|preview|proxy|ptst[ /]\\d|reputation|resolver|retriever|rexx;|rigor|rss\\b|scan|scrape|server|sogou|sparkler/|speedcurve|spider|splash|statuscake|synapse|synthetic|tools|torrent|trace|transcoder|url|virtuoso|wappalyzer|watch|webglance|webkit2png|whatcms/|zgrab",ft=/bot|spider|crawl|http|lighthouse/i,z;function gt(){if(z instanceof RegExp)return z;try{z=new RegExp(ht,"i")}catch{z=ft}return z}function mt(a){return!!a&>().test(a)}class Q{timestamp;constructor(){this.timestamp=new Date}}class yt extends Q{type;testId;hypothesisId;constructor(t,e,i){super(),this.type=3,this.testId=t,this.hypothesisId=e,this.timestamp=i}}class vt extends Q{type;path;constructor(t){super(),this.type=4,this.path=t}}class wt extends Q{type;cart;constructor(t){super(),this.type=5,this.cart=t}}class et extends Error{isBot;constructor(){super(),this.isBot=!0}}function bt(a,t,e){for(const i of t.selectors){const s=a.querySelectorAll(i.cssSelector);for(let r=0;r<s.length;r++)e(t.testId,t.hypothesisId)}st(a,t,(i,s,r,n,o)=>o(s,r),e)}function U(a,t,e){for(const i of t.selectors)rt(a,t.testId,t.hypothesisId,i,e??(()=>{}));st(a,t,rt,e??(()=>{}))}function it(a){return a.urlPatterns.reduce((t,e)=>{switch(e.operator){case"contains":return t+`.*${e}.*`;case"endsWith":return t+`.*${e}`;case"startsWith":return t+`${e}.*`}},"")}function st(a,t,e,i){new MutationObserver(()=>{for(const r of t.selectors)e(a,t.testId,t.hypothesisId,r,i)}).observe(a.documentElement,{childList:!0,subtree:!0})}function rt(a,t,e,i,s){const r=a.querySelectorAll(i.cssSelector);for(let n=0;n<r.length;n++){let o=r.item(n);if(o instanceof HTMLElement&&o.dataset.shoplift!==""){o.dataset.shoplift="";for(const l of i.actions.sort(kt))o=St(a,i.cssSelector,o,l)}}return r.length>0&&s?(s(t,e),!0):!1}function St(a,t,e,i){switch(i.type){case"innerHtml":e.innerHTML=i.value;break;case"attribute":Ct(e,i.scope,i.value);break;case"css":Tt(a,t,i.value);break;case"js":It(a,e,i);break;case"copy":return Pt(e);case"remove":At(e);break;case"move":Et(e,parseInt(i.value));break}return e}function Ct(a,t,e){a.setAttribute(t,e)}function Tt(a,t,e){const i=a.createElement("style");i.innerHTML=`${t} { ${e} }`,a.getElementsByTagName("head")[0]?.appendChild(i)}function It(a,t,e){Function("document","element",`"use strict"; ${e.value}`)(a,t)}function Pt(a){const t=a.cloneNode(!0);if(!a.parentNode)throw"Can't copy node outside of DOM";return a.parentNode.insertBefore(t,a.nextSibling),t}function At(a){a.remove()}function Et(a,t){if(t===0)return;const e=Array.prototype.slice.call(a.parentElement.children).indexOf(a),i=Math.min(Math.max(e+t,0),a.parentElement.children.length-1);a.parentElement.children.item(i).insertAdjacentElement(t>0?"afterend":"beforebegin",a)}function kt(a,t){return nt(a)-nt(t)}function nt(a){return a.type==="copy"||a.type==="remove"?0:1}var M=(a=>(a[a.Template=0]="Template",a[a.Theme=1]="Theme",a[a.UrlRedirect=2]="UrlRedirect",a[a.Script=3]="Script",a[a.Dom=4]="Dom",a[a.Price=5]="Price",a))(M||{});const xt="data:image/svg+xml,%3csvg%20width='12'%20height='12'%20viewBox='0%200%2012%2012'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M9.96001%207.90004C9.86501%207.90004%209.77001%207.86504%209.69501%207.79004L6.43501%204.53004C6.19501%204.29004%205.80501%204.29004%205.56501%204.53004L2.30501%207.79004C2.16001%207.93504%201.92001%207.93504%201.77501%207.79004C1.63001%207.64504%201.63001%207.40504%201.77501%207.26004L5.03501%204.00004C5.56501%203.47004%206.43001%203.47004%206.96501%204.00004L10.225%207.26004C10.37%207.40504%2010.37%207.64504%2010.225%207.79004C10.15%207.86004%2010.055%207.90004%209.96001%207.90004Z'%20fill='white'/%3e%3c/svg%3e",_t="data:image/svg+xml,%3csvg%20width='14'%20height='24'%20viewBox='0%200%2014%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M12.3976%2014.5255C12.2833%2013.8788%2012.0498%2013.3024%2011.6952%2012.7961C11.3416%2012.2898%2010.9209%2011.8353%2010.4353%2011.4317C9.94868%2011.0291%209.43546%2010.6488%208.89565%2010.292C8.48487%2010.049%208.09577%209.78565%207.72637%209.50402C7.35697%209.2224%207.08016%208.89503%206.89694%208.51987C6.71273%208.14471%206.67826%207.69533%206.79055%207.1697C6.86345%206.83216%206.97476%206.54647%207.12351%206.31162C7.27324%206.07778%207.47124%205.89986%207.7175%205.77684C7.96377%205.65483%208.21989%205.59383%208.48389%205.59383C8.88087%205.59383%209.17639%205.7016%209.3734%205.91714C9.56943%206.13268%209.68271%206.42345%209.71424%206.78946C9.74576%207.15547%209.72015%207.55401%209.63839%207.98509C9.55663%208.41617%209.43645%208.84724%209.27687%209.27934L13.5127%208.80149C13.9638%207.52656%2014.1017%206.42447%2013.9264%205.49725C13.751%204.56901%2013.2664%203.85122%2012.4724%203.34491C12.239%203.19648%2011.9779%203.07041%2011.6893%202.96569L12.0026%201.50979L9.86397%200L7.3875%201.50979L7.11169%202.78878C6.65166%202.8874%206.21724%203.01957%205.8114%203.19038C4.85292%203.594%204.06684%204.15115%203.45117%204.86385C2.83452%205.57655%202.42571%206.40108%202.22378%207.33847C2.06616%208.06947%202.04942%208.70796%202.17551%209.25087C2.30061%209.7948%202.52028%2010.2828%202.8355%2010.7139C3.14974%2011.145%203.51816%2011.5344%203.93977%2011.881C4.36039%2012.2288%204.782%2012.5521%205.20164%2012.851C5.68334%2013.1702%206.13844%2013.5169%206.56497%2013.8921C6.99052%2014.2672%207.31954%2014.7125%207.55004%2015.228C7.78055%2015.7445%207.81502%2016.3769%207.65347%2017.1262C7.56482%2017.5389%207.43676%2017.8765%207.27028%2018.1388C7.10381%2018.4011%206.89596%2018.5983%206.64772%2018.7295C6.3985%2018.8606%206.12071%2018.9267%205.8114%2018.9267C5.21641%2018.9267%204.79776%2018.6034%204.62833%2018.1632C4.4589%2017.7229%204.47367%2017.2583%204.60075%2016.5639C4.72782%2015.8705%205.05092%2015.1395%205.37107%2014.3699H1.17665C1.17665%2014.3699%200.207341%2016.1115%200.0310135%2017.6762C-0.0655232%2018.5302%200.0635208%2019.2653%200.41519%2019.8844C0.76686%2020.5036%201.33032%2020.9814%202.10655%2021.319C2.39222%2021.443%202.7104%2021.5447%203.05813%2021.623L2.54589%2024H7.17473L7.7047%2021.5386C8.08493%2021.442%208.43857%2021.3231%208.76562%2021.1787C9.73985%2020.7476%2010.52%2020.1427%2011.1071%2019.3649C11.6932%2018.5871%2012.0873%2017.7291%2012.2892%2016.7917C12.4744%2015.9295%2012.5099%2015.1741%2012.3966%2014.5275L12.3976%2014.5255Z'%20fill='white'/%3e%3c/svg%3e";async function Rt(a){let t=a.replace(/-/g,"+").replace(/_/g,"/");for(;t.length%4;)t+="=";const e=atob(t),i=Uint8Array.from(e,n=>n.charCodeAt(0)),s=new Blob([i]).stream().pipeThrough(new DecompressionStream("gzip")),r=await new Response(s).text();return JSON.parse(r)}function F(a,t){return typeof t=="string"&&/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+(?:Z|[+-]\d+)/.test(t)?new Date(t):t}function X(a,t){return t}function q(a,t=!1,e=!1,i=","){const s=a/100;if(e){const n=Math.round(s).toLocaleString("en-US");return i!==","?n.replace(/,/g,i):n}else{const r=t?",":".",n=s.toFixed(2).split("."),o=parseInt(n[0],10),l=n[1]??"00",c=o.toLocaleString("en-US");return i!==","?`${c.replace(/,/g,i)}${r}${l}`:t?`${c.replace(/,/g,".")}${r}${l}`:`${c}${r}${l}`}}function H(a,t,e,i){const s=t.replace("{{amount}}",q(a,!1,!1)).replace("{{amount_no_decimals}}",q(a,!1,!0)).replace("{{amount_with_comma_separator}}",q(a,!0,!1)).replace("{{amount_no_decimals_with_comma_separator}}",q(a,!0,!0)).replace("{{amount_with_space_separator}}",q(a,!1,!1," ")).replace("{{amount_no_decimals_with_space_separator}}",q(a,!1,!0," ")).replace("{{amount_with_apostrophe_separator}}",q(a,!1,!1,"'")).replace("{{amount_no_decimals_with_apostrophe_separator}}",q(a,!1,!0,"'")).replace("{{amount_with_period_and_space_separator}}",q(a,!1,!1,". ")).replace("{{amount_no_decimals_with_period_and_space_separator}}",q(a,!1,!0,". "));return i?`${s} ${e}`:s}function ot(a){return a.replace(/[^\d.,\s-]/g,"").trim()}function j(a){const t=new Map;for(const[e,i,s]of a.variants)t.set(e,{priceInCents:i,compareAtPriceInCents:s});return t}function Dt(a,t,e,i){const{priceInCents:s,compareAtPriceInCents:r}=e,{moneyFormat:n,currency:o,currencyCodeEnabled:l}=i;if(a.getAttribute("data-sl-attribute-p")===t)a.innerHTML=H(s,n,o,l);else if(a.getAttribute("data-sl-attribute-cap")===t)r<=0||r<=s?a.remove():a.innerHTML=H(r,n,o,l);else if(a.getAttribute("data-sl-attribute-discount")===t&&!(r<=0||r<=s)){const d=Math.round((r-s)/r*100),p=ot(H(r-s,n,o,!1)),h=a.getAttribute("data-sl-format")||"percent";h==="percent"?a.textContent=`-${d}%`:h==="amount"?a.textContent=`-${p}`:h==="both"&&(a.textContent=`-${d}% (-${p})`)}}function Ot(a){const t=[],e={id:"url-pattern",operator:"contains",value:"/"};for(const[i,s,r]of a.variants){t.push({id:`p-${i}`,cssSelector:`[data-sl-attribute-p="${i}"]`,urlPatterns:[e],actions:[{id:`p-action-${i}`,type:"innerHtml",scope:"price",value:H(s,a.moneyFormat,a.currency,a.currencyCodeEnabled)}]});const n=r<=0||r<=s;if(t.push({id:`cap-${i}`,cssSelector:`[data-sl-attribute-cap="${i}"]`,urlPatterns:[e],actions:[{id:`cap-action-${i}`,type:n?"remove":"innerHtml",scope:"compare-at-price",value:n?"":H(r,a.moneyFormat,a.currency,a.currencyCodeEnabled)}]}),!n&&r>s){const o=Math.round((r-s)/r*100),l=ot(H(r-s,a.moneyFormat,a.currency,!1));t.push({id:`d-${i}`,cssSelector:`[data-sl-attribute-discount="${i}"]`,urlPatterns:[e],actions:[{id:`d-action-${i}`,type:"js",scope:null,value:`var format = element.getAttribute('data-sl-format') || 'percent'; if (format === 'percent') { element.textContent = '-${o}%'; } else if (format === 'amount') { element.textContent = '-${l}'; } else if (format === 'both') { element.textContent = '-${o}% (-${l})'; }`}]})}}return t}const Jt="modulepreload",Yt=function(a){return"/"+a},Zt={},Vt=function(t,e,i){let s=Promise.resolve();function r(n){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=n,window.dispatchEvent(o),!o.defaultPrevented)throw n}return s.then(n=>{for(const o of n||[])o.status==="rejected"&&r(o.reason);return t().catch(r)})};function at(a,t,e){const i=e?a.plans.filter(c=>!c.variantId||c.variantId===e):a.plans,s=[],r=[];for(const c of i)c.direction==="decrease"?(s.push(c.existingShopifyPlanId),r.push(c.createdShopifyPlanId)):(s.push(c.createdShopifyPlanId),r.push(c.existingShopifyPlanId));const n=t?s:r,o=t?r:s;if(e)for(const c of a.plans)for(const d of[c.existingShopifyPlanId,c.createdShopifyPlanId])d&&!n.includes(d)&&!o.includes(d)&&o.push(d);const l={};for(let c=0;c<o.length;c++){const d=o[c],p=n[c];d&&p&&(l[d]=p)}return{showPlanIds:n,hidePlanIds:o,swapMap:l}}function lt(a,t,e){const i=t?a.plans.find(r=>r.variantId===t):void 0;if(i)return i.direction;if(e){const r=a.plans.find(n=>n.productId===e);if(r)return r.direction}return a.plans.find(r=>!r.variantId)?.direction??null}function K(a,t){const e=t?a.plans.filter(r=>!r.productId||r.productId===t):a.plans,i={};for(const r of e)i[r.existingShopifyPlanId]=r.existingDiscountAmount,i[r.createdShopifyPlanId]=r.existingDiscountAmount;const s=Math.max(...Object.values(i),0);return{discountMap:i,maxDiscount:s}}function W(a){const t=document.querySelector('form[action*="/cart/add"] input[name="product-id"]')?.value;if(t)return t;if(a){for(const r of Array.from(document.querySelectorAll("[data-sl-attribute-p]"))){const n=r.getAttribute("data-sl-attribute-p");if(!n)continue;const o=a.variants.find(l=>l[0]===n);if(o?.[3])return o[3]}const s=document.querySelector('form[action*="/cart/add"] input[name="id"]')?.value;if(s){const r=a.variants.find(n=>n[0]===s);if(r?.[3])return r[3]}}const e=window,i=e.ShopifyAnalytics?.meta?.product?.id??e.meta?.product?.id;return i!=null?String(i):null}function D(a,t){return a.widget.selectors[t]??[]}function N(a,t){return a.replace(/[\d.]+%/,`${t}%`)}function $(a,t){const e=document.createTreeWalker(a,NodeFilter.SHOW_TEXT);let i=e.nextNode();for(;i;){if(i.nodeValue!==null){const s=t(i.nodeValue);if(s!==i.nodeValue){i.nodeValue=s;return}}i=e.nextNode()}}function ct(a,t){return a===null?!1:a==="decrease"?!t:t}async function Lt(a){if(a.subscriptionSwapDone)return;const t=a.getActiveAssignment();if(!t)return;const e=a.getHypothesis(t.hypothesisId);if(!e?.subscriptionData)return;a.subscriptionSwapDone=!0;const i=e.subscriptionData,s=e.isControl,r=[...new Set(i.plans.map(d=>d.direction))].join(",");a.log(`[SUB-SWAP] ${s?"A":"B"} side, directions=${r}`);const n=i.plans.some(d=>d.variantId);let o=!1,l=!1;function c(){if(!l){l=!0;try{const d=n?document.querySelector("select[name='id'], input[name='id']")?.value:void 0,{showPlanIds:p,hidePlanIds:h,swapMap:u}=at(i,s,d);a.swapMap=u;const b=D(i,"widgetParent"),k=D(i,"subscriptionPlans"),S=D(i,"subscriptionInput");if(!b.length||!k.length||!S.length)return;const P=document.querySelector(b[0].selector);if(!P?.shadowRoot)return;const _=P.shadowRoot.querySelector(k[0].selector);if(!_?.shadowRoot)return;const C=S[0].selector;let m=null;if(i.widget.widgetType==="buttons"||i.widget.widgetType==="radio"){const y=Array.from(_.shadowRoot.querySelectorAll(C));if(!y.length)return;for(const v of y){const g=v.closest("label");g&&(p.includes(v.value)?g.style.display="":h.includes(v.value)&&(g.style.display="none"))}const w=y.some(v=>p.includes(v.value)&&v.checked),T=y.some(v=>h.includes(v.value)&&v.checked);if((w||T)&&(o=!1),!w&&!o){o=!0;for(const v of y)if(p.includes(v.value)){v.closest("label")?.click(),v.dispatchEvent(new Event("change",{bubbles:!0}));break}}const f=y.find(v=>v.checked);m=f&&p.includes(f.value)?f.value:p[0]??null}else if(i.widget.widgetType==="dropdown"){const y=_.shadowRoot.querySelector("select");if(!y)return;for(const w of Array.from(y.options))h.includes(w.value)&&(w.style.display="none",w.disabled=!0);if(h.includes(y.value)){const w=Array.from(y.options).find(T=>p.includes(T.value));w&&(y.value=w.value,y.dispatchEvent(new Event("change",{bubbles:!0})))}m=p.includes(y.value)?y.value:p[0]??null}if(m){const y=Array.from(document.querySelectorAll('input[name="selling_plan"]'));for(const w of y)w.value!==m&&(w.value=m)}}finally{l=!1}}}if(a.subscriptionHideWrongPlans=c,a.swapMap=at(i,s).swapMap,c(),n){const d=document.querySelector("select[name='id'], input[name='id']");d&&d.addEventListener("change",c)}}function B(a){const t=D(a,"widgetParent");return t.length?document.querySelector(t[0].selector)?.shadowRoot??null:null}function J(a,t){const e=D(a,"subscriptionPlans");return e.length?t.querySelector(e[0].selector)?.shadowRoot??null:null}function Y(a,t){const e=new URLSearchParams(window.location.search).get("variant");if(e)return e;{const i=document.querySelector('form[action*="/cart/add"] input[name="id"]')?.value;if(i)return i}return a.size>0?[...a.keys()][0]:void 0}function G(a,t){return H(a,t.moneyFormat,t.currency,t.currencyCodeEnabled)}function $t({originalFetch:a,swapMap:t,slptValue:e,getSelectedPlanId:i,log:s}){if(window.fetch.__shoplift_intercepted)return s("[SUB-INTERCEPT] already installed — skipping"),()=>{};function r(o){if(i){const l=i();if(l)return t[l]??l}return t[o]??o}const n=function(o,l){if((typeof o=="string"?o:o instanceof URL?o.href:o.url).includes("/cart/add")&&l?.body)try{if(l.body instanceof FormData){const d=l.body.get("selling_plan");d?l.body.set("selling_plan",r(String(d))):(!d||d==="")&&e&&l.body.set("properties[_slpt]",e)}else if(typeof l.body=="string"){const d=JSON.parse(l.body);if(d.items)for(const p of d.items){const h=String(p.selling_plan??"");h?p.selling_plan=r(h):!p.selling_plan&&e&&(p.properties||(p.properties={}),p.properties._slpt=e)}else if(d.id){const p=String(d.selling_plan??"");p?d.selling_plan=r(p):!d.selling_plan&&e&&(d.properties||(d.properties={}),d.properties._slpt=e)}l.body=JSON.stringify(d)}}catch(d){s("[SUB-INTERCEPT] body parse failed; cart-add proceeds with un-swapped plan",d)}return a.call(window,o,l)};return n.__shoplift_intercepted=!0,window.fetch=n,function(){window.fetch===n&&(window.fetch=a)}}function Mt({log:a}){if(window.fetch.__shoplift_intercepted)return a("[SUB-PREVIEW-BLOCK] already installed — skipping"),()=>{};const t=window.fetch,e=function(i,s){const r=typeof i=="string"?i:i instanceof URL?i.href:i.url;return r.includes("/cart/add")?(a("[SUB-PREVIEW-BLOCK] cart-add blocked in preview mode",{url:r}),Promise.resolve(new Response(JSON.stringify({id:0,properties:{},quantity:0,variant_id:0,key:"preview",title:"Preview — cart-add blocked",price:0,original_price:0,line_price:0,original_line_price:0,total_discount:0,discounts:[],preview:!0}),{status:200,headers:{"Content-Type":"application/json"}}))):t.call(window,i,s)};return e.__shoplift_intercepted=!0,window.fetch=e,function(){window.fetch===e&&(window.fetch=t)}}function dt({data:a,runUpdates:t,debounceMs:e=150}){let i=null;function s(){i&&clearTimeout(i),t(),i=setTimeout(t,e)}let r=null;const n=[],o={childList:!0,subtree:!0,characterData:!0,attributes:!0};function l(h){for(const u of n)u.disconnect();n.length=0;for(const u of Array.from(h.querySelectorAll("*")))if(u.shadowRoot){const b=new MutationObserver(s);b.observe(u.shadowRoot,o),n.push(b)}}function c(){const h=B(a);return h?(r&&r.disconnect(),l(h),r=new MutationObserver(u=>{u.some(b=>b.type==="childList"&&b.addedNodes.length>0)&&l(h),s()}),r.observe(h,o),!0):!1}const d=document.body||document.documentElement,p=new MutationObserver(()=>{c()&&s()});return p.observe(d,{childList:!0,subtree:!0}),c()&&s(),t(),function(){i&&(clearTimeout(i),i=null),p.disconnect(),r&&(r.disconnect(),r=null);for(const u of n)u.disconnect();n.length=0}}async function qt(a){if(a.subscriptionPriceDone)return;const t=a.getActiveAssignment(),e=t?a.getHypothesis(t.hypothesisId):void 0,i=e?.subscriptionData?null:a.findActiveSubscriptionTestControl(),s=e?.subscriptionData?e:i?.hypothesis;if(!s?.subscriptionData)return;const r=e?.subscriptionData?t.testId:i.testId;a.subscriptionPriceDone=!0;const n=s.subscriptionData,o=s.isControl,l=s.priceData,c=n.widget.widgetType;let d=W(l),p=K(n,d),h=p.discountMap,u=p.maxDiscount;function b(){const g=W(l);g!==d&&(d=g,p=K(n,d),h=p.discountMap,u=p.maxDiscount,a.log(`[SUB-PRICE] scope refreshed side=${o?"A":"B"}, currentProductId=${d??"n/a"}, maxDiscount=${u}`))}a.log(`[SUB-PRICE] side=${o?"A":"B"}, currentProductId=${d??"n/a"}, maxDiscount=${u}`),a.updatePriceTestHiddenInputs(r,o?"control":"variant",!1);function k(){if(!l)return null;const g=j(l),I=Y(g),A=lt(n,I,d);if(!ct(A,o))return null;const E=I?g.get(I):void 0;return E?{formattedVariantPrice:G(E.priceInCents,l),formattedDiscounted:G(E.priceInCents*(1-u/100),l)}:null}$t({originalFetch:a.fetch,swapMap:a.swapMap??{},slptValue:a.slptValue??void 0,log:a.log,getSelectedPlanId:()=>{const g=B(n);if(!g)return null;const I=J(n,g);if(!I)return null;const A=D(n,"subscriptionInput"),E=A.length?A[0].selector:'input[name="rc_plan"]';return I.querySelector(`${E}:checked`)?.value??null}});function S(g){const I=D(n,"subscriptionDiscount");for(const A of I)if(A.selector.includes("badge")||A.selector.includes("__badge")){const E=g.querySelector(A.selector);E?.textContent&&!E.textContent.includes(`${u}%`)&&$(E,x=>N(x,u))}}function P(g){const I=k();if(!I)return;const A=D(n,"subscriptionCompareAt");for(const E of A){const x=g.querySelector(E.selector)||g.querySelector(`[part~="${E.selector}"]`);x?.textContent&&!x.textContent.includes(I.formattedVariantPrice)&&$(x,R=>/\d/.test(R)?I.formattedVariantPrice:R)}}function _(g,I){const A=D(n,"subscriptionCompareAt"),E=I===0?"none":"";for(const x of A){const R=g.querySelector(x.selector)||g.querySelector(`[part~="${x.selector}"]`);R&&(E==="none"?R.style.display!=="none"&&(R.style.display="none"):R.style.display==="none"&&(R.style.display=""))}}function C(g){const I=D(n,"subscriptionInput"),A=I.length?I[0].selector:'input[name="rc_plan"]',E=D(n,"subscriptionPlanDiscount"),x=E.length?E[0].selector:".rc-plans-button__discount";for(const R of Array.from(g.querySelectorAll("label"))){const V=R.querySelector(A),O=R.querySelector(x);if(V&&O){const L=h[V.value];if(L!==void 0){if(L===0)O.style.display!=="none"&&(O.style.display="none");else if(O.style.display==="none"&&(O.style.display=""),O.textContent){const Z=O.textContent.match(/[\d.]+%/)?.[0];Z&&Z!==`${L}%`&&$(O,Kt=>N(Kt,L))}}}}}function m(g){const I=g.querySelector("select");if(I)for(const A of Array.from(I.options)){const E=h[A.value];if(E!==void 0&&A.textContent){const x=A.textContent.match(/[\d.]+%/)?.[0];x&&x!==`${E}%`&&(A.textContent=N(A.textContent,E))}}}function y(g,I){const E=D(n,"subscriptionDiscount").filter(x=>x.selector.includes("benefit")||x.selector==="rc-benefits");for(const x of E){const R=g.querySelector(x.selector);if(R?.shadowRoot){for(const V of Array.from(R.shadowRoot.querySelectorAll("li")))if(V.textContent?.includes("Save")){const O=V;if(I===0)O.style.display!=="none"&&(O.style.display="none");else{O.style.display==="none"&&(O.style.display="");const L=V.textContent.match(/[\d.]+%/)?.[0];L&&L!==`${I}%`&&$(V,Z=>N(Z,I))}}}}}let w=!1;function T(){if(!w){w=!0;try{if(b(),d!==null&&Object.keys(h).length===0)return;const g=B(n);if(!g)return;S(g),l&&P(g);const I=J(n,g);let A=u;if(I){const E=D(n,"subscriptionInput"),x=E.length?E[0].selector:'input[name="rc_plan"]',R=I.querySelector(`${x}:checked`);if(R){const V=h[R.value];V!==void 0&&(A=V)}c==="buttons"||c==="radio"?C(I):m(I)}_(g,A),y(g,A)}finally{w=!1}}}function f(){const g=k();if(!g)return;const I=B(n);if(!I)return;const A=D(n,"onetimeToggle"),E=A.length?A[0].selector:'input[value="onetime"]';if(!I.querySelector(E)?.checked)return;const R=D(n,"subscriptionPrice");for(const V of R){const O=I.querySelector(V.selector)||I.querySelector(`[part~="${V.selector}"]`);O?.textContent&&!O.textContent.includes(g.formattedDiscounted)&&$(O,L=>/\d/.test(L)?g.formattedDiscounted:L)}}function v(){a.subscriptionHideWrongPlans&&a.subscriptionHideWrongPlans(),T(),a.subscriptionUpdateOneTime&&a.subscriptionUpdateOneTime(),f()}dt({data:n,runUpdates:v})}async function Ht(a){if(a.subscriptionOneTimeDone)return;const t=a.getActiveAssignment(),e=t?a.getHypothesis(t.hypothesisId):void 0,i=!!(e?.subscriptionData&&e.priceData),s=i?null:a.findActiveSubscriptionTestControl(),r=i?e:s?.hypothesis;if(!r?.subscriptionData||!r.priceData)return;const n=i?t.testId:s.testId;a.subscriptionOneTimeDone=!0;const o=r.subscriptionData,l=r.priceData,c=j(l),d=r.isControl,p=d?"control":"variant";a.slptValue=`${n}:${p}:f`,a.updatePriceTestHiddenInputs(n,p,!1);function h(){const u=B(o);if(!u)return;const b=Y(c);if(!b)return;const k=W(l),S=lt(o,b,k);if(!ct(S,d))return;const P=c.get(b);if(!P)return;const _=H(P.priceInCents,l.moneyFormat,l.currency,l.currencyCodeEnabled),C=D(o,"onetimePrice");if(!C.length)return;const m=D(o,"onetimeContainer"),y=m.length?m[0].selector:'[part~="rc-purchase-option__onetime"]',T=u.querySelector(y)??u;for(const f of C){let v=null;try{v=T.querySelector(f.selector)}catch{v=null}v??=T.querySelector(`[part~="${f.selector}"]`),v&&v.textContent&&!v.textContent.includes(_)&&$(v,g=>/\d/.test(g)?_:g)}}a.subscriptionUpdateOneTime=h,h()}async function Nt(a,t){const{subscriptionPreviewRender:e}=await Vt(async()=>{const{subscriptionPreviewRender:i}=await Promise.resolve().then(()=>jt);return{subscriptionPreviewRender:i}},void 0);return e(a.subscriptionData,a.priceData,a.isControl,t)}function Ut(a,t){const e=a.widget.selectors.widgetParent??[],i=a.widget.selectors.subscriptionPlans??[],s=a.widget.selectors.subscriptionInput??[];if(!e.length||!i.length||!s.length){t("[SUB-GLOBAL-HIDE] Missing required selectors — skipping");return}const r=e[0].selector,n=i[0].selector,o=s[0].selector;let l=!1,c=null,d=!1;function p(){if(!d){d=!0;try{h()}finally{d=!1}}}function h(){const P=document.querySelector(r);if(!P?.shadowRoot)return;const _=P.shadowRoot.querySelector(n);if(!_?.shadowRoot)return;_.shadowRoot!==c&&(c=_.shadowRoot,l=!1);let C=0;if(a.widget.widgetType==="buttons"||a.widget.widgetType==="radio"){const m=Array.from(_.shadowRoot.querySelectorAll(o));for(const f of m)if(a.planIds.includes(f.value)){f.disabled||(f.disabled=!0);const v=f.closest("label");v&&v.style.display!=="none"&&(v.style.display="none",C++)}const y=m.filter(f=>!a.planIds.includes(f.value));if(!y.some(f=>f.checked)&&!l&&y.length>0){l=!0;const f=y[0];f.closest("label")?.click(),f.dispatchEvent(new Event("change",{bubbles:!0})),t(`[SUB-GLOBAL-HIDE] Preselected first visible plan input=${f.value}`)}const T=y.find(f=>f.checked)??y[0];if(T){const f=Array.from(document.querySelectorAll('input[name="selling_plan"]'));for(const v of f)v.value!==T.value&&(v.value=T.value,t(`[SUB-GLOBAL-HIDE] Mirrored plan id ${T.value} to form selling_plan input`))}}else if(a.widget.widgetType==="dropdown"){const m=_.shadowRoot.querySelector("select");if(!m)return;for(const T of Array.from(m.options))a.planIds.includes(T.value)&&(T.style.display!=="none"&&(T.style.display="none"),T.disabled||(T.disabled=!0),C++);const y=Array.from(m.options).filter(T=>!a.planIds.includes(T.value)),w=y.some(T=>T.value===m.value);y.length>0&&!w&&!l&&(l=!0,m.value=y[0].value,m.dispatchEvent(new Event("change",{bubbles:!0})),t(`[SUB-GLOBAL-HIDE] Preselected first visible option=${y[0].value}`))}C>0&&t(`[SUB-GLOBAL-HIDE] Hidden ${C} B-side plan buttons`)}const u={childList:!0,subtree:!0,characterData:!0};let b=null;function k(P){b?.disconnect(),b=new MutationObserver(()=>p()),b.observe(P,u)}function S(){const P=document.querySelector(r);if(!P?.shadowRoot)return!1;p(),new MutationObserver(()=>{p();const m=P.shadowRoot.querySelector(n);m?.shadowRoot&&k(m.shadowRoot)}).observe(P.shadowRoot,u);const C=P.shadowRoot.querySelector(n);return C?.shadowRoot&&k(C.shadowRoot),!0}if(!S()){t("[SUB-GLOBAL-HIDE] Widget not in DOM yet — waiting via MutationObserver");const P=new MutationObserver(()=>{S()&&P.disconnect()});P.observe(document.body??document.documentElement,{childList:!0,subtree:!0})}}const ut="Limited preview",Ft="Add-to-cart and checkout prices won't reflect this test until it launches — test selling plans are not created in your subscription app until after a test is launched.",Bt=5e3;function zt(){const a=document.createElement("div");a.id="shoplift-preview-subscription-warning";const t=document.createElement("span");t.id="shoplift-preview-subscription-warning__icon",t.setAttribute("aria-hidden","true"),t.textContent="!";const e=document.createElement("span");e.id="shoplift-preview-subscription-warning__label",e.textContent=ut;const i=document.createElement("div");i.id="shoplift-preview-subscription-warning__tooltip",i.setAttribute("role","tooltip"),i.textContent=Ft,a.appendChild(t),a.appendChild(e),a.appendChild(i),a.setAttribute("tabindex","0"),a.setAttribute("aria-describedby",i.id),a.setAttribute("aria-label",ut);let s=null;function r(){s!==null&&(clearTimeout(s),s=null)}function n(){i.classList.add("shoplift-preview-subscription-warning__tooltip--visible")}function o(){i.classList.remove("shoplift-preview-subscription-warning__tooltip--visible")}function l(){n(),r(),s=setTimeout(()=>{o(),s=null},Bt)}function c(){r(),n()}function d(){s===null&&o()}a.addEventListener("mouseenter",c),a.addEventListener("mouseleave",d),a.addEventListener("focus",c),a.addEventListener("blur",d);function p(u){try{const b=u.target;if(!(b instanceof Element))return;(b.closest('form[action*="/cart/add"] button[type="submit"], form[action*="/cart/add"] input[type="submit"]')!==null||b.closest('[name="add"], button[name="add"], [data-add-to-cart], button[data-add-to-cart]')!==null)&&l()}catch{}}document.addEventListener("click",p,!0);function h(){r(),document.removeEventListener("click",p,!0),a.removeEventListener("mouseenter",c),a.removeEventListener("mouseleave",d),a.removeEventListener("focus",c),a.removeEventListener("blur",d),a.remove()}return{root:a,tooltip:i,cleanup:h}}let pt=!1;class Wt{constructor(t,e,i,s,r,n,o,l,c,d,p,h,u){this.shop=t,this.host=e,this.eventHost=i,this.disableReferrerOverride=l,this.logHistory=[],this.legacySessionKey=`SHOPLIFT_SESSION_${this.shop}`,this.cssHideClass=s?"shoplift-hide":"",this.testConfigs=p.map(k=>({...k,startAt:new Date(k.startAt),statusHistory:k.statusHistory.map(S=>({...S,createdAt:new Date(S.createdAt)}))})),this.inactiveTestConfigs=h,this.hiddenSubscriptionPlans=u,this.sendPageView=!!r,this.shopliftDebug=n===!0,this.telemetryEnabled=c===!0,this.gaConfig=o!=={"sendEvents":false,"mode":"gtag"}?o:{sendEvents:!1},this.fetch=window.fetch.bind(window),this.localStorageSet=window.localStorage.setItem.bind(window.localStorage),this.localStorageGet=window.localStorage.getItem.bind(window.localStorage);const b=this.getDeviceType();this.device=b!=="tablet"?b:"mobile",this.state=this.loadState(),this.shopifyAnalyticsId=this.getShopifyAnalyticsId(),this.testsFilteredByAudience=p.filter(k=>k.status=="active"),this.getCountryTimeout=d===1000?1e3:d,this.log("State Loaded",JSON.stringify(this.state))}DATA_SL_ATTRIBUTE_P="data-sl-attribute-p";DATA_SL_TEST_ID="data-sl-test-id";VIEWPORT_TRACK_THRESHOLD=.5;temporarySessionKey="Shoplift_Session";essentialSessionKey="Shoplift_Essential";analyticsSessionKey="Shoplift_Analytics";priceSelectorsSessionKey="Shoplift_PriceSelectors_v2";legacySessionKey;cssHideClass;testConfigs;inactiveTestConfigs;hiddenSubscriptionPlans;testsFilteredByAudience;sendPageView;shopliftDebug;gaConfig;telemetryEnabled;getCountryTimeout;state;subscriptionPreviewWarningCleanup=null;shopifyAnalyticsId;cookie=document.cookie;isSyncing=!1;isSyncingGA=!1;fetch;localStorageSet;localStorageGet;sessionStorageSet=window.sessionStorage.setItem.bind(window.sessionStorage);sessionStorageGet=window.sessionStorage.getItem.bind(window.sessionStorage);urlParams=new URLSearchParams(window.location.search);device;logHistory;activeViewportObservers=new Map;clientIdRetryCount=0;deriveCategoryFromExistingTests(){if(!this.state.temporary.testCategory&&this.state.essential.visitorTests.length>0){const t=this.state.essential.visitorTests.some(e=>{if(!e.hypothesisId)return!1;const i=this.getHypothesis(e.hypothesisId);return i&&["theme","basicScript","price"].includes(i.type)});this.state.temporary.testCategory=t?"global":"conditional",this.persistTemporaryState(),this.log("Derived test category from existing visitorTests: %s",this.state.temporary.testCategory)}}async init(){try{if(this.log("Shoplift script initializing"),window.Shopify&&window.Shopify.designMode){this.log("Skipping script for design mode");return}if(window.location.href.includes("slScreenshot=true")){this.log("Skipping script for screenshot");return}if(window.location.hostname.endsWith(".edgemesh.com")){this.log("Skipping script for preview");return}if(window.location.href.includes("isShopliftMerchant")){const s=this.urlParams.get("isShopliftMerchant")==="true";this.log("Setting merchant session to %s",s),this.state.temporary.isMerchant=s,this.persistTemporaryState()}if(this.state.temporary.isMerchant){this.log("Setting up preview for merchant"),typeof window.shoplift!="object"&&this.setShopliftStub(),this.state.temporary.previewConfig||this.hidePage(),await this.initPreview(),document.querySelector("#sl-preview-bar-hide")?.remove();return}if(this.state.temporary.previewConfig=void 0,mt(navigator.userAgent))return;const t=this.state.essential.visitorTests.filter(s=>s.hypothesisId&&+s.createdAt>Date.now()-6e4);if(t.length===0)this.sendDiagnosticTelemetry("page-landed",null);else for(const s of t)this.sendDiagnosticTelemetry("page-landed",s.testId,{hypothesisId:s.hypothesisId,isControl:s.assignedTo==="control",testType:s.testType??"unknown"});if(navigator.userAgent.includes("Chrome/118")){this.log("Random: %o",[Math.random(),Math.random(),Math.random()]);const s=await this.makeRequest({url:`${this.eventHost}/api/v0/events/ip`,method:"get"}).then(r=>r?.json());this.log(`IP: ${s}`),this.makeRequest({url:`${this.eventHost}/api/v0/logs`,method:"post",data:JSON.stringify(this.debugState(),X)}).catch()}if(this.shopifyAnalyticsId=this.getShopifyAnalyticsId(),this.monitorConsentChange(),this.checkForThemePreview())return;if(!this.disableReferrerOverride&&this.state.temporary.originalReferrer!=null){this.log(`Overriding referrer from '${document.referrer}' to '${this.state.temporary.originalReferrer}'`);const s=this.state.temporary.originalReferrer;delete this.state.temporary.originalReferrer,this.persistTemporaryState(),Object.defineProperty(document,"referrer",{get:()=>s,enumerable:!0,configurable:!0})}if(await this.refreshVisitor(this.shopifyAnalyticsId),await this.handleVisitorTest()){this.log("Redirecting for visitor test");return}this.setShoplift(),this.showPage(),this.ensureCartAttributesForExistingPriceTests(!1);const i=this.state.essential.visitorTests.some(s=>(s.hypothesisId?this.getHypothesis(s.hypothesisId):void 0)?.subscriptionData!=null)||Object.values(this.state.temporary.testReservations??{}).some(s=>this.getHypothesis(s.hypothesisId)?.subscriptionData!=null);this.hiddenSubscriptionPlans&&!i&&(this.log(`[SUB-GLOBAL] Visitor not in subscription test — hiding ${this.hiddenSubscriptionPlans.planIds.length} B-side plans`),Ut(this.hiddenSubscriptionPlans,s=>this.log(s))),await this.subscriptionSwap(),await this.subscriptionOneTimePrice(),await this.subscriptionPriceChange(),await this.finalize(),console.log("SHOPLIFT SCRIPT INITIALIZED!")}catch(t){if(t instanceof et)return;throw t}finally{typeof window.shoplift!="object"&&this.setShopliftStub()}}getVariantColor(t){switch(t){case"a":return{text:"#141414",bg:"#E2E2E2"};case"b":return{text:"rgba(255, 255, 255, 1)",bg:"rgba(37, 99, 235, 1)"}}}getDefaultVariantTitle(t){return t.title?t.title:t.type==="price"?t.isControl?"Original prices":"Variant prices":t.isControl?"Original":"Untitled variant "+t.label.toUpperCase()}async initPreview(){const t=this.urlParams.get("previewConfig");if(t){this.state.temporary.previewConfig=void 0,this.log("Setting up the preview"),this.log("Found preview config, writing to temporary state");const e=await Rt(t);if(this.state.temporary.previewConfig=e,this.state.temporary.previewConfig.testTypeCategory===M.Price){this.hidePage(!0);const s=this.state.temporary.previewConfig;let r=`${this.host}/api/dom-selectors/${s.storeId}/${s.testId}/${s.isDraft||!1}`;s.shopifyProductId&&(r+=`?productId=${s.shopifyProductId}`);const n=await this.makeJsonRequest({method:"get",url:r}).catch(o=>(this.log("Error getting domSelectors",o),null));if(s.variants.forEach(o=>o.domSelectors=n[o.id]?.domSelectors),s.isDraft){const o=`${this.host}/api/dom-selectors/${s.storeId}/${s.testId}/subscription-preview`,l=await this.makeJsonRequest({method:"get",url:o}).catch(c=>(this.log("No subscription preview data for draft (test may not have a subscription widget)",c),null));l?.subscriptionData&&s.variants.forEach(c=>{c.subscriptionData=l.subscriptionData,c.priceData=l.priceData})}}this.persistTemporaryState();const i=new URL(window.location.toString());i.searchParams.delete("previewConfig"),this.queueRedirect(i)}else if(this.state.temporary.previewConfig){this.showPage();const e=this.state.temporary.previewConfig;if(e.testTypeCategory===M.Template&&this.handleTemplatePreview(e)&&this.initPreviewControls(e),e.testTypeCategory===M.UrlRedirect&&this.handleUrlPreview(e)&&this.initPreviewControls(e),e.testTypeCategory===M.Script&&this.handleScriptPreview(e)&&this.initPreviewControls(e),e.testTypeCategory===M.Price){const i=await this.handlePricePreview(e);e.isDraft?await this.handleSubscriptionPricePreview(e):await this.handleSubscriptionLivePreview(e),i&&this.initPreviewControls(e)}}}initPreviewControls(t){document.addEventListener("DOMContentLoaded",()=>{const e=t.variants.find(b=>b.id===t.currentVariant),i=e?.label||"a",s=t.variants,r=document.createElement("div");r.id="shoplift-preview-control";const n=document.createElement("div"),o=document.createElement("img");o.src=_t,o.height=24,o.width=14,n.style.padding="0 16px",n.style.lineHeight="100%",n.appendChild(o),r.appendChild(n);const l=document.createElement("div");l.id="shoplift-preview-variant-selector";const c=document.createElement("button");c.id="shoplift-preview-variant-menu-trigger";const d=document.createElement("div");d.className="menu-variant-label",d.style.backgroundColor=this.getVariantColor(i).bg,d.style.color=this.getVariantColor(i).text,d.innerText=i.toUpperCase(),c.appendChild(d);const p=document.createElement("span");if(p.id="shoplift-preview-variant-title",p.innerText=e?this.getDefaultVariantTitle(e):"Untitled variant "+i.toUpperCase(),c.appendChild(p),s.length>1){const b=document.createElement("img");b.src=xt,b.width=12,b.height=12,b.style.height="12px",b.style.width="12px",c.appendChild(b);const k=document.createElement("div");k.className="preview-variant-menu";for(const S of t.variants.filter(P=>P.id!==t.currentVariant)){const P=document.createElement("div");P.className="preview-variant-menu--item";const _=document.createElement("div");_.className="menu-variant-label",_.style.backgroundColor=this.getVariantColor(S.label).bg,_.style.color=this.getVariantColor(S.label).text,_.style.flexShrink="0",_.innerText=S.label.toUpperCase(),P.appendChild(_);const C=document.createElement("span");C.innerText=this.getDefaultVariantTitle(S),P.appendChild(C),P.addEventListener("click",()=>{this.pickVariant(S.id)}),k.appendChild(P)}l.appendChild(k),c.addEventListener("click",()=>{k.className!=="preview-variant-menu preview-variant-menu__visible"?k.classList.add("preview-variant-menu__visible"):k.classList.remove("preview-variant-menu__visible")}),document.addEventListener("click",S=>{S.target instanceof Element&&!c.contains(S.target)&&k.className==="preview-variant-menu preview-variant-menu__visible"&&k.classList.remove("preview-variant-menu__visible")})}else c.style.pointerEvents="none",d.style.margin="0";if(l.appendChild(c),r.appendChild(l),t.hasSubscription){this.subscriptionPreviewWarningCleanup?.();const b=zt();r.appendChild(b.root),this.subscriptionPreviewWarningCleanup=b.cleanup}const h=document.createElement("div"),u=document.createElement("button");u.id="shoplift-exit-preview-button",u.innerText="Exit",h.appendChild(u),u.addEventListener("click",()=>{this.exitPreview()}),r.appendChild(h),document.body.appendChild(r),requestAnimationFrame(()=>{r.classList.add("visible")})}),this.ensureCartAttributesForExistingPriceTests(!0)}pickVariant(t){if(this.state.temporary.previewConfig){const e=this.state.temporary.previewConfig,i=new URL(window.location.toString());if(e.testTypeCategory===M.UrlRedirect){const s=e.variants.find(r=>r.id===e.currentVariant)?.redirectUrl;if(i.pathname===s){const r=e.variants.find(n=>n.id===t)?.redirectUrl;r&&(i.pathname=r)}}if(e.testTypeCategory===M.Template){const s=e.variants.find(r=>r.id===e.currentVariant)?.pathName;if(s&&i.pathname===s){const r=e.variants.find(n=>n.id===t)?.pathName;r&&r!==s&&(i.pathname=r)}}e.currentVariant=t,this.persistTemporaryState(),this.queueRedirect(i)}}exitPreview(){const t=new URL(window.location.toString());if(this.state.temporary.previewConfig?.testTypeCategory===M.Template&&t.searchParams.delete("view"),this.state.temporary.previewConfig?.testTypeCategory===M.Script&&t.searchParams.delete("slVariant"),this.state.temporary.previewConfig?.testTypeCategory===M.UrlRedirect){const i=this.state.temporary.previewConfig.variants.filter(r=>!r.isControl&&r.redirectUrl!==null).map(r=>r.redirectUrl),s=this.state.temporary.previewConfig.variants.find(r=>r.label==="a")?.redirectUrl;i.includes(t.pathname)&&s&&(t.pathname=s)}this.state.temporary.isMerchant=!1,t.searchParams.delete("isShopliftMerchant"),this.state.temporary.previewConfig=void 0,this.persistTemporaryState(),this.subscriptionPreviewWarningCleanup?.(),this.subscriptionPreviewWarningCleanup=null,this.hidePage(),this.queueRedirect(t)}handleTemplatePreview(t){const e=t.currentVariant,i=t.variants.find(l=>l.id===e);if(!i)return!1;const s=t.variants.find(l=>l.isControl);if(!s)return!1;this.log("Setting up template preview for type",s.type);const r=new URL(window.location.toString()),n=r.searchParams.get("view"),o=i.type===s.type;return!o&&!i.isControl&&template.suffix===s.affix&&this.typeFromTemplate()===s.type&&i.pathName!==null?(this.log("Hit control template type, redirecting to the variant url"),this.hidePage(),r.pathname=i.pathName,this.queueRedirect(r),!0):(!i.isControl&&this.typeFromTemplate()==i.type&&template.suffix===s.affix&&o&&n!==(i.affix||"__DEFAULT__")&&(this.log("Template type and affix match control, updating the view param"),r.searchParams.delete("view"),this.log("Setting the new viewParam to",i.affix||"__DEFAULT__"),this.hidePage(),r.searchParams.set("view",i.affix||"__DEFAULT__"),this.queueRedirect(r)),n!==null&&n!==(i.affix||"__DEFAULT__")&&(r.searchParams.delete("view"),this.hidePage(),this.queueRedirect(r)),!0)}handleUrlPreview(t){const e=t.currentVariant,i=t.variants.find(n=>n.id===e),s=t.variants.find(n=>n.isControl)?.redirectUrl;if(!i)return!1;this.log("Setting up URL redirect preview");const r=new URL(window.location.toString());return r.pathname===s&&!i.isControl&&i.redirectUrl!==null&&(this.log("Url matches control, redirecting"),this.hidePage(),r.pathname=i.redirectUrl,this.queueRedirect(r)),!0}handleScriptPreview(t){const e=t.currentVariant,i=t.variants.find(n=>n.id===e);if(!i)return!1;this.log("Setting up script preview");const s=new URL(window.location.toString());return s.searchParams.get("slVariant")!==i.id&&(this.log("current id doesn't match the variant, redirecting"),s.searchParams.delete("slVariant"),this.log("Setting the new slVariantParam"),this.hidePage(),s.searchParams.set("slVariant",i.id),this.queueRedirect(s)),!0}async handlePricePreview(t){const e=t.currentVariant,i=t.variants.find(s=>s.id===e);return i?(this.log("Setting up price preview"),i.domSelectors&&i.domSelectors.length>0&&(U(document,{testId:t.testId,hypothesisId:i.id,selectors:i.domSelectors}),this.ensureCartAttributesForExistingPriceTests(!0)),!0):!1}async handleSubscriptionPricePreview(t){const e=t.variants.find(i=>i.id===t.currentVariant);e?.subscriptionData&&(this.log("Setting up subscription price preview"),await Nt({id:e.id,isControl:e.isControl,subscriptionData:e.subscriptionData,priceData:e.priceData},(i,...s)=>this.log(i,...s)))}async handleSubscriptionLivePreview(t){this.testConfigs.find(s=>s.id===t.testId)?.hypotheses.find(s=>s.id===t.currentVariant)?.subscriptionData&&(this.log("Setting up subscription live preview"),this.subscriptionSwapDone=!1,this.subscriptionOneTimeDone=!1,this.subscriptionPriceDone=!1,await this.subscriptionSwap(),await this.subscriptionOneTimePrice(),await this.subscriptionPriceChange())}async finalize(){const t=await this.getCartState();t!==null&&this.queueCartUpdate(t),this.pruneStateAndSave(),await this.syncAllEvents()}setShoplift(){this.log("Setting up public API");const e=this.urlParams.get("slVariant")==="true",i=e?null:this.urlParams.get("slVariant");window.shoplift={isHypothesisActive:async s=>{if(this.log("Script checking variant for hypothesis '%s'",s),e)return this.log("Forcing variant for hypothesis '%s'",s),!0;if(i!==null)return this.log("Forcing hypothesis '%s'",i),s===i;const r=this.testConfigs.find(o=>o.hypotheses.some(l=>l.id===s));if(!r)return this.log("No test found for hypothesis '%s'",s),!1;const n=this.state.essential.visitorTests.find(o=>o.testId===r.id);return n?(this.log("Active visitor test found",s),n.hypothesisId===s):(await this.manuallySplitVisitor(r),this.testConfigs.some(o=>o.hypotheses.some(l=>l.id===s&&this.state.essential.visitorTests.some(c=>c.hypothesisId===l.id))))},setAnalyticsConsent:async s=>{await this.onConsentChange(s,!0)},getVisitorData:()=>({visitor:this.state.analytics.visitor,visitorTests:this.state.essential.visitorTests.filter(s=>!s.isInvalid).map(s=>{const{shouldSendToGa:r,savedAt:n,...o}=s;return o})})}}setShopliftStub(){this.log("Setting up stubbed public API");const e=this.urlParams.get("slVariant")==="true",i=e?null:this.urlParams.get("slVariant");window.shoplift={isHypothesisActive:s=>Promise.resolve(e||s===i),setAnalyticsConsent:()=>Promise.resolve(),getVisitorData:()=>({visitor:null,visitorTests:[]})}}async manuallySplitVisitor(t){this.log("Starting manual split for test '%s'",t.id),await this.handleVisitorTest([t]);const e=this.getReservationForTest(t.id);e&&!e.isRealized&&e.entryCriteriaKey&&(this.log("Realizing manual API reservation for test '%s'",t.id),this.realizeReservationForCriteria(e.entryCriteriaKey)),this.saveState(),this.syncAllEvents()}async handleVisitorTest(t){await this.filterTestsByAudience(this.testConfigs,this.state.analytics.visitor??this.buildBaseVisitor(),this.state.essential.visitorTests),this.pruneStaleVisitorTests(),this.deriveCategoryFromExistingTests(),this.clearStaleReservations();let e=t?t.filter(i=>this.testsFilteredByAudience.some(s=>s.id===i.id)):[...this.testsForUrl(this.testsFilteredByAudience),...this.domTestsForUrl(this.testsFilteredByAudience)];try{if(e.length===0)return this.log("No tests found"),!1;this.log("Checking for existing visitor test on page");const i=this.getCurrentVisitorHypothesis(e);if(i){this.log("Found current visitor test");const l=this.considerRedirect(i);return l&&(this.log("Redirecting for current visitor test"),this.redirect(i)),l}const s=this.getReservationForCurrentPage();if(s){this.log("Found matching reservation for current page: %s",s.testId);const l=this.getHypothesis(s.hypothesisId);if(l){l.type!=="price"&&this.realizeReservationForCriteria(s.entryCriteriaKey);const c=this.considerRedirect(l);return c&&this.redirect(l),c}}this.log("No active test relation for test page");const r=this.testsForUrl(this.inactiveTestConfigs.filter(l=>this.testIsPaused(l)&&l.hypotheses.some(c=>this.state.essential.visitorTests.some(d=>d.hypothesisId===c.id)))).map(l=>l.id);if(r.length>0)return this.log("Visitor has paused tests for test page, skipping test assignment: %o",r),!1;if(!this.state.temporary.testCategory){const l=this.testsFilteredByAudience.filter(d=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(d))),c=this.testsFilteredByAudience.filter(d=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(d)));if(this.log("Category dice roll - global tests: %o, conditional tests: %o",l.map(d=>({id:d.id,title:d.title,criteria:this.getEntryCriteriaKey(d)})),c.map(d=>({id:d.id,title:d.title,criteria:this.getEntryCriteriaKey(d)}))),l.length>0&&c.length>0){const d=l.length,p=c.length,h=d+p,u=Math.random()*h;this.state.temporary.testCategory=u<d?"global":"conditional",this.log("Category dice roll: rolled %.2f of %d (global weight: %d, conditional weight: %d), selected '%s'",u,h,d,p,this.state.temporary.testCategory)}else l.length>0?(this.state.temporary.testCategory="global",this.log("Only global tests available, setting category to global")):(this.state.temporary.testCategory="conditional",this.log("Only conditional tests available, setting category to conditional"));this.persistTemporaryState()}const n=this.state.temporary.testCategory;if(this.log("Visitor test category: %s",n),n==="global"){const l=this.testsFilteredByAudience.filter(c=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)));for(const c of l)this.markTestAsBlocked(c,"category:global");e=e.filter(c=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)))}else{const l=this.testsFilteredByAudience.filter(c=>this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)));for(const c of l)this.markTestAsBlocked(c,"category:conditional");e=e.filter(c=>!this.isGlobalEntryCriteria(this.getEntryCriteriaKey(c)))}if(e.length===0)return this.log("No tests remaining after category filter"),!1;this.createReservations(e);const o=this.getReservationForCurrentPage();if(o&&!o.isRealized){const l=this.getHypothesis(o.hypothesisId);if(l){l.type!=="price"&&this.realizeReservationForCriteria(o.entryCriteriaKey);const c=this.considerRedirect(l);return c&&(this.log("Redirecting for new test"),this.redirect(l)),c}}return!1}finally{this.includeInDomTests(),this.saveState()}}includeInDomTests(){this.applyControlForAudienceFilteredPriceTests();const t=this.getDomTestsForCurrentUrl(),e=this.getVisitorDomHypothesis(t);for(const i of t){this.log("Evaluating dom test '%s'",i.id);const s=i.hypotheses.some(u=>u.type==="price");if(this.state.essential.visitorTests.find(u=>u.testId===i.id&&u.isInvalid&&!u.hypothesisId)){if(this.log("Visitor is blocked from test '%s', applying control prices if price test",i.id),s){const u=i.hypotheses.find(b=>b.isControl);u?.priceData&&(this.applyPriceTestWithMapLookup(i.id,u,[u],()=>{this.log("Control prices applied for blocked visitor, no metrics tracked")}),this.updatePriceTestHiddenInputs(i.id,"control",!1))}continue}const n=this.getReservationForTest(i.id);let o=null,l=!1;const c=e.find(u=>i.hypotheses.some(b=>u.id===b.id));if(n)o=this.getHypothesis(n.hypothesisId)??null,this.log("Using reserved hypothesis '%s' for test '%s'",n.hypothesisId,i.id);else if(c)o=c,this.log("Using existing hypothesis assignment for test '%s'",i.id);else if(s){const u=this.visitorActiveTestTypeWithReservations();u?(l=!0,this.log("Visitor already in test type '%s', treating as non-test for price test '%s'",u,i.id)):o=this.pickHypothesis(i)}else o=this.pickHypothesis(i);if(l&&s){const u=i.hypotheses.find(b=>b.isControl);u?.priceData&&(this.log("Applying control prices for non-test visitor on price test '%s' (Map-based)",i.id),this.applyPriceTestWithMapLookup(i.id,u,[u],()=>{this.log("Control prices applied for non-test visitor, no metrics tracked")}),this.updatePriceTestHiddenInputs(i.id,"control",!1));continue}if(!o){this.log("Failed to pick hypothesis for test");continue}this.sendDiagnosticTelemetry("assignment",i.id,{hypothesisId:o.id,isControl:o.isControl,testType:o.type});const d=i.bayesianRevision??4,p=o.type==="price",h=d>=5;if(p&&h){if(this.log(`Price test with Map-based lookup (v${d}): ${i.id}`),!o.priceData){this.log("No price data for hypothesis '%s', skipping",o.id);continue}const u=o.isControl?"control":"variant";this.log(`Setting up Map-based price test for ${u} (test: ${i.id})`),this.applyPriceTestWithMapLookup(i.id,o,i.hypotheses,b=>{const k=this.getReservationForTest(b);k&&!k.isRealized&&k.entryCriteriaKey?this.realizeReservationForCriteria(k.entryCriteriaKey):this.queueAddVisitorToTest(b,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()});continue}if(p&&!h){this.log(`Price test without viewport tracking (v${d}): ${i.id}`);const u=this.getDomSelectorsForHypothesis(o);if(u.length===0)continue;U(document,{testId:i.id,hypothesisId:o.id,selectors:u},b=>{this.queueAddVisitorToTest(b,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()});continue}if(!o.domSelectors||o.domSelectors.length===0){this.log("No selectors found, skipping hypothesis");continue}U(document,{testId:i.id,hypothesisId:o.id,selectors:o.domSelectors},u=>{this.queueAddVisitorToTest(u,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()})}}considerRedirect(t){if(this.log("Considering redirect for hypothesis '%s'",t.id),t.isControl)return this.log("Skipping redirect for control"),!1;if(t.type==="basicScript"||t.type==="manualScript")return this.log("Skipping redirect for script test"),!1;const e=this.state.essential.visitorTests.find(n=>n.hypothesisId===t.id),i=new URL(window.location.toString()),r=new URLSearchParams(window.location.search).get("view");if(t.type==="theme"){if(!(t.themeId===themeId)){if(this.log("Theme id '%s' is not hypothesis theme ID '%s'",t.themeId,themeId),this.isAppProxyPath())return this.log("On App Proxy path, skipping theme redirect to avoid infinite loop"),!1;if(e&&e.themeId!==t.themeId&&(e.themeId===themeId||!this.isThemePreview()))this.log("On old theme, redirecting and updating local visitor"),e.themeId=t.themeId;else if(this.isThemePreview())return this.log("On non-test theme, skipping redirect"),!1;return this.log("Hiding page to redirect for theme test"),this.hidePage(),!0}return!1}else if(t.type!=="dom"&&t.type!=="price"&&t.affix!==template.suffix&&t.affix!==r||t.redirectPath&&!i.pathname.endsWith(t.redirectPath))return this.log("Hiding page to redirect for template test"),this.hidePage(),!0;return this.log("Not redirecting"),!1}redirect(t){if(this.log("Redirecting to hypothesis '%s'",t.id),t.isControl)return;const e=new URL(window.location.toString());if(e.searchParams.delete("view"),t.redirectPath){const i=RegExp("^(/w{2}-w{2})/").exec(e.pathname);if(i&&i.length>1){const s=i[1];e.pathname=`${s}${t.redirectPath}`}else e.pathname=t.redirectPath}else t.type==="theme"?(e.searchParams.set("_ab","0"),e.searchParams.set("_fd","0"),e.searchParams.set("_sc","1"),e.searchParams.set("preview_theme_id",t.themeId.toString())):t.type!=="urlRedirect"&&e.searchParams.set("view",t.affix);this.queueRedirect(e)}async refreshVisitor(t){if(t===null||!this.state.essential.isFirstLoad||!this.testConfigs.some(i=>i.visitorOption!=="all"))return;this.log("Refreshing visitor"),this.hidePage();const e=await this.getVisitor(t);e&&e.id&&this.updateLocalVisitor(e)}buildBaseVisitor(){return{shopifyAnalyticsId:this.shopifyAnalyticsId,device:this.device,country:null,...this.state.essential.initialState}}getInitialState(){const t=this.getUTMValue("utm_source")??"",e=this.getUTMValue("utm_medium")??"",i=this.getUTMValue("utm_campaign")??"",s=this.getUTMValue("utm_content")??"",r=window.document.referrer,n=this.device;return{createdAt:new Date,utmSource:t,utmMedium:e,utmCampaign:i,utmContent:s,referrer:r,device:n}}checkForThemePreview(){return this.log("Checking for theme preview"),window.location.hostname.endsWith(".shopifypreview.com")?(this.log("on shopify preview domain"),this.clearThemeBar(!0,!1,this.state),document.querySelector("#sl-preview-bar-hide")?.remove(),!1):this.isThemePreview()?this.state.essential.visitorTests.some(t=>t.isThemeTest&&t.hypothesisId!=null&&this.getHypothesis(t.hypothesisId)&&t.themeId===themeId)?(this.log("On active theme test, removing theme bar"),this.clearThemeBar(!1,!0,this.state),!1):this.state.essential.visitorTests.some(t=>t.isThemeTest&&t.hypothesisId!=null&&!this.getHypothesis(t.hypothesisId)&&t.themeId===themeId)?(this.log("Visitor is on an inactive theme test, redirecting to main theme"),this.redirectToMainTheme(),!0):this.state.essential.isFirstLoad?(this.log("No visitor found on theme preview, redirecting to main theme"),this.redirectToMainTheme(),!0):this.inactiveTestConfigs.some(t=>t.hypotheses.some(e=>e.themeId===themeId))?(this.log("Current theme is an inactive theme test, redirecting to main theme"),this.redirectToMainTheme(),!0):this.testConfigs.some(t=>t.hypotheses.some(e=>e.themeId===themeId))?(this.log("Falling back to clearing theme bar"),this.clearThemeBar(!1,!0,this.state),!1):(this.log("No tests on current theme, skipping script"),this.clearThemeBar(!0,!1,this.state),document.querySelector("#sl-preview-bar-hide")?.remove(),!0):(this.log("Not on theme preview"),this.clearThemeBar(!0,!1,this.state),!1)}redirectToMainTheme(){this.hidePage();const t=new URL(window.location.toString());t.searchParams.set("preview_theme_id",""),this.queueRedirect(t)}testsForUrl(t){const e=new URL(window.location.href),i=this.typeFromTemplate();return t.filter(s=>s.hypotheses.some(r=>r.type!=="dom"&&r.type!=="price"&&(r.isControl&&r.type===i&&r.affix===template.suffix||r.type==="theme"||r.isControl&&r.type==="urlRedirect"&&r.redirectPath&&e.pathname.endsWith(r.redirectPath)||r.type==="basicScript"))&&(s.ignoreTestViewParameterEnforcement||!e.searchParams.has("view")||s.hypotheses.map(r=>r.affix).includes(e.searchParams.get("view")??"")))}domTestsForUrl(t){const e=new URL(window.location.href);return t.filter(i=>i.hypotheses.some(s=>s.type!=="dom"&&s.type!=="price"?!1:s.type==="price"&&s.priceData&&s.priceData.variants.length>0?!0:s.domSelectors&&s.domSelectors.some(r=>new RegExp(it(r)).test(e.toString()))))}async filterTestsByAudience(t,e,i){const s=[];let r=e.country;!r&&t.some(n=>n.requiresCountry&&!i.some(o=>o.testId===n.id))&&(this.log("Hiding page to check geoip"),this.hidePage(),r=await this.makeJsonRequest({method:"get",url:`${this.eventHost}/api/v0/visitors/get-country`,signal:AbortSignal.timeout(this.getCountryTimeout)}).catch(n=>(this.log("Error getting country",n),null)));for(const n of t){if(this.log("Checking audience for test '%s'",n.id),this.state.essential.visitorTests.some(c=>c.testId===n.id&&c.hypothesisId==null)){console.log(`Skipping blocked test '${n.id}'`);continue}const o=this.visitorCreatedDuringTestActive(n.statusHistory);(i.some(c=>c.testId===n.id&&(n.device==="all"||n.device===e.device&&n.device===this.device))||this.isTargetAudience(n,e,o,r))&&(this.log("Visitor is in audience for test '%s'",n.id),s.push(n))}this.testsFilteredByAudience=s}isTargetAudience(t,e,i,s){const r=this.getChannel(e);return(t.device==="all"||t.device===e.device&&t.device===this.device)&&(t.visitorOption==="all"||t.visitorOption==="new"&&i||t.visitorOption==="returning"&&!i)&&(t.targetAudiences.length===0||t.targetAudiences.reduce((n,o)=>n||o.reduce((l,c)=>l&&c(e,i,r,s),!0),!1))}visitorCreatedDuringTestActive(t){let e="";for(const i of t){if(this.state.analytics.visitor!==null&&this.state.analytics.visitor.createdAt<i.createdAt||this.state.essential.initialState.createdAt<i.createdAt)break;e=i.status}return e==="active"}getDomTestsForCurrentUrl(){return this.domTestsForUrl(this.testsFilteredByAudience)}getCurrentVisitorHypothesis(t){return t.flatMap(e=>e.hypotheses).find(e=>e.type!=="dom"&&e.type!=="price"&&this.state.essential.visitorTests.some(i=>i.hypothesisId===e.id))}getVisitorDomHypothesis(t){return t.flatMap(e=>e.hypotheses).filter(e=>(e.type==="dom"||e.type==="price")&&this.state.essential.visitorTests.some(i=>i.hypothesisId===e.id))}getHypothesis(t){return this.testConfigs.filter(e=>e.hypotheses.some(i=>i.id===t)).map(e=>e.hypotheses.find(i=>i.id===t))[0]}getActiveAssignment(){if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const e=this.state.temporary.previewConfig;return e.currentVariant&&e.testId?{testId:e.testId,hypothesisId:e.currentVariant}:null}const t=this.state.essential.visitorTests.find(e=>e.hypothesisId);return t?.hypothesisId?{testId:t.testId,hypothesisId:t.hypothesisId}:null}findActiveSubscriptionTestControl(){for(const t of this.testConfigs){const e=t.hypotheses.find(i=>i.isControl);if(e?.subscriptionData)return{testId:t.id,hypothesis:e}}return null}getDomSelectorsForHypothesis(t){if(!t)return[];if(t.domSelectors&&t.domSelectors.length>0)return t.domSelectors;if(t.priceData){const e=`${this.priceSelectorsSessionKey}_${t.id}`;try{const s=sessionStorage.getItem(e);if(s){const r=JSON.parse(s);return t.domSelectors=r,this.log("Loaded %d price selectors from cache for hypothesis '%s'",r.length,t.id),r}}catch{}const i=Ot(t.priceData);t.domSelectors=i;try{sessionStorage.setItem(e,JSON.stringify(i)),this.log("Generated and cached %d price selectors for hypothesis '%s'",i.length,t.id)}catch{this.log("Generated %d price selectors for hypothesis '%s' (cache unavailable)",i.length,t.id)}return i}return[]}hasThemeTest(t){return t.some(e=>e.hypotheses.some(i=>i.type==="theme"))}hasTestThatIsNotThemeTest(t){return t.some(e=>e.hypotheses.some(i=>i.type!=="theme"&&i.type!=="dom"&&i.type!=="price"))}hasThemeAndOtherTestTypes(t){return this.hasThemeTest(t)&&this.hasTestThatIsNotThemeTest(t)}testIsPaused(t){return t.status==="paused"||t.status==="incompatible"||t.status==="suspended"}visitorActiveTestType(){const t=this.state.essential.visitorTests.filter(e=>this.testConfigs.some(i=>i.hypotheses.some(s=>s.id==e.hypothesisId)));return t.length===0?null:t.some(e=>e.isThemeTest)?"theme":"templateOrUrlRedirect"}getReservationType(t){return t==="price"||this.isTemplateTestType(t)?"deferred":"immediate"}isTemplateTestType(t){return["product","collection","landing","index","cart","search","blog","article","collectionList"].includes(t)}getEntryCriteriaKey(t){const e=t.hypotheses.find(i=>i.isControl);if(!e)return`unknown:${t.id}`;switch(e.type){case"theme":return"global:theme";case"basicScript":return"global:autoApi";case"price":return"global:price";case"manualScript":return`conditional:manualApi:${t.id}`;case"urlRedirect":return`conditional:url:${e.redirectPath||"unknown"}`;default:return`conditional:template:${e.type}`}}isGlobalEntryCriteria(t){return t.startsWith("global:")}groupTestsByEntryCriteria(t){const e=new Map;for(const i of t){const s=this.getEntryCriteriaKey(i),r=e.get(s)||[];r.push(i),e.set(s,r)}return e}doesCurrentPageMatchEntryCriteria(t){if(this.isGlobalEntryCriteria(t))return!0;if(t==="conditional:manualApi")return!1;if(t.startsWith("conditional:url:")){const e=t.replace("conditional:url:","");return window.location.pathname.endsWith(e)}if(t.startsWith("conditional:template:")){const e=t.replace("conditional:template:","");return this.typeFromTemplate()===e}return!1}hasActiveReservation(){const t=this.getActiveReservations();return Object.values(t).some(e=>!e.isRealized)}getActiveReservation(){const t=this.getActiveReservations();return Object.values(t).find(e=>!e.isRealized)??null}clearStaleReservations(){const t=this.state.temporary.testReservations;if(!t)return;let e=!1;for(const[i,s]of Object.entries(t)){const r=this.testConfigs.find(o=>o.id===s.testId);if(!r){this.log("Test '%s' no longer in config, clearing reservation for criteria '%s'",s.testId,i),delete t[i],e=!0;continue}if(r.status!=="active"){this.log("Test '%s' status is '%s', clearing reservation for criteria '%s'",s.testId,r.status,i),delete t[i],e=!0;continue}this.testsFilteredByAudience.some(o=>o.id===s.testId)||(this.log("Visitor no longer passes audience for test '%s', clearing reservation for criteria '%s'",s.testId,i),delete t[i],e=!0)}e&&this.persistTemporaryState()}createReservations(t){if(this.state.temporary.testReservations||(this.state.temporary.testReservations={}),this.state.temporary.rolledEntryCriteria||(this.state.temporary.rolledEntryCriteria=[]),this.state.temporary.testCategory==="global"){this.createSingleReservation(t,"global");return}const i=t.filter(o=>this.doesCurrentPageMatchEntryCriteria(this.getEntryCriteriaKey(o))),s=t.filter(o=>!this.doesCurrentPageMatchEntryCriteria(this.getEntryCriteriaKey(o)));this.log("Conditional tests split - matching current page: %d, not matching: %d",i.length,s.length),i.length>0&&this.log("Tests matching current page (same pool): %o",i.map(o=>({id:o.id,title:o.title,criteria:this.getEntryCriteriaKey(o)})));const r=`conditional:current-page:${this.typeFromTemplate()}`;if(i.length>0&&!this.state.temporary.rolledEntryCriteria.includes(r)){this.createSingleReservation(i,r);for(const o of i){const l=this.getEntryCriteriaKey(o);this.state.temporary.rolledEntryCriteria.includes(l)||this.state.temporary.rolledEntryCriteria.push(l)}}const n=this.groupTestsByEntryCriteria(s);for(const[o,l]of n){if(this.state.temporary.rolledEntryCriteria.includes(o)){this.log("Already rolled for criteria '%s', skipping",o);continue}if(l.some(S=>this.state.essential.visitorTests.some(P=>P.testId===S.id))){this.log("Visitor already has VT for criteria '%s', skipping",o),this.state.temporary.rolledEntryCriteria.push(o);continue}const d=[...l].sort((S,P)=>S.id.localeCompare(P.id));this.log("Test dice roll for criteria '%s' - available tests: %o",o,d.map(S=>({id:S.id,title:S.title})));const p=Math.floor(Math.random()*d.length),h=d[p];this.log("Test dice roll: picked index %d of %d, selected test '%s' (%s)",p+1,l.length,h.id,h.title);const u=this.pickHypothesis(h);if(!u){this.log("No hypothesis picked for test '%s'",h.id);continue}this.sendDiagnosticTelemetry("assignment",h.id,{hypothesisId:u.id,isControl:u.isControl,testType:u.type});const b=this.getReservationType(u.type),k={testId:h.id,hypothesisId:u.id,testType:u.type,reservationType:b,isThemeTest:u.type==="theme",themeId:u.themeId,createdAt:new Date,isRealized:!1,entryCriteriaKey:o};this.state.temporary.testReservations[o]=k,this.state.temporary.rolledEntryCriteria.push(o),this.log("Created %s reservation for test '%s' (criteria: %s)",b,h.id,o);for(const S of l)S.id!==h.id&&this.markTestAsBlocked(S,o)}this.persistTemporaryState()}createSingleReservation(t,e){if(this.state.temporary.rolledEntryCriteria.includes(e)){this.log("Already rolled for pool '%s', skipping",e);return}if(t.some(p=>this.state.essential.visitorTests.some(h=>h.testId===p.id&&!h.isInvalid))){this.log("Visitor already has VT for pool '%s', skipping",e),this.state.temporary.rolledEntryCriteria.push(e);return}if(t.length===0){this.log("No tests in pool '%s'",e);return}const s=[...t].sort((p,h)=>p.id.localeCompare(h.id));this.log("Test dice roll for pool '%s' - available tests: %o",e,s.map(p=>({id:p.id,title:p.title,criteria:this.getEntryCriteriaKey(p)})));const r=Math.floor(Math.random()*s.length),n=s[r];this.log("Test dice roll: picked index %d of %d, selected test '%s' (%s)",r,t.length,n.id,n.title);const o=this.pickHypothesis(n);if(!o){this.log("No hypothesis picked for test '%s'",n.id);return}this.sendDiagnosticTelemetry("assignment",n.id,{hypothesisId:o.id,isControl:o.isControl,testType:o.type});const l=this.getReservationType(o.type),c=this.getEntryCriteriaKey(n),d={testId:n.id,hypothesisId:o.id,testType:o.type,reservationType:l,isThemeTest:o.type==="theme",themeId:o.themeId,createdAt:new Date,isRealized:!1,entryCriteriaKey:c};this.state.temporary.testReservations[c]=d,this.state.temporary.rolledEntryCriteria.push(e),this.log("Created %s reservation for test '%s' from pool '%s' (criteria: %s)",l,n.id,e,c);for(const p of t)p.id!==n.id&&this.markTestAsBlocked(p,`pool:${e}`);this.persistTemporaryState()}markTestAsBlocked(t,e){this.state.essential.visitorTests.some(i=>i.testId===t.id)||(this.log("Blocking visitor from test '%s' (reason: %s)",t.id,e),this.state.essential.visitorTests.push({createdAt:new Date,testId:t.id,hypothesisId:null,isThemeTest:t.hypotheses.some(i=>i.type==="theme"),shouldSendToGa:!1,isSaved:!0,isInvalid:!0,themeId:void 0}))}realizeReservationForCriteria(t){const e=this.state.temporary.testReservations?.[t];if(!e)return this.log("No reservation found for criteria '%s'",t),!1;if(e.isRealized)return this.log("Reservation already realized for criteria '%s'",t),!1;if(this.state.essential.visitorTests.some(s=>s.testId===e.testId&&!s.isInvalid))return this.log("Visitor already assigned to test '%s'",e.testId),!1;const i=this.getHypothesis(e.hypothesisId);return i?(e.isRealized=!0,this.persistTemporaryState(),this.queueAddVisitorToTest(e.testId,i),this.saveState(),this.log("Realized reservation for test '%s' (criteria: %s)",e.testId,t),!0):(this.log("Hypothesis '%s' not found",e.hypothesisId),!1)}getActiveReservations(){return this.state.temporary.testReservations??{}}getReservationForCurrentPage(){const t=this.getActiveReservations();for(const[e,i]of Object.entries(t)){if(i.isRealized)continue;const s=this.testConfigs.find(r=>r.id===i.testId);if(!(!s||s.status!=="active")&&this.doesCurrentPageMatchEntryCriteria(e))return i}return null}getReservationForTest(t){const e=this.getActiveReservations();return Object.values(e).find(i=>i.testId===t)??null}getReservationTestType(){const t=this.getActiveReservations(),e=Object.values(t);if(e.length===0)return null;for(const i of e)if(i.isThemeTest)return"theme";for(const i of e)if(i.testType==="price")return"price";return e.some(i=>!i.isRealized)?"templateOrUrlRedirect":null}hasPriceTests(t){return t.some(e=>e.hypotheses.some(i=>i.type==="price"))}_priceTestProductIds=null;getPriceTestProductIds(){if(this._priceTestProductIds)return this._priceTestProductIds;const t=new Set;for(const e of this.testConfigs)for(const i of e.hypotheses)if(i.type==="price"){for(const s of i.domSelectors||[]){const r=s.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);r?.[1]&&t.add(r[1])}if(i.priceData?.variants)for(const[s]of i.priceData.variants)t.add(s)}return this._priceTestProductIds=t,this.log("Built price test product ID cache with %d products",t.size),t}isProductInAnyPriceTest(t){return this.getPriceTestProductIds().has(t)}visitorActiveTestTypeWithReservations(){const t=this.getActiveReservations();for(const r of Object.values(t)){if(r.isThemeTest)return"theme";if(r.testType==="price")return"price"}if(Object.values(t).some(r=>!r.isRealized)){if(this.state.temporary.testCategory==="global")for(const n of Object.values(t)){if(n.testType==="theme")return"theme";if(n.testType==="price")return"price";if(n.testType==="basicScript")return"theme"}return"templateOrUrlRedirect"}const i=this.state.essential.visitorTests.filter(r=>!r.isInvalid&&this.testConfigs.some(n=>n.hypotheses.some(o=>o.id===r.hypothesisId)));return i.length===0?null:i.some(r=>this.getHypothesis(r.hypothesisId)?.type==="price")?"price":i.some(r=>r.isThemeTest)?"theme":"templateOrUrlRedirect"}applyControlForAudienceFilteredPriceTests(){const t=this.testConfigs.filter(s=>s.status==="active"&&s.hypotheses.some(r=>r.type==="price"));if(t.length===0)return;const e=this.testsFilteredByAudience.filter(s=>s.hypotheses.some(r=>r.type==="price")),i=t.filter(s=>!e.some(r=>r.id===s.id));if(i.length!==0){this.log("Found %d price tests filtered by audience, applying control selectors",i.length);for(const s of i){const r=s.hypotheses.find(c=>c.isControl),n=this.getDomSelectorsForHypothesis(r);if(n.length===0){this.log("No control selectors for audience-filtered price test '%s'",s.id);continue}const o=new URL(window.location.href);n.some(c=>{try{return new RegExp(it(c)).test(o.toString())}catch{return!1}})&&(this.log("Applying control selectors for audience-filtered price test '%s'",s.id),U(document,{testId:s.id,hypothesisId:r.id,selectors:n},()=>{}),this.updatePriceTestHiddenInputs(s.id,"control",!1))}}}pickHypothesis(t){let e=Math.random();const i=t.hypotheses.reduce((r,n)=>r+n.visitorCount,0);return t.hypotheses.sort((r,n)=>r.isControl?n.isControl?0:-1:n.isControl?1:0).reduce((r,n)=>{if(r!==null)return r;const l=t.hypotheses.reduce((c,d)=>c&&d.visitorCount>20,!0)?n.visitorCount/i-n.trafficPercentage:0;return e<=n.trafficPercentage-l?n:(e-=n.trafficPercentage-l,null)},null)}typeFromTemplate(){switch(template.type){case"list-collections":return"collectionList";case"page":return"landing";case"article":case"blog":case"cart":case"collection":case"index":case"product":case"search":return template.type;default:return null}}queueRedirect(t){this.saveState(),this.disableReferrerOverride||(this.log(`Saving temporary referrer override '${document.referrer}'`),this.state.temporary.originalReferrer=document.referrer,this.persistTemporaryState()),window.setTimeout(()=>window.location.assign(t),0),window.setTimeout(()=>{this.syncAllEvents()},2e3)}scheduleRetrySync(){this.clientIdRetryCount>=5||(this.clientIdRetryCount++,window.setTimeout(()=>{this.syncAllEvents()},500))}async syncAllEvents(){const t=async()=>{if(this.isSyncing){window.setTimeout(()=>{(async()=>await t())()},500);return}try{if(this.isSyncing=!0,this.syncGAEvents(),this.shopifyAnalyticsId||(this.shopifyAnalyticsId=this.getShopifyAnalyticsId()),!this.shopifyAnalyticsId){this.scheduleRetrySync();return}await this.syncEvents()}finally{this.isSyncing=!1}};await t()}async syncEvents(){if(!this.state.essential.consentApproved||!this.shopifyAnalyticsId||this.state.analytics.queue.length===0)return;const t=this.state.analytics.queue.length,e=this.state.analytics.queue.splice(0,t);this.log("Syncing %s events",t);try{const i={shop:this.shop,visitorDetails:{shopifyAnalyticsId:this.shopifyAnalyticsId,device:this.state.analytics.visitor?.device??this.device,country:this.state.analytics.visitor?.country??null,...this.state.essential.initialState},events:this.state.essential.visitorTests.filter(r=>!r.isInvalid&&!r.isSaved&&r.hypothesisId!=null).map(r=>new yt(r.testId,r.hypothesisId,r.createdAt)).concat(e)};await this.sendEvents(i);for(const r of this.state.essential.visitorTests.filter(n=>!n.isInvalid&&!n.isSaved&&n.hypothesisId!=null))this.sendDiagnosticTelemetry("event-delivered",r.testId,{hypothesisId:r.hypothesisId,isControl:r.assignedTo==="control",testType:r.testType??"unknown"});const s=await this.getVisitor(this.shopifyAnalyticsId);s!==null&&this.updateLocalVisitor(s);for(const r of this.state.essential.visitorTests.filter(n=>!n.isInvalid&&!n.isSaved))r.isSaved=!0,r.savedAt=Date.now()}catch{this.state.analytics.queue.splice(0,0,...e)}finally{this.saveState()}}syncGAEvents(){if(!this.gaConfig.sendEvents){if(pt)return;pt=!0,this.log("UseGtag is false — skipping GA Events");return}if(this.isSyncingGA){this.log("Already syncing GA - skipping GA events");return}const t=this.state.essential.visitorTests.filter(e=>e.shouldSendToGa);t.length!==0&&(this.isSyncingGA=!0,this.log("Syncing %s GA Events",t.length),Promise.allSettled(t.map(e=>this.sendGAEvent(e))).then(()=>this.log("All gtag events sent")).finally(()=>this.isSyncingGA=!1))}sendGAEvent(t){return new Promise(e=>{this.log("Sending GA Event for test %s, hypothesis %s",t.testId,t.hypothesisId);const i=()=>{this.log("GA acknowledged event for hypothesis %s",t.hypothesisId),t.shouldSendToGa=!1,this.persistEssentialState(),e()},s={exp_variant_string:`SL-${t.testId}-${t.hypothesisId}`};this.shopliftDebug&&Object.assign(s,{debug_mode:!0});function r(n,o,l){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}this.gaConfig.mode==="gtag"?r("event","experience_impression",{...s,event_callback:i}):(window.dataLayer=window.dataLayer||[],window.dataLayer.push({event:"experience_impression",...s,eventCallback:i}))})}updateLocalVisitor(t){let e;({visitorTests:e,...this.state.analytics.visitor}=t),this.log("updateLocalVisitor - server returned %d tests: %o",e.length,e.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isInvalid:s.isInvalid}))),this.log("updateLocalVisitor - local has %d tests: %o",this.state.essential.visitorTests.length,this.state.essential.visitorTests.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isSaved:s.isSaved,isInvalid:s.isInvalid})));const i=300*1e3;for(const s of this.state.essential.visitorTests.filter(r=>r.isSaved&&(!r.savedAt||Date.now()-r.savedAt>i)&&!e.some(n=>n.testId===r.testId)))this.log("updateLocalVisitor - marking LOCAL test as INVALID (isSaved && not in server): testId=%s, hypothesisId=%s",s.testId,s.hypothesisId),s.isInvalid=!0;for(const s of e){const r=this.state.essential.visitorTests.findIndex(o=>o.testId===s.testId);if(!(r!==-1))this.log("updateLocalVisitor - ADDING server test (not found locally): testId=%s, hypothesisId=%s",s.testId,s.hypothesisId),this.state.essential.visitorTests.push(s);else{const o=this.state.essential.visitorTests.at(r);this.log("updateLocalVisitor - REPLACING local test with server test: testId=%s, local hypothesisId=%s -> server hypothesisId=%s, local isInvalid=%s -> false",s.testId,o?.hypothesisId,s.hypothesisId,o?.isInvalid),s.isInvalid=!1,s.shouldSendToGa=o?.shouldSendToGa??!1,s.testType=o?.testType,s.assignedTo=o?.assignedTo,s.testTitle=o?.testTitle,this.state.essential.visitorTests.splice(r,1,s)}}this.log("updateLocalVisitor - FINAL local tests: %o",this.state.essential.visitorTests.map(s=>({testId:s.testId,hypothesisId:s.hypothesisId,isSaved:s.isSaved,isInvalid:s.isInvalid}))),this.state.analytics.visitor.storedAt=new Date}async getVisitor(t){try{return await this.makeJsonRequest({method:"get",url:`${this.eventHost}/api/v0/visitors/by-key/${this.shop}/${t}`})}catch{return null}}async sendEvents(t){await this.makeRequest({method:"post",url:`${this.eventHost}/api/v0/events`,data:JSON.stringify(t)})}sendDiagnosticTelemetry(t,e,i){if(!this.telemetryEnabled||!navigator.sendBeacon)return;const s=this.state.essential.consentApproved,r=JSON.stringify({shop:this.shop,testId:e,checkpoint:t,device:this.device,...s?{visitorId:this.shopifyAnalyticsId??"unknown"}:{},clientTimestamp:Date.now(),consentApproved:s,hasConsentInteraction:this.state.essential.hasConsentInteraction,...i});navigator.sendBeacon(`${this.eventHost}/api/v0/telemetry`,new Blob([r],{type:"text/plain"}))}getUTMValue(t){const i=decodeURIComponent(window.location.search.substring(1)).split("&");for(let s=0;s<i.length;s++){const r=i[s].split("=");if(r[0]===t)return r[1]||null}return null}hidePage(t){this.log("Hiding page"),this.cssHideClass&&!window.document.documentElement.classList.contains(this.cssHideClass)&&(window.document.documentElement.classList.add(this.cssHideClass),t||setTimeout(this.removeAsyncHide(this.cssHideClass),2e3))}showPage(){this.cssHideClass&&this.removeAsyncHide(this.cssHideClass)()}getDeviceType(){function t(){let i=!1;return(function(s){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(s)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(s.substr(0,4)))&&(i=!0)})(navigator.userAgent||navigator.vendor),i}function e(){let i=!1;return(function(s){(/android|ipad|playbook|silk/i.test(s)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(s.substr(0,4)))&&(i=!0)})(navigator.userAgent||navigator.vendor),i}return t()?"mobile":e()?"tablet":"desktop"}removeAsyncHide(t){return()=>{t&&window.document.documentElement.classList.remove(t)}}async getCartState(){try{let t=await this.makeJsonRequest({method:"get",url:`${window.location.origin}/cart.js`});return t===null||(t.note===null&&(t=await this.makeJsonRequest({method:"post",url:`${window.location.origin}/cart/update.js`,data:JSON.stringify({note:""})})),t==null)?null:{token:t.token,total_price:t.total_price,total_discount:t.total_discount,currency:t.currency,items_subtotal_price:t.items_subtotal_price,items:t.items.map(e=>({quantity:e.quantity,variant_id:e.variant_id,key:e.key,price:e.price,final_line_price:e.final_line_price,sku:e.sku,product_id:e.product_id}))}}catch(t){return this.log("Error sending cart info",t),null}}ensureCartAttributesForExistingPriceTests(t){try{if(this.log("Checking visitor assignments for active price tests"),t&&this.state.temporary.previewConfig){const e=this.state.temporary.previewConfig;this.log("Using preview config for merchant:",e.testId);let i="variant";if(e.variants&&e.variants.length>0){const s=e.variants.find(r=>r.id===e.currentVariant);s&&s.isControl&&(i="control")}this.log("Merchant preview - updating hidden inputs:",e.testId,i),this.updatePriceTestHiddenInputs(e.testId,i,!0);return}for(const e of this.state.essential.visitorTests){const i=this.testConfigs.find(n=>n.id===e.testId);if(!i){this.log("Test config not found:",e.testId);continue}const s=i.hypotheses.find(n=>n.id===e.hypothesisId);if(!s||s.type!=="price")continue;const r=s.isControl?"control":"variant";this.log("Updating hidden inputs for price test:",e.testId,r),this.updatePriceTestHiddenInputs(e.testId,r,t)}}catch(e){this.log("Error ensuring cart attributes for existing price tests:",e)}}subscriptionSwapDone=!1;subscriptionHideWrongPlans=null;subscriptionPriceDone=!1;subscriptionUpdateOneTime=null;subscriptionOneTimeDone=!1;swapMap=null;slptValue=null;async subscriptionSwap(){await Lt(this)}async subscriptionPriceChange(){await qt(this)}async subscriptionOneTimePrice(){await Ht(this)}updatePriceTestHiddenInputs(t,e,i){try{this.cleanupPriceTestObservers();const s=`${t}:${e}:${i?"t":"f"}`,r=C=>{const m=C.getAttribute("data-sl-pid");if(!m)return!0;if(i&&this.state.temporary.previewConfig){const w=this.state.temporary.previewConfig,T=e==="control"?"a":"b",f=w.variants.find(v=>v.label===T);if(!f)return!1;for(const v of f.domSelectors||[]){const g=v.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);if(g){const I=g[1];if(this.log(`Extracted ID from selector: ${I}, comparing to: ${m}`),I===m)return this.log("Product ID match found in preview config:",m,"variant:",f.label),!0}else this.log(`Could not extract ID from selector: ${v.cssSelector}`)}return this.log("No product ID match in preview config for:",m,"variant:",T),!1}const y=this.testConfigs.find(w=>w.id===t);if(!y)return this.log("Test config not found for testId:",t),!1;for(const w of y.hypotheses||[]){for(const T of w.domSelectors||[]){const f=T.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);if(f&&f[1]===m)return this.log("Product ID match found in domSelectors:",m,"for test:",t),!0}if(w.priceData?.variants){for(const T of w.priceData.variants)if(T[0]===m)return this.log("Product ID match found in priceData:",m,"for test:",t),!0}}return this.log("No product ID match for:",m,"in test:",t),!1},n=new Set;let o=!1,l=null;const c=(C,m)=>{if(document.querySelectorAll("[data-sl-attribute-p]").forEach(w=>{if(w instanceof Element&&w.nodeType===Node.ELEMENT_NODE&&w.isConnected&&document.contains(w))try{C.observe(w,{childList:!0,subtree:!0,characterData:!0,characterDataOldValue:!0,attributes:!1})}catch(T){this.log(`Failed to observe element (${m}):`,T)}}),document.body&&document.body.isConnected)try{C.observe(document.body,{childList:!0,subtree:!0,characterData:!0,characterDataOldValue:!0,attributes:!1})}catch(w){this.log(`Failed to observe document.body (${m}):`,w)}},d=(C,m,y,w)=>{const T=C.filter(f=>{const v=f.cssSelector.match(/data-sl-attribute-(?:p|cap)="(\d+)"/);return v&&v[1]===w});this.log(`Applying ${y} DOM selectors, total: ${C.length}, filtered: ${T.length}`),T.length>0&&U(document,{testId:t,hypothesisId:m,selectors:T})},p=(C,m)=>{this.log(`Applying DOM selector changes for product ID: ${C}`),m.disconnect(),o=!0;try{if(i&&this.state.temporary.previewConfig){const y=e==="control"?"a":"b",w=this.state.temporary.previewConfig.variants.find(T=>T.label===y);if(!w?.domSelectors){this.log(`No DOM selectors found for preview variant: ${y}`);return}d(w.domSelectors,w.id,"preview config",C)}else{const y=this.testConfigs.find(T=>T.id===t);if(!y){this.log(`No test config found for testId: ${t}`);return}const w=y.hypotheses.find(T=>e==="control"?T.isControl:!T.isControl);if(!w?.domSelectors){this.log(`No DOM selectors found for assignment: ${e}`);return}d(w.domSelectors,w.id,"live config",C)}}finally{l!==null&&clearTimeout(l),l=window.setTimeout(()=>{o=!1,l=null,c(m,"reconnection"),this.log("Re-established innerHTML observer after DOM changes")},50)}},h=new MutationObserver(C=>{if(!o)for(const m of C){if(m.type!=="childList"&&m.type!=="characterData")continue;let y=m.target;m.type==="characterData"&&(y=m.target.parentElement||m.target.parentNode);let w=y,T=w.getAttribute("data-sl-attribute-p");for(;!T&&w.parentElement;)w=w.parentElement,T=w.getAttribute("data-sl-attribute-p");if(!T)continue;const f=w.innerHTML||w.textContent||"";let v="";m.type==="characterData"&&m.oldValue!==null&&(v=m.oldValue),this.log(`innerHTML changed on element with data-sl-attribute-p="${T}"`),v&&this.log(`Previous content: "${v}"`),this.log(`Current content: "${f}"`),p(T,h)}});c(h,"initial setup"),n.add(h);const u=new MutationObserver(C=>{C.forEach(m=>{m.addedNodes.forEach(y=>{if(y.nodeType===Node.ELEMENT_NODE){const w=y;k(w);const T=w.matches('input[name="properties[_slpt]"]')?[w]:w.querySelectorAll('input[name="properties[_slpt]"]');T.length>0&&this.log(`MutationObserver found ${T.length} new hidden input(s)`),T.forEach(f=>{const v=f.getAttribute("data-sl-pid");if(this.log(`MutationObserver checking new input with data-sl-pid="${v}"`),r(f))f.value!==s&&(f.value=s,this.log("Updated newly added hidden input:",s)),S(f);else{const g=f.getAttribute("data-sl-pid");g&&this.isProductInAnyPriceTest(g)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",g):(f.remove(),this.log("Removed newly added non-matching hidden input for product ID:",g))}})}})})});n.add(u);const b=new MutationObserver(C=>{C.forEach(m=>{if(m.type==="attributes"&&m.attributeName==="data-sl-pid"){const y=m.target;if(this.log("AttributeObserver detected data-sl-pid attribute change on:",y.tagName),y.matches('input[name="properties[_slpt]"]')){const w=y,T=m.oldValue,f=w.getAttribute("data-sl-pid");this.log(`data-sl-pid changed from "${T}" to "${f}" - triggering payment placement updates`),r(w)?(w.value!==s&&(w.value=s,this.log("Updated hidden input after data-sl-pid change:",s)),f&&p(f,h),this.log("Re-running payment placement updates after variant change"),k(document.body)):f&&this.isProductInAnyPriceTest(f)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",f):(w.remove(),this.log("Removed non-matching hidden input after data-sl-pid change:",f))}}})});n.add(b);const k=C=>{C.tagName==="SHOPIFY-PAYMENT-TERMS"&&(this.log("MutationObserver found new shopify-payment-terms element"),this.updateShopifyPaymentTerms(t,e));const m=C.querySelectorAll("shopify-payment-terms");m.length>0&&(this.log(`MutationObserver found ${m.length} shopify-payment-terms in added node`),this.updateShopifyPaymentTerms(t,e)),C.tagName==="AFTERPAY-PLACEMENT"&&(this.log("MutationObserver found new afterpay-placement element"),this.updateAfterpayPlacements(t,e,"afterpay"));const y=C.querySelectorAll("afterpay-placement");y.length>0&&(this.log(`MutationObserver found ${y.length} afterpay-placement in added node`),this.updateAfterpayPlacements(t,e,"afterpay")),C.tagName==="SQUARE-PLACEMENT"&&(this.log("MutationObserver found new square-placement element"),this.updateAfterpayPlacements(t,e,"square"));const w=C.querySelectorAll("square-placement");w.length>0&&(this.log(`MutationObserver found ${w.length} square-placement in added node`),this.updateAfterpayPlacements(t,e,"square")),C.tagName==="KLARNA-PLACEMENT"&&(this.log("MutationObserver found new klarna-placement element"),this.updateKlarnaPlacements(t,e));const T=C.querySelectorAll("klarna-placement");T.length>0&&(this.log(`MutationObserver found ${T.length} klarna-placement in added node`),this.updateKlarnaPlacements(t,e))},S=C=>{b.observe(C,{attributes:!0,attributeFilter:["data-sl-pid"],attributeOldValue:!0,subtree:!1});const m=C.getAttribute("data-sl-pid");this.log(`Started AttributeObserver on specific input with data-sl-pid="${m}"`)},P=()=>{const C=document.querySelectorAll('input[name="properties[_slpt]"]');this.log(`Found ${C.length} existing hidden inputs to check`),C.forEach(m=>{const y=m.getAttribute("data-sl-pid");this.log(`Checking existing input with data-sl-pid="${y}"`),r(m)?(m.value=s,this.log("Updated existing hidden input:",s),y&&(this.log("Applying initial DOM selector changes for existing product"),p(y,h)),S(m)):y&&this.isProductInAnyPriceTest(y)?this.log("Preserving hidden input for product ID '%s' - belongs to a different price test",y):(m.remove(),this.log("Removed non-matching hidden input for product ID:",y))})},_=()=>{document.body?(u.observe(document.body,{childList:!0,subtree:!0}),this.log("Started MutationObserver on document.body"),P(),k(document.body)):document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{document.body&&(u.observe(document.body,{childList:!0,subtree:!0}),this.log("Started MutationObserver after DOMContentLoaded"),P(),k(document.body))}):(this.log("Set timeout on observer"),setTimeout(_,10))};_(),window.__shopliftPriceTestObservers=n,window.__shopliftPriceTestValue=s,this.log("Set up DOM observer for price test hidden inputs")}catch(s){this.log("Error updating price test hidden inputs:",s)}}updateKlarnaPlacements(t,e){this.updatePlacementElements(t,e,"klarna-placement",(i,s)=>{i.setAttribute("data-purchase-amount",s.toString())})}cleanupPriceTestObservers(){const t=window.__shopliftPriceTestObservers;t&&(t.forEach(e=>{e.disconnect()}),t.clear(),this.log("Cleaned up existing price test observers")),delete window.__shopliftPriceTestObservers,delete window.__shopliftPriceTestValue}updateAfterpayPlacements(t,e,i="afterpay"){const s=i==="square"?"square-placement":"afterpay-placement";if(document.querySelectorAll(s).length===0){this.log(`No ${s} elements found on page - early return`);return}this.updatePlacementElements(t,e,s,(n,o)=>{if(i==="afterpay"){const l=(o/100).toFixed(2);n.setAttribute("data-amount",l)}else n.setAttribute("data-amount",o.toString())}),this.log("updateAfterpayPlacements completed")}updatePlacementElements(t,e,i,s){const r=document.querySelectorAll(i);if(r.length===0){this.log(`No ${i} elements found - early return`);return}let n;if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const l=e==="control"?"a":"b",c=this.state.temporary.previewConfig.variants.find(d=>d.label===l);if(!c?.domSelectors){this.log(`No variant found for label ${l} in preview config for ${i}`);return}n=c.domSelectors,this.log(`Using preview config for ${i} in merchant mode, variant: ${l}`)}else{const l=this.testConfigs.find(d=>d.id===t);if(!l){this.log(`No testConfig found for id: ${t} - early return`);return}const c=l.hypotheses.find(d=>e==="control"?d.isControl:!d.isControl);if(!c?.domSelectors){this.log(`No hypothesis or domSelectors found for assignment: ${e} - early return`);return}n=c.domSelectors}const o=new RegExp(`${this.DATA_SL_ATTRIBUTE_P}=["'](\\d+)["']`);r.forEach(l=>{let c=null;const d=l.parentElement;if(d&&(c=d.querySelector('input[name="properties[_slpt]"]')),c||(c=l.querySelector('input[name="properties[_slpt]"]')),!c){this.log(`No hidden input found for ${i} element`);return}const p=c.getAttribute("data-sl-pid");if(!p){this.log("Hidden input has no data-sl-pid attribute - skipping");return}const h=n.find(S=>{const P=S.cssSelector.match(o);return P&&P[1]===p});if(!h){this.log(`No matching selector found for productId: ${p} - skipping element`);return}const u=h.actions.find(S=>S.scope==="price");if(!u?.value){this.log("No price action or value found - skipping element");return}const b=parseFloat(u.value.replace(/[^0-9.]/g,""));if(Number.isNaN(b)){this.log(`Invalid price "${u.value}" for product ${p} - skipping`);return}const k=Math.round(b*100);s(l,k)}),this.log(`updatePlacementElements completed for ${i}`)}updateShopifyPaymentTerms(t,e){const i=document.querySelectorAll("shopify-payment-terms");if(i.length===0)return;this.log("Store using shopify payments");let s;if(this.state.temporary.isMerchant&&this.state.temporary.previewConfig){const n=e==="control"?"a":"b",o=this.state.temporary.previewConfig.variants.find(l=>l.label===n);if(!o||!o.domSelectors){this.log(`No variant found for label ${n} in preview config`);return}s=o.domSelectors,this.log(`Using preview config for shopify-payment-terms in merchant mode, variant: ${n}`)}else{const n=this.testConfigs.find(l=>l.id===t);if(!n)return;const o=n.hypotheses.find(l=>e==="control"?l.isControl===!0:l.isControl===!1);if(!o||!o.domSelectors)return;s=o.domSelectors}const r=new RegExp(`${this.DATA_SL_ATTRIBUTE_P}=["'](\\d+)["']`);i.forEach(n=>{const o=n.getAttribute("variant-id");if(!o)return;const l=s.find(c=>{const d=c.cssSelector.match(r);return d&&d[1]===o});if(l){const c=l.actions.find(d=>d.scope==="price");if(c&&c.value){const d=n.getAttribute("shopify-meta");if(d)try{const p=JSON.parse(d);if(p.variants&&Array.isArray(p.variants)){const h=p.variants.find(u=>u.id?.toString()===o);if(h){h.full_price=c.value;const u=parseFloat(c.value.replace(/[^0-9.]/g,""));if(h.number_of_payment_terms&&h.number_of_payment_terms>1){const b=u/h.number_of_payment_terms;h.price_per_term=`$${b.toFixed(2)}`}n.setAttribute("shopify-meta",JSON.stringify(p))}}}catch(p){this.log("Error parsing/updating shoplift-meta:",p)}}}})}async makeJsonRequest(t){const e=await this.makeRequest(t);return e===null?null:JSON.parse(await e.text(),F)}async makeRequest(t){const{url:e,method:i,headers:s,data:r,signal:n}=t,o=new Headers;if(s)for(const c in s)o.append(c,s[c]);(!s||!s.Accept)&&o.append("Accept","application/json"),(!s||!s["Content-Type"])&&o.append("Content-Type","application/json"),(this.eventHost.includes("ngrok.io")||this.eventHost.includes("ngrok-free.app"))&&o.append("ngrok-skip-browser-warning","1234");const l=await this.fetch(e,{method:i,headers:o,body:r,signal:n});if(!l.ok){if(l.status===204)return null;if(l.status===422){const c=await l.json();if(typeof c<"u"&&c.isBot)throw new et}throw new Error(`Error sending shoplift request ${l.status}`)}return l}queueAddVisitorToTest(t,e){if(this.state.essential.visitorTests.some(s=>s.testId===t))return;const i=this.testConfigs.find(s=>s.id===t);if(this.state.essential.visitorTests.push({createdAt:new Date,testId:t,hypothesisId:e.id,isThemeTest:e.type==="theme",themeId:e.themeId,isSaved:!1,isInvalid:!1,shouldSendToGa:!0,testType:e.type,assignedTo:e.isControl?"control":"variant",testTitle:i?.title}),e.type==="price"){const s=e.isControl?"control":"variant";this.log("Price test assignment detected, updating cart attributes:",t,s),this.updatePriceTestHiddenInputs(t,s,!1)}}queueCartUpdate(t){this.queueEvent(new wt(t))}queuePageView(t){this.queueEvent(new vt(t))}queueEvent(t){!this.state.essential.consentApproved&&this.state.essential.hasConsentInteraction||this.state.analytics.queue.length>10||this.state.analytics.queue.push(t)}legacyGetLocalStorageVisitor(){const t=this.localStorageGet(this.legacySessionKey);if(t)try{return JSON.parse(t,F)}catch{}return null}pruneStaleVisitorTests(){this.state.essential.visitorTests=this.state.essential.visitorTests.filter(t=>this.testConfigs.some(e=>e.id==t.testId)||this.inactiveTestConfigs.filter(e=>this.testIsPaused(e)).some(e=>e.id===t.testId))}pruneStateAndSave(){this.pruneStaleVisitorTests(),this.saveState()}saveState(){this.persistEssentialState(),this.persistAnalyticsState()}loadState(){const t=this.loadAnalyticsState(),e={analytics:t,essential:this.loadEssentialState(t),temporary:this.loadTemporaryState()},i=this.legacyGetLocalStorageVisitor(),s=this.legacyGetCookieVisitor(),r=[i,s].filter(n=>n!==null).sort((n,o)=>+o.storedAt-+n.storedAt)[0];return e.analytics.visitor===null&&r&&({visitorTests:e.essential.visitorTests,...e.analytics.visitor}=r,e.essential.isFirstLoad=!1,e.essential.initialState={createdAt:r.createdAt,referrer:r.referrer,utmCampaign:r.utmCampaign,utmContent:r.utmContent,utmMedium:r.utmMedium,utmSource:r.utmSource,device:r.device},this.deleteCookie("SHOPLIFT"),this.deleteLocalStorage(this.legacySessionKey)),!e.essential.consentApproved&&e.essential.hasConsentInteraction&&this.deleteLocalStorage(this.analyticsSessionKey),e}loadEssentialState(t){const e=this.loadLocalStorage(this.essentialSessionKey),i=this.loadCookie(this.essentialSessionKey),s=this.getInitialState();t.visitor?.device&&(s.device=t.visitor.device);const r={timestamp:new Date,consentApproved:!1,hasConsentInteraction:!1,debugMode:!1,initialState:s,visitorTests:[],isFirstLoad:!0},n=[e,i].filter(o=>o!==null).sort((o,l)=>+l.timestamp-+o.timestamp)[0]??r;return n.initialState||(t.visitor!==null?n.initialState=t.visitor:(n.initialState=s,n.initialState.createdAt=n.timestamp)),n}loadAnalyticsState(){const t=this.loadLocalStorage(this.analyticsSessionKey),e=this.loadCookie(this.analyticsSessionKey),i={timestamp:new Date,visitor:null,queue:[]},s=[t,e].filter(r=>r!==null).sort((r,n)=>+n.timestamp-+r.timestamp)[0]??i;return s.queue.length===0&&t&&t.queue.length>1&&(s.queue=t.queue),s}loadTemporaryState(){const t=this.sessionStorageGet(this.temporarySessionKey),e=t?JSON.parse(t,F):null,i=this.loadCookie(this.temporarySessionKey);return e??i??{isMerchant:!1,timestamp:new Date}}persistEssentialState(){this.log("Persisting essential state"),this.state.essential.isFirstLoad=!1,this.state.essential.timestamp=new Date,this.persistLocalStorageState(this.essentialSessionKey,this.state.essential),this.persistCookieState(this.essentialSessionKey,this.state.essential)}persistAnalyticsState(){this.log("Persisting analytics state"),this.state.essential.consentApproved&&(this.state.analytics.timestamp=new Date,this.persistLocalStorageState(this.analyticsSessionKey,this.state.analytics),this.persistCookieState(this.analyticsSessionKey,{...this.state.analytics,queue:[]}))}persistTemporaryState(){this.log("Setting temporary session state"),this.state.temporary.timestamp=new Date,this.sessionStorageSet(this.temporarySessionKey,JSON.stringify(this.state.temporary)),this.persistCookieState(this.temporarySessionKey,this.state.temporary,!0)}loadLocalStorage(t){const e=this.localStorageGet(t);if(e===null)return null;try{return JSON.parse(e,F)}catch{return null}}loadCookie(t){const e=this.getCookie(t);if(e===null)return null;try{return JSON.parse(e,F)}catch{return null}}persistLocalStorageState(t,e){this.localStorageSet(t,JSON.stringify(e))}persistCookieState(t,e,i=!1){const s=JSON.stringify(e),r=i?"":`expires=${new Date(new Date().getTime()+864e5*365).toUTCString()};`;document.cookie=`${t}=${s};domain=.${window.location.hostname};path=/;SameSite=Strict;${r}`}deleteCookie(t){const e=new Date(0).toUTCString();document.cookie=`${t}=;domain=.${window.location.hostname};path=/;expires=${e};`}deleteLocalStorage(t){window.localStorage.removeItem(t)}getChannel(t){return[{"name":"cross-network","test":(v) => new RegExp(".*cross-network.*", "i").test(v.utmCampaign)},{"name":"direct","test":(v) => v.utmSource === "" && v.utmMedium === ""},{"name":"paid-shopping","test":(v) => (new RegExp("^(?:Google|IGShopping|aax-us-east\.amazon-adsystem\.com|aax\.amazon-adsystem\.com|alibaba|alibaba\.com|amazon|amazon\.co\.uk|amazon\.com|apps\.shopify\.com|checkout\.shopify\.com|checkout\.stripe\.com|cr\.shopping\.naver\.com|cr2\.shopping\.naver\.com|ebay|ebay\.co\.uk|ebay\.com|ebay\.com\.au|ebay\.de|etsy|etsy\.com|m\.alibaba\.com|m\.shopping\.naver\.com|mercadolibre|mercadolibre\.com|mercadolibre\.com\.ar|mercadolibre\.com\.mx|message\.alibaba\.com|msearch\.shopping\.naver\.com|nl\.shopping\.net|no\.shopping\.net|offer\.alibaba\.com|one\.walmart\.com|order\.shopping\.yahoo\.co\.jp|partners\.shopify\.com|s3\.amazonaws\.com|se\.shopping\.net|shop\.app|shopify|shopify\.com|shopping\.naver\.com|shopping\.yahoo\.co\.jp|shopping\.yahoo\.com|shopzilla|shopzilla\.com|simplycodes\.com|store\.shopping\.yahoo\.co\.jp|stripe|stripe\.com|uk\.shopping\.net|walmart|walmart\.com)$", "i").test(v.utmSource) || new RegExp("^(.*(([^a-df-z]|^)shop|shopping).*)$", "i").test(v.utmCampaign)) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-search","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-social","test":(v) => new RegExp("^(?:43things|43things\.com|51\.com|5ch\.net|Hatena|ImageShack|academia\.edu|activerain|activerain\.com|activeworlds|activeworlds\.com|addthis|addthis\.com|airg\.ca|allnurses\.com|allrecipes\.com|alumniclass|alumniclass\.com|ameba\.jp|ameblo\.jp|americantowns|americantowns\.com|amp\.reddit\.com|ancestry\.com|anobii|anobii\.com|answerbag|answerbag\.com|answers\.yahoo\.com|aolanswers|aolanswers\.com|apps\.facebook\.com|ar\.pinterest\.com|artstation\.com|askubuntu|askubuntu\.com|asmallworld\.com|athlinks|athlinks\.com|away\.vk\.com|awe\.sm|b\.hatena\.ne\.jp|baby-gaga|baby-gaga\.com|babyblog\.ru|badoo|badoo\.com|bebo|bebo\.com|beforeitsnews|beforeitsnews\.com|bharatstudent|bharatstudent\.com|biip\.no|biswap\.org|bit\.ly|blackcareernetwork\.com|blackplanet|blackplanet\.com|blip\.fm|blog\.com|blog\.feedspot\.com|blog\.goo\.ne\.jp|blog\.naver\.com|blog\.yahoo\.co\.jp|blogg\.no|bloggang\.com|blogger|blogger\.com|blogher|blogher\.com|bloglines|bloglines\.com|blogs\.com|blogsome|blogsome\.com|blogspot|blogspot\.com|blogster|blogster\.com|blurtit|blurtit\.com|bookmarks\.yahoo\.co\.jp|bookmarks\.yahoo\.com|br\.pinterest\.com|brightkite|brightkite\.com|brizzly|brizzly\.com|business\.facebook\.com|buzzfeed|buzzfeed\.com|buzznet|buzznet\.com|cafe\.naver\.com|cafemom|cafemom\.com|camospace|camospace\.com|canalblog\.com|care\.com|care2|care2\.com|caringbridge\.org|catster|catster\.com|cbnt\.io|cellufun|cellufun\.com|centerblog\.net|chat\.zalo\.me|chegg\.com|chicagonow|chicagonow\.com|chiebukuro\.yahoo\.co\.jp|classmates|classmates\.com|classquest|classquest\.com|co\.pinterest\.com|cocolog-nifty|cocolog-nifty\.com|copainsdavant\.linternaute\.com|couchsurfing\.org|cozycot|cozycot\.com|cross\.tv|crunchyroll|crunchyroll\.com|cyworld|cyworld\.com|cz\.pinterest\.com|d\.hatena\.ne\.jp|dailystrength\.org|deluxe\.com|deviantart|deviantart\.com|dianping|dianping\.com|digg|digg\.com|diigo|diigo\.com|discover\.hubpages\.com|disqus|disqus\.com|dogster|dogster\.com|dol2day|dol2day\.com|doostang|doostang\.com|dopplr|dopplr\.com|douban|douban\.com|draft\.blogger\.com|draugiem\.lv|drugs-forum|drugs-forum\.com|dzone|dzone\.com|edublogs\.org|elftown|elftown\.com|epicurious\.com|everforo\.com|exblog\.jp|extole|extole\.com|facebook|facebook\.com|faceparty|faceparty\.com|fandom\.com|fanpop|fanpop\.com|fark|fark\.com|fb|fb\.me|fc2|fc2\.com|feedspot|feministing|feministing\.com|filmaffinity|filmaffinity\.com|flickr|flickr\.com|flipboard|flipboard\.com|folkdirect|folkdirect\.com|foodservice|foodservice\.com|forums\.androidcentral\.com|forums\.crackberry\.com|forums\.imore\.com|forums\.nexopia\.com|forums\.webosnation\.com|forums\.wpcentral\.com|fotki|fotki\.com|fotolog|fotolog\.com|foursquare|foursquare\.com|free\.facebook\.com|friendfeed|friendfeed\.com|fruehstueckstreff\.org|fubar|fubar\.com|gaiaonline|gaiaonline\.com|gamerdna|gamerdna\.com|gather\.com|geni\.com|getpocket\.com|glassboard|glassboard\.com|glassdoor|glassdoor\.com|godtube|godtube\.com|goldenline\.pl|goldstar|goldstar\.com|goo\.gl|gooblog|goodreads|goodreads\.com|google\+|googlegroups\.com|googleplus|govloop|govloop\.com|gowalla|gowalla\.com|gree\.jp|groups\.google\.com|gulli\.com|gutefrage\.net|habbo|habbo\.com|hi5|hi5\.com|hootsuite|hootsuite\.com|houzz|houzz\.com|hoverspot|hoverspot\.com|hr\.com|hu\.pinterest\.com|hubculture|hubculture\.com|hubpages\.com|hyves\.net|hyves\.nl|ibibo|ibibo\.com|id\.pinterest\.com|identi\.ca|ig|imageshack\.com|imageshack\.us|imvu|imvu\.com|in\.pinterest\.com|insanejournal|insanejournal\.com|instagram|instagram\.com|instapaper|instapaper\.com|internations\.org|interpals\.net|intherooms|intherooms\.com|irc-galleria\.net|is\.gd|italki|italki\.com|jammerdirect|jammerdirect\.com|jappy\.com|jappy\.de|kaboodle\.com|kakao|kakao\.com|kakaocorp\.com|kaneva|kaneva\.com|kin\.naver\.com|l\.facebook\.com|l\.instagram\.com|l\.messenger\.com|last\.fm|librarything|librarything\.com|lifestream\.aol\.com|line|line\.me|linkedin|linkedin\.com|listal|listal\.com|listography|listography\.com|livedoor\.com|livedoorblog|livejournal|livejournal\.com|lm\.facebook\.com|lnkd\.in|m\.blog\.naver\.com|m\.cafe\.naver\.com|m\.facebook\.com|m\.kin\.naver\.com|m\.vk\.com|m\.yelp\.com|mbga\.jp|medium\.com|meetin\.org|meetup|meetup\.com|meinvz\.net|meneame\.net|menuism\.com|messages\.google\.com|messages\.yahoo\.co\.jp|messenger|messenger\.com|mix\.com|mixi\.jp|mobile\.facebook\.com|mocospace|mocospace\.com|mouthshut|mouthshut\.com|movabletype|movabletype\.com|mubi|mubi\.com|my\.opera\.com|myanimelist\.net|myheritage|myheritage\.com|mylife|mylife\.com|mymodernmet|mymodernmet\.com|myspace|myspace\.com|netvibes|netvibes\.com|news\.ycombinator\.com|newsshowcase|nexopia|ngopost\.org|niconico|nicovideo\.jp|nightlifelink|nightlifelink\.com|ning|ning\.com|nl\.pinterest\.com|odnoklassniki\.ru|odnoklassniki\.ua|okwave\.jp|old\.reddit\.com|oneworldgroup\.org|onstartups|onstartups\.com|opendiary|opendiary\.com|oshiete\.goo\.ne\.jp|out\.reddit\.com|over-blog\.com|overblog\.com|paper\.li|partyflock\.nl|photobucket|photobucket\.com|pinboard|pinboard\.in|pingsta|pingsta\.com|pinterest|pinterest\.at|pinterest\.ca|pinterest\.ch|pinterest\.cl|pinterest\.co\.kr|pinterest\.co\.uk|pinterest\.com|pinterest\.com\.au|pinterest\.com\.mx|pinterest\.de|pinterest\.es|pinterest\.fr|pinterest\.it|pinterest\.jp|pinterest\.nz|pinterest\.ph|pinterest\.pt|pinterest\.ru|pinterest\.se|pixiv\.net|pl\.pinterest\.com|playahead\.se|plurk|plurk\.com|plus\.google\.com|plus\.url\.google\.com|pocket\.co|posterous|posterous\.com|pro\.homeadvisor\.com|pulse\.yahoo\.com|qapacity|qapacity\.com|quechup|quechup\.com|quora|quora\.com|qzone\.qq\.com|ravelry|ravelry\.com|reddit|reddit\.com|redux|redux\.com|renren|renren\.com|researchgate\.net|reunion|reunion\.com|reverbnation|reverbnation\.com|rtl\.de|ryze|ryze\.com|salespider|salespider\.com|scoop\.it|screenrant|screenrant\.com|scribd|scribd\.com|scvngr|scvngr\.com|secondlife|secondlife\.com|serverfault|serverfault\.com|shareit|sharethis|sharethis\.com|shvoong\.com|sites\.google\.com|skype|skyrock|skyrock\.com|slashdot\.org|slideshare\.net|smartnews\.com|snapchat|snapchat\.com|social|sociallife\.com\.br|socialvibe|socialvibe\.com|spaces\.live\.com|spoke|spoke\.com|spruz|spruz\.com|ssense\.com|stackapps|stackapps\.com|stackexchange|stackexchange\.com|stackoverflow|stackoverflow\.com|stardoll\.com|stickam|stickam\.com|studivz\.net|suomi24\.fi|superuser|superuser\.com|sweeva|sweeva\.com|t\.co|t\.me|tagged|tagged\.com|taggedmail|taggedmail\.com|talkbiznow|talkbiznow\.com|taringa\.net|techmeme|techmeme\.com|tencent|tencent\.com|tiktok|tiktok\.com|tinyurl|tinyurl\.com|toolbox|toolbox\.com|touch\.facebook\.com|tr\.pinterest\.com|travellerspoint|travellerspoint\.com|tripadvisor|tripadvisor\.com|trombi|trombi\.com|trustpilot|tudou|tudou\.com|tuenti|tuenti\.com|tumblr|tumblr\.com|tweetdeck|tweetdeck\.com|twitter|twitter\.com|twoo\.com|typepad|typepad\.com|unblog\.fr|urbanspoon\.com|ushareit\.com|ushi\.cn|vampirefreaks|vampirefreaks\.com|vampirerave|vampirerave\.com|vg\.no|video\.ibm\.com|vk\.com|vkontakte\.ru|wakoopa|wakoopa\.com|wattpad|wattpad\.com|web\.facebook\.com|web\.skype\.com|webshots|webshots\.com|wechat|wechat\.com|weebly|weebly\.com|weibo|weibo\.com|wer-weiss-was\.de|weread|weread\.com|whatsapp|whatsapp\.com|wiki\.answers\.com|wikihow\.com|wikitravel\.org|woot\.com|wordpress|wordpress\.com|wordpress\.org|xanga|xanga\.com|xing|xing\.com|yahoo-mbga\.jp|yammer|yammer\.com|yelp|yelp\.co\.uk|yelp\.com|youroom\.in|za\.pinterest\.com|zalo|zoo\.gr|zooppa|zooppa\.com)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"paid-video","test":(v) => new RegExp("^(?:blog\.twitch\.tv|crackle|crackle\.com|curiositystream|curiositystream\.com|d\.tube|dailymotion|dailymotion\.com|dashboard\.twitch\.tv|disneyplus|disneyplus\.com|fast\.wistia\.net|help\.hulu\.com|help\.netflix\.com|hulu|hulu\.com|id\.twitch\.tv|iq\.com|iqiyi|iqiyi\.com|jobs\.netflix\.com|justin\.tv|m\.twitch\.tv|m\.youtube\.com|music\.youtube\.com|netflix|netflix\.com|player\.twitch\.tv|player\.vimeo\.com|ted|ted\.com|twitch|twitch\.tv|utreon|utreon\.com|veoh|veoh\.com|viadeo\.journaldunet\.com|vimeo|vimeo\.com|wistia|wistia\.com|youku|youku\.com|youtube|youtube\.com)$", "i").test(v.utmSource) && new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"display","test":(v) => new RegExp("^(?:display|banner|expandable|interstitial|cpm)$", "i").test(v.utmMedium)},{"name":"paid-other","test":(v) => new RegExp("^(.*cp.*|ppc|retargeting|paid.*)$", "i").test(v.utmMedium)},{"name":"organic-shopping","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) || new RegExp("^(.*(([^a-df-z]|^)shop|shopping).*)$", "i").test(v.utmCampaign)},{"name":"organic-social","test":(v) => new RegExp("^(?:43things|43things\.com|51\.com|5ch\.net|Hatena|ImageShack|academia\.edu|activerain|activerain\.com|activeworlds|activeworlds\.com|addthis|addthis\.com|airg\.ca|allnurses\.com|allrecipes\.com|alumniclass|alumniclass\.com|ameba\.jp|ameblo\.jp|americantowns|americantowns\.com|amp\.reddit\.com|ancestry\.com|anobii|anobii\.com|answerbag|answerbag\.com|answers\.yahoo\.com|aolanswers|aolanswers\.com|apps\.facebook\.com|ar\.pinterest\.com|artstation\.com|askubuntu|askubuntu\.com|asmallworld\.com|athlinks|athlinks\.com|away\.vk\.com|awe\.sm|b\.hatena\.ne\.jp|baby-gaga|baby-gaga\.com|babyblog\.ru|badoo|badoo\.com|bebo|bebo\.com|beforeitsnews|beforeitsnews\.com|bharatstudent|bharatstudent\.com|biip\.no|biswap\.org|bit\.ly|blackcareernetwork\.com|blackplanet|blackplanet\.com|blip\.fm|blog\.com|blog\.feedspot\.com|blog\.goo\.ne\.jp|blog\.naver\.com|blog\.yahoo\.co\.jp|blogg\.no|bloggang\.com|blogger|blogger\.com|blogher|blogher\.com|bloglines|bloglines\.com|blogs\.com|blogsome|blogsome\.com|blogspot|blogspot\.com|blogster|blogster\.com|blurtit|blurtit\.com|bookmarks\.yahoo\.co\.jp|bookmarks\.yahoo\.com|br\.pinterest\.com|brightkite|brightkite\.com|brizzly|brizzly\.com|business\.facebook\.com|buzzfeed|buzzfeed\.com|buzznet|buzznet\.com|cafe\.naver\.com|cafemom|cafemom\.com|camospace|camospace\.com|canalblog\.com|care\.com|care2|care2\.com|caringbridge\.org|catster|catster\.com|cbnt\.io|cellufun|cellufun\.com|centerblog\.net|chat\.zalo\.me|chegg\.com|chicagonow|chicagonow\.com|chiebukuro\.yahoo\.co\.jp|classmates|classmates\.com|classquest|classquest\.com|co\.pinterest\.com|cocolog-nifty|cocolog-nifty\.com|copainsdavant\.linternaute\.com|couchsurfing\.org|cozycot|cozycot\.com|cross\.tv|crunchyroll|crunchyroll\.com|cyworld|cyworld\.com|cz\.pinterest\.com|d\.hatena\.ne\.jp|dailystrength\.org|deluxe\.com|deviantart|deviantart\.com|dianping|dianping\.com|digg|digg\.com|diigo|diigo\.com|discover\.hubpages\.com|disqus|disqus\.com|dogster|dogster\.com|dol2day|dol2day\.com|doostang|doostang\.com|dopplr|dopplr\.com|douban|douban\.com|draft\.blogger\.com|draugiem\.lv|drugs-forum|drugs-forum\.com|dzone|dzone\.com|edublogs\.org|elftown|elftown\.com|epicurious\.com|everforo\.com|exblog\.jp|extole|extole\.com|facebook|facebook\.com|faceparty|faceparty\.com|fandom\.com|fanpop|fanpop\.com|fark|fark\.com|fb|fb\.me|fc2|fc2\.com|feedspot|feministing|feministing\.com|filmaffinity|filmaffinity\.com|flickr|flickr\.com|flipboard|flipboard\.com|folkdirect|folkdirect\.com|foodservice|foodservice\.com|forums\.androidcentral\.com|forums\.crackberry\.com|forums\.imore\.com|forums\.nexopia\.com|forums\.webosnation\.com|forums\.wpcentral\.com|fotki|fotki\.com|fotolog|fotolog\.com|foursquare|foursquare\.com|free\.facebook\.com|friendfeed|friendfeed\.com|fruehstueckstreff\.org|fubar|fubar\.com|gaiaonline|gaiaonline\.com|gamerdna|gamerdna\.com|gather\.com|geni\.com|getpocket\.com|glassboard|glassboard\.com|glassdoor|glassdoor\.com|godtube|godtube\.com|goldenline\.pl|goldstar|goldstar\.com|goo\.gl|gooblog|goodreads|goodreads\.com|google\+|googlegroups\.com|googleplus|govloop|govloop\.com|gowalla|gowalla\.com|gree\.jp|groups\.google\.com|gulli\.com|gutefrage\.net|habbo|habbo\.com|hi5|hi5\.com|hootsuite|hootsuite\.com|houzz|houzz\.com|hoverspot|hoverspot\.com|hr\.com|hu\.pinterest\.com|hubculture|hubculture\.com|hubpages\.com|hyves\.net|hyves\.nl|ibibo|ibibo\.com|id\.pinterest\.com|identi\.ca|ig|imageshack\.com|imageshack\.us|imvu|imvu\.com|in\.pinterest\.com|insanejournal|insanejournal\.com|instagram|instagram\.com|instapaper|instapaper\.com|internations\.org|interpals\.net|intherooms|intherooms\.com|irc-galleria\.net|is\.gd|italki|italki\.com|jammerdirect|jammerdirect\.com|jappy\.com|jappy\.de|kaboodle\.com|kakao|kakao\.com|kakaocorp\.com|kaneva|kaneva\.com|kin\.naver\.com|l\.facebook\.com|l\.instagram\.com|l\.messenger\.com|last\.fm|librarything|librarything\.com|lifestream\.aol\.com|line|line\.me|linkedin|linkedin\.com|listal|listal\.com|listography|listography\.com|livedoor\.com|livedoorblog|livejournal|livejournal\.com|lm\.facebook\.com|lnkd\.in|m\.blog\.naver\.com|m\.cafe\.naver\.com|m\.facebook\.com|m\.kin\.naver\.com|m\.vk\.com|m\.yelp\.com|mbga\.jp|medium\.com|meetin\.org|meetup|meetup\.com|meinvz\.net|meneame\.net|menuism\.com|messages\.google\.com|messages\.yahoo\.co\.jp|messenger|messenger\.com|mix\.com|mixi\.jp|mobile\.facebook\.com|mocospace|mocospace\.com|mouthshut|mouthshut\.com|movabletype|movabletype\.com|mubi|mubi\.com|my\.opera\.com|myanimelist\.net|myheritage|myheritage\.com|mylife|mylife\.com|mymodernmet|mymodernmet\.com|myspace|myspace\.com|netvibes|netvibes\.com|news\.ycombinator\.com|newsshowcase|nexopia|ngopost\.org|niconico|nicovideo\.jp|nightlifelink|nightlifelink\.com|ning|ning\.com|nl\.pinterest\.com|odnoklassniki\.ru|odnoklassniki\.ua|okwave\.jp|old\.reddit\.com|oneworldgroup\.org|onstartups|onstartups\.com|opendiary|opendiary\.com|oshiete\.goo\.ne\.jp|out\.reddit\.com|over-blog\.com|overblog\.com|paper\.li|partyflock\.nl|photobucket|photobucket\.com|pinboard|pinboard\.in|pingsta|pingsta\.com|pinterest|pinterest\.at|pinterest\.ca|pinterest\.ch|pinterest\.cl|pinterest\.co\.kr|pinterest\.co\.uk|pinterest\.com|pinterest\.com\.au|pinterest\.com\.mx|pinterest\.de|pinterest\.es|pinterest\.fr|pinterest\.it|pinterest\.jp|pinterest\.nz|pinterest\.ph|pinterest\.pt|pinterest\.ru|pinterest\.se|pixiv\.net|pl\.pinterest\.com|playahead\.se|plurk|plurk\.com|plus\.google\.com|plus\.url\.google\.com|pocket\.co|posterous|posterous\.com|pro\.homeadvisor\.com|pulse\.yahoo\.com|qapacity|qapacity\.com|quechup|quechup\.com|quora|quora\.com|qzone\.qq\.com|ravelry|ravelry\.com|reddit|reddit\.com|redux|redux\.com|renren|renren\.com|researchgate\.net|reunion|reunion\.com|reverbnation|reverbnation\.com|rtl\.de|ryze|ryze\.com|salespider|salespider\.com|scoop\.it|screenrant|screenrant\.com|scribd|scribd\.com|scvngr|scvngr\.com|secondlife|secondlife\.com|serverfault|serverfault\.com|shareit|sharethis|sharethis\.com|shvoong\.com|sites\.google\.com|skype|skyrock|skyrock\.com|slashdot\.org|slideshare\.net|smartnews\.com|snapchat|snapchat\.com|social|sociallife\.com\.br|socialvibe|socialvibe\.com|spaces\.live\.com|spoke|spoke\.com|spruz|spruz\.com|ssense\.com|stackapps|stackapps\.com|stackexchange|stackexchange\.com|stackoverflow|stackoverflow\.com|stardoll\.com|stickam|stickam\.com|studivz\.net|suomi24\.fi|superuser|superuser\.com|sweeva|sweeva\.com|t\.co|t\.me|tagged|tagged\.com|taggedmail|taggedmail\.com|talkbiznow|talkbiznow\.com|taringa\.net|techmeme|techmeme\.com|tencent|tencent\.com|tiktok|tiktok\.com|tinyurl|tinyurl\.com|toolbox|toolbox\.com|touch\.facebook\.com|tr\.pinterest\.com|travellerspoint|travellerspoint\.com|tripadvisor|tripadvisor\.com|trombi|trombi\.com|trustpilot|tudou|tudou\.com|tuenti|tuenti\.com|tumblr|tumblr\.com|tweetdeck|tweetdeck\.com|twitter|twitter\.com|twoo\.com|typepad|typepad\.com|unblog\.fr|urbanspoon\.com|ushareit\.com|ushi\.cn|vampirefreaks|vampirefreaks\.com|vampirerave|vampirerave\.com|vg\.no|video\.ibm\.com|vk\.com|vkontakte\.ru|wakoopa|wakoopa\.com|wattpad|wattpad\.com|web\.facebook\.com|web\.skype\.com|webshots|webshots\.com|wechat|wechat\.com|weebly|weebly\.com|weibo|weibo\.com|wer-weiss-was\.de|weread|weread\.com|whatsapp|whatsapp\.com|wiki\.answers\.com|wikihow\.com|wikitravel\.org|woot\.com|wordpress|wordpress\.com|wordpress\.org|xanga|xanga\.com|xing|xing\.com|yahoo-mbga\.jp|yammer|yammer\.com|yelp|yelp\.co\.uk|yelp\.com|youroom\.in|za\.pinterest\.com|zalo|zoo\.gr|zooppa|zooppa\.com)$", "i").test(v.utmSource) || new RegExp("^(?:social|social-network|social-media|sm|social network|social media)$", "i").test(v.utmMedium)},{"name":"organic-video","test":(v) => new RegExp("^(?:blog\.twitch\.tv|crackle|crackle\.com|curiositystream|curiositystream\.com|d\.tube|dailymotion|dailymotion\.com|dashboard\.twitch\.tv|disneyplus|disneyplus\.com|fast\.wistia\.net|help\.hulu\.com|help\.netflix\.com|hulu|hulu\.com|id\.twitch\.tv|iq\.com|iqiyi|iqiyi\.com|jobs\.netflix\.com|justin\.tv|m\.twitch\.tv|m\.youtube\.com|music\.youtube\.com|netflix|netflix\.com|player\.twitch\.tv|player\.vimeo\.com|ted|ted\.com|twitch|twitch\.tv|utreon|utreon\.com|veoh|veoh\.com|viadeo\.journaldunet\.com|vimeo|vimeo\.com|wistia|wistia\.com|youku|youku\.com|youtube|youtube\.com)$", "i").test(v.utmSource) || new RegExp("^(.*video.*)$", "i").test(v.utmMedium)},{"name":"organic-search","test":(v) => new RegExp("^(?:360\.cn|alice|aol|ar\.search\.yahoo\.com|ask|at\.search\.yahoo\.com|au\.search\.yahoo\.com|auone|avg|babylon|baidu|biglobe|biglobe\.co\.jp|biglobe\.ne\.jp|bing|br\.search\.yahoo\.com|ca\.search\.yahoo\.com|centrum\.cz|ch\.search\.yahoo\.com|cl\.search\.yahoo\.com|cn\.bing\.com|cnn|co\.search\.yahoo\.com|comcast|conduit|daum|daum\.net|de\.search\.yahoo\.com|dk\.search\.yahoo\.com|dogpile|dogpile\.com|duckduckgo|ecosia\.org|email\.seznam\.cz|eniro|es\.search\.yahoo\.com|espanol\.search\.yahoo\.com|exalead\.com|excite\.com|fi\.search\.yahoo\.com|firmy\.cz|fr\.search\.yahoo\.com|globo|go\.mail\.ru|google|google-play|hk\.search\.yahoo\.com|id\.search\.yahoo\.com|in\.search\.yahoo\.com|incredimail|it\.search\.yahoo\.com|kvasir|lens\.google\.com|lite\.qwant\.com|lycos|m\.baidu\.com|m\.naver\.com|m\.search\.naver\.com|m\.sogou\.com|mail\.rambler\.ru|mail\.yandex\.ru|malaysia\.search\.yahoo\.com|msn|msn\.com|mx\.search\.yahoo\.com|najdi|naver|naver\.com|news\.google\.com|nl\.search\.yahoo\.com|no\.search\.yahoo\.com|ntp\.msn\.com|nz\.search\.yahoo\.com|onet|onet\.pl|pe\.search\.yahoo\.com|ph\.search\.yahoo\.com|pl\.search\.yahoo\.com|play\.google\.com|qwant|qwant\.com|rakuten|rakuten\.co\.jp|rambler|rambler\.ru|se\.search\.yahoo\.com|search-results|search\.aol\.co\.uk|search\.aol\.com|search\.google\.com|search\.smt\.docomo\.ne\.jp|search\.ukr\.net|secureurl\.ukr\.net|seznam|seznam\.cz|sg\.search\.yahoo\.com|so\.com|sogou|sogou\.com|sp-web\.search\.auone\.jp|startsiden|startsiden\.no|suche\.aol\.de|terra|th\.search\.yahoo\.com|tr\.search\.yahoo\.com|tut\.by|tw\.search\.yahoo\.com|uk\.search\.yahoo\.com|ukr|us\.search\.yahoo\.com|virgilio|vn\.search\.yahoo\.com|wap\.sogou\.com|webmaster\.yandex\.ru|websearch\.rakuten\.co\.jp|yahoo|yahoo\.co\.jp|yahoo\.com|yandex|yandex\.by|yandex\.com|yandex\.com\.tr|yandex\.fr|yandex\.kz|yandex\.ru|yandex\.ua|yandex\.uz|zen\.yandex\.ru)$", "i").test(v.utmSource) || v.utmMedium.toLowerCase() === "organic"},{"name":"referral","test":(v) => new RegExp("^(?:referral|app|link)$", "i").test(v.utmMedium)},{"name":"email","test":(v) => new RegExp("^(?:email|e-mail|e_mail|e mail)$", "i").test(v.utmMedium) || new RegExp("^(?:email|e-mail|e_mail|e mail)$", "i").test(v.utmSource)},{"name":"affiliate","test":(v) => v.utmMedium.toLowerCase() === "affiliate"},{"name":"audio","test":(v) => v.utmMedium.toLowerCase() === "audio"},{"name":"sms","test":(v) => v.utmSource.toLowerCase() === "sms" || v.utmMedium.toLowerCase() === "sms"},{"name":"mobile-push-notification","test":(v) => v.utmSource.toLowerCase() === "firebase" || new RegExp("(?:.*mobile.*|.*notification.*|push$)", "i").test(v.utmMedium)}].find(i=>i.test(t))?.name??"other"}getShopifyAnalyticsId(){const t=this.getCookie("_shopify_y");if(t)return t;try{const e=this.localStorageGet("Shoplift_ClientId");if(e)return e}catch{}return null}legacyGetCookieVisitor(){const t=this.getCookie("SHOPLIFT");return t===null?null:JSON.parse(t,F)}getCookie(t){const e=this.cookie.split("; ").filter(i=>i.split("=").at(0)===t).at(0);return e===void 0?null:e.split("=").slice(1).join("=")}monitorConsentChange(){document.addEventListener("visitorConsentCollected",t=>{(async()=>await this.onConsentChange(t.detail.analyticsAllowed,!0))()}),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.loadShopifyConsentApiWithRetry()):this.loadShopifyConsentApiWithRetry()}loadShopifyConsentApiWithRetry(){let t=0;const e=()=>{this.loadShopifyConsentApi()||t++<10&&window.setTimeout(e,100)};e()}loadShopifyConsentApi(){if(window.Shopify){this.log("Loading Shopify features");const t=async()=>{if(!window.Shopify){this.log("Shopify object missing... suddenly?");return}if(window.Shopify.customerPrivacy===void 0){this.log("Shopify CustomerPrivacy api still missing, trying again in 1000ms"),e=window.setTimeout(()=>{(async()=>await t())()},1e3);return}const i=window.Shopify.customerPrivacy.getTrackingConsent();await this.onConsentChange(window.Shopify.customerPrivacy.analyticsProcessingAllowed(),i==="yes")};let e=window.setTimeout(()=>{(async()=>await t())()},5e3);return window.Shopify.loadFeatures([{name:"consent-tracking-api",version:"0.1"}],i=>{(async()=>{if(window.clearTimeout(e),i){this.log("Error loading consent tracking",i);return}await t()})()}),!0}return!1}async onConsentChange(t,e){try{if(this.log("Consent change detected",t,e),this.state.essential.consentApproved=t,this.state.essential.hasConsentInteraction=e,!this.state.essential.consentApproved){this.state.essential.hasConsentInteraction&&(this.state.analytics.queue.length=0),this.saveState();return}this.cookie=document.cookie,this.shopifyAnalyticsId=this.getShopifyAnalyticsId();for(const i of this.state.analytics.queue.filter(s=>s.type===1||s.type===2)){const s=i;s.shopifyAnalyticsId=this.shopifyAnalyticsId}this.saveState(),await this.syncAllEvents()}catch(i){this.log("Error syncing on consent change",i)}}isThemePreview(){return isThemePreview||themeRole!=="main"}isAppProxyPath(){const t=["/apps/","/tools/","/a/"],e=window.location.pathname;return t.some(i=>e.startsWith(i))}clearThemeBar(t,e,i){const s=structuredClone(i);this.log("Looking for theme bar"),this.waitForElement(null,"body").then(r=>this.waitForElement(r,"#preview-bar-iframe, #PBarNextFrameWrapper").then(n=>(this.log("Found theme bar"),e&&(this.log("Removing theme bar"),n.remove()),t?this.makeRequest({url:`${this.eventHost}/api/v0/logs`,method:"post",data:JSON.stringify({...this.debugState(),stateAtEvaluation:s},X)}):Promise.resolve(null)))).catch(r=>console.error(r))}waitForElement(t,e){return new Promise(i=>{const s=document.querySelector(e);if(s){i(s);return}const r=new MutationObserver(n=>{const o=document.querySelector(e);if(o){r.disconnect(),i(o);return}});r.observe(t??document.documentElement,{childList:!0})})}setDebug(t){this.state.essential.debugMode=t,this.saveState()}log(t,...e){let i=0;const s=t.replace(/%[sdoOfF]/g,r=>{if(i>=e.length)return r;const n=e[i++];return r==="%o"||r==="%O"?JSON.stringify(n):String(n)});this.logHistory.push(`[${new Date().toISOString()}][SL] ${s}`),!(!this.state.essential.debugMode&&!this.shopliftDebug)&&console.debug(`[SL] ${t}`,...e)}debugState(){return{state:this.state,storage:{essential:this.loadLocalStorage(this.essentialSessionKey),analytics:this.loadLocalStorage(this.analyticsSessionKey)},params:{shop:this.shop,host:this.host,eventHost:this.eventHost,cssHideClass:this.cssHideClass,testConfigs:this.testConfigs,inactiveTestConfigs:this.inactiveTestConfigs,sendPageView:this.sendPageView,isShopifyMerchantCookie:this.getCookie("is_shopify_merchant"),themeId,url:window.location.href,isThemePreview,themeRole,gaConfig:this.gaConfig},logHistory:this.logHistory}}createViewportObserver(t,e={}){const{threshold:i=this.VIEWPORT_TRACK_THRESHOLD,triggerOnce:s=!0}=e,r=new Set;return new IntersectionObserver(n=>{n.forEach(o=>{if(o.isIntersecting&&!r.has(o.target)){const l=o.target,c=l.getAttribute(this.DATA_SL_TEST_ID);c&&(t(c,l),s&&r.add(l))}})},{threshold:i})}applyChangesWithViewport(t,e,i,s){const r=e.selectorsForViewportTracking??e.selectors,n=o=>{if(this.state.essential.visitorTests.some(h=>h.testId===o)||this.activeViewportObservers.has(o))return;const l=[];if(r.forEach(h=>{t.querySelectorAll(h.cssSelector).forEach(b=>l.push(b))}),l.length===0)return;let c=!1;const d=()=>{c||(c=!0,i(o),p.disconnect(),this.activeViewportObservers.delete(o))},p=this.createViewportObserver(()=>{d()},{triggerOnce:!0,...s});this.activeViewportObservers.set(o,p),this.log(`Created viewport observer for test ${o}, observing ${l.length} elements`),l.forEach(h=>{h.setAttribute(this.DATA_SL_TEST_ID,String(o)),p.observe(h)}),setTimeout(()=>{c||l.forEach(h=>{const u=h.getBoundingClientRect(),b=s?.threshold??this.VIEWPORT_TRACK_THRESHOLD,k=Math.min(u.bottom,window.innerHeight)-Math.max(u.top,0),S=Math.min(u.right,window.innerWidth)-Math.max(u.left,0);u.top<window.innerHeight&&u.bottom>0&&u.left<window.innerWidth&&u.right>0&&k>0&&S>0&&k>=u.height*b&&(this.log(`Price element already visible in viewport for test ${o}:`,h),d())})},100)};e.selectors.length>0&&U(t,e,()=>{}),bt(t,{testId:e.testId,hypothesisId:e.hypothesisId,selectors:r},o=>{n(o)})}applyPriceTestWithMapLookup(t,e,i,s){if(!e.priceData){this.log("No price data for hypothesis '%s'",e.id);return}this.log("Hypothesis '%s' isControl=%s, priceData has %d variants",e.id,e.isControl,e.priceData.variants.length);const r=e.priceData.variants.slice(0,3);for(const[S,P,_]of r)this.log(" Sample priceData: variant=%s, price=%d, compareAt=%d",S,P,_);const n=j(e.priceData),o=new Set;for(const S of i)if(S.priceData)for(const[P]of S.priceData.variants)o.add(P);this.log("Price test Map lookup: %d products in hypothesis, %d total products to track",n.size,o.size);const l=e.priceData,c=new WeakSet;let d=!1;const p="[data-sl-attribute-p], [data-sl-attribute-cap], [data-sl-attribute-discount]",h=S=>{if(c.has(S))return;const P=S.getAttribute("data-sl-attribute-p"),_=S.getAttribute("data-sl-attribute-cap"),C=S.getAttribute("data-sl-attribute-discount"),m=P||_||C;if(!m||!o.has(m))return;c.add(S);const y=n.get(m);y&&(this.log("Applying price for product %s: %d cents (compare at: %d cents)",m,y.priceInCents,y.compareAtPriceInCents),Dt(S,m,y,l),this.log("Applied price to element for product %s",m)),!d&&!this.state.essential.visitorTests.some(w=>w.testId===t)&&(S.setAttribute(this.DATA_SL_TEST_ID,String(t)),this.setupElementViewportTracking(S,t,()=>{d||(d=!0,s(t))}))},u=()=>{const S=document.querySelectorAll(p);this.log("Scanning for price elements, found: %d",S.length),S.forEach(h)},b=new MutationObserver(S=>{for(const P of S)P.type==="childList"&&P.addedNodes.forEach(_=>{if(_.nodeType===Node.ELEMENT_NODE){const C=_;(C.hasAttribute("data-sl-attribute-p")||C.hasAttribute("data-sl-attribute-cap")||C.hasAttribute("data-sl-attribute-discount"))&&h(C),C.querySelectorAll(p).forEach(h)}}),P.type==="attributes"&&P.target instanceof Element&&h(P.target)}),k=document.body||document.documentElement;b.observe(k,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-sl-attribute-p","data-sl-attribute-cap","data-sl-attribute-discount"]}),this.log("MutationObserver started for price elements"),u(),document.readyState==="loading"&&document.addEventListener("DOMContentLoaded",()=>{this.log("DOMContentLoaded - rescanning for price elements"),u()}),setTimeout(()=>{this.log("Delayed rescan for price elements"),u()},100),setTimeout(()=>{this.log("Final rescan for price elements"),u()},500)}setupElementViewportTracking(t,e,i){const s=this.VIEWPORT_TRACK_THRESHOLD,r=t.getBoundingClientRect(),n=Math.min(r.bottom,window.innerHeight)-Math.max(r.top,0),o=Math.min(r.right,window.innerWidth)-Math.max(r.left,0);if(r.top<window.innerHeight&&r.bottom>0&&r.left<window.innerWidth&&r.right>0&&n>0&&o>0&&n>=r.height*s){this.log("Price element already visible for test %s",e),i();return}const c=new IntersectionObserver(d=>{for(const p of d)if(p.isIntersecting&&p.intersectionRatio>=s){this.log("Price element entered viewport for test %s",e),c.disconnect(),i();break}},{threshold:s});c.observe(t)}debug(){const t=this.debugState();console.log(JSON.stringify(t,X,2))}}(async function(){window.shopliftInstance||(window.shopliftInstance=new Wt("homeceuconnection.myshopify.com","https://app.shoplift.ai","https://events.shoplift.ai",true,false,false,{"sendEvents":false,"mode":"gtag"},false,false,1000,[{"id":"019d6310-948f-7be9-b8ee-1b2e85cc0585","startAt":"2026-04-06T13:52:04.239119Z","requiresCountry":false,"bayesianRevision":5,"device":"all","status":"active","visitorOption":"all","ignoreTestViewParameterEnforcement":false,"statusHistory":[{"status":"active","createdAt":"2026-04-06T13:52:04.243251Z"}],"hypotheses":[{"visitorCount":354,"trafficPercentage":0.5084741010996764,"title":"Unlimited Membership for Occupational Therapy","domSelectors":[],"id":"019d5543-461a-7e2e-8741-661d519ae526","type":"urlRedirect","themeId":188791652640,"affix":"","isControl":true,"redirectPath":"/pages/unlimited-ce-membership-occupational-therapy"},{"visitorCount":343,"trafficPercentage":0.4915258989003236,"title":"Membership Page CE Benefits Module Redesign","domSelectors":[],"id":"019d5543-a1bb-73ca-8da9-9b6148324de0","type":"urlRedirect","themeId":188791652640,"affix":"","isControl":false,"redirectPath":"/pages/unlimited-membership-for-occupational-therapy-ot"}],"targetAudiences":[],"title":"AB-26164: HomeCEU Occupational Therapy Membership "}],[],null),await window.shopliftInstance.init())})();async function Gt(a,t,e,i){const s=Mt({log:i});if(e)return i("[SUB-PREVIEW] A side — no overlay applied; widget renders naturally"),s;const r=a.widget.widgetType,n=t?j(t):null;let o=W(t),l=K(a,o),c=l.discountMap,d=l.maxDiscount;function p(){const f=W(t);f!==o&&(o=f,l=K(a,o),c=l.discountMap,d=l.maxDiscount,i(`[SUB-PREVIEW] scope refreshed currentProductId=${o??"n/a"}, maxDiscount=${d}`))}i(`[SUB-PREVIEW] side=B, currentProductId=${o??"n/a"}, maxDiscount=${d}`);function h(f){if(!t||!n)return null;const v=Y(n),g=v?n.get(v):void 0;return g?{formattedVariantPrice:G(g.priceInCents,t),formattedDiscounted:G(g.priceInCents*(1-f/100),t)}:null}function u(f){const v=J(a,f);if(!v)return d;const g=D(a,"subscriptionInput"),I=g.length?g[0].selector:'input[name="rc_plan"]',A=v.querySelector(`${I}:checked`);if(A){const E=c[A.value];if(E!==void 0)return E}return d}function b(f){const v=D(a,"subscriptionDiscount");for(const g of v)if(g.selector.includes("badge")||g.selector.includes("__badge")){const I=f.querySelector(g.selector);I?.textContent&&!I.textContent.includes(`${d}%`)&&$(I,A=>N(A,d))}}function k(f,v){const g=h(v);if(!g)return;const I=D(a,"subscriptionCompareAt");for(const A of I){const E=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);E?.textContent&&!E.textContent.includes(g.formattedVariantPrice)&&$(E,x=>/\d/.test(x)?g.formattedVariantPrice:x)}}function S(f,v){const g=h(v);if(!g)return;const I=D(a,"subscriptionPrice");for(const A of I){const E=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);E?.textContent&&!E.textContent.includes(g.formattedDiscounted)&&$(E,x=>/\d/.test(x)?g.formattedDiscounted:x)}}function P(f){const v=D(a,"subscriptionInput"),g=v.length?v[0].selector:'input[name="rc_plan"]',I=D(a,"subscriptionPlanDiscount"),A=I.length?I[0].selector:".rc-plans-button__discount";for(const E of Array.from(f.querySelectorAll("label"))){const x=E.querySelector(g),R=E.querySelector(A);if(x&&R?.textContent){const V=c[x.value];if(V!==void 0){const O=R.textContent.match(/[\d.]+%/)?.[0];O&&O!==`${V}%`&&$(R,L=>N(L,V))}}}}function _(f){const v=f.querySelector("select");if(v)for(const g of Array.from(v.options)){const I=c[g.value];if(I!==void 0&&g.textContent){const A=g.textContent.match(/[\d.]+%/)?.[0];A&&A!==`${I}%`&&(g.textContent=N(g.textContent,I))}}}function C(f){const v=D(a,"onetimePrice");if(!v.length||!t||!n)return;const g=Y(n),I=g?n.get(g):void 0;if(!I)return;const A=G(I.priceInCents,t),E=D(a,"onetimeContainer"),x=E.length?E[0].selector:'[part~="rc-purchase-option__onetime"]',R=f.querySelector(x);if(R)for(const V of v){const O=R.querySelector(`[part~="${V.selector}"]`);O?.textContent&&!O.textContent.includes(A)&&$(O,L=>/\d/.test(L)?A:L)}}function m(f,v){const I=D(a,"subscriptionDiscount").filter(A=>A.selector.includes("benefit")||A.selector==="rc-benefits");for(const A of I){const E=f.querySelector(A.selector);if(E?.shadowRoot){for(const x of Array.from(E.shadowRoot.querySelectorAll("li")))if(x.textContent?.includes("Save")){const R=x.textContent.match(/[\d.]+%/)?.[0];R&&R!==`${v}%`&&$(x,V=>N(V,v))}}}}let y=!1;function w(){if(!y){y=!0;try{p();const f=B(a);if(!f)return;const v=u(f);b(f),k(f,v),S(f,v),C(f);const g=J(a,f);g&&(r==="buttons"||r==="radio"?P(g):_(g)),m(f,v)}finally{y=!1}}}const T=dt({data:a,runUpdates:w});return function(){T(),s()}}const jt=Object.freeze(Object.defineProperty({__proto__:null,subscriptionPreviewRender:Gt},Symbol.toStringTag,{value:"Module"}))})(); })("/", { suffix: "", type: "article" }, "main", 188791652640, false)</script>
PT Practice Management and Growth Strategies – HomeCEUSkip to content
Running a successful physical therapy (PT) practice requires more than just clinical expertise.
Effective management, operational efficiency, and strategic growth planning are all important for keeping a PT practice thriving and growing. Whether managing a private PT practice or expanding an existing clinic, understanding key business principles helps therapists attract more patients, optimize workflow, and increase profitability.
By using structured management practices and adopting different growth strategies, physical therapists can build successful and sustainable practices while continuing to provide high-quality patient care.
This article explores key components of PT practice management and offers insights on growth strategies that can help PT clinics achieve long-term success.
A well-managed PT clinic operates efficiently, provides excellent patient care, and maintains financial stability. Success in practice management is dependent on balancing patient needs with business objectives.
Key elements of PT practice management
Patient-centered care.Focusing on high-quality, personalized treatment to improve patient outcomes and satisfaction.
Efficient operations. Streamlining administrative tasks, scheduling, and documentation to improve workflow.
Compliance and legal considerations. Adhering to industry regulations, billing policies, and documentation standards.
Marketing and outreach. Attracting new patients through community engagement, digital marketing, and physician referrals.
Staff training and retention. Investing in team development to maintain a skilled and motivated workforce.
Strategies for effective PT practice operations
A well-structured clinic relies on efficient operations, organized administration, and proper leadership. Establishing strong processes reduces overhead costs and allows for a smooth experience for both patients and staff. Some strategies for effective practice operations include:
Optimize scheduling and patient flow
Efficient scheduling makes sure that patient visits are well-managed, reducing wait times and improving clinic productivity. Some things to consider are:
Use automated scheduling software to minimize errors and no-shows.
Implement telehealth and flexible appointment options for better accessibility.
Train front-desk staff to handle scheduling changes and cancellations efficiently.
Balance patient load distribution among therapists to prevent overbooking.
Strengthen documentation and compliance
Accurate documentation is a must for reimbursement, legal protection, and patient progress tracking. Some tips include:
Use electronic health record (EHR) systems to streamline documentation.
Make sure compliance is kept with HIPAA and insurance regulations to avoid audits.
Allow for regular staff training on documentation best practices to maintain consistency.
Monitor audit trends to stay ahead of potential compliance risks.
Improve patient experience and retention
Patient satisfaction directly affects retention and referrals. Creating a welcoming and professional environment encourages repeat visits. Strategies to improve this include:
Offer patient education resources to promote engagement in their recovery.
Personalize care plans to align with individual patient goals.
Maintain open communication and follow up with patients after treatment.
Establish a feedback loop to assess patient satisfaction and implement improvements.
Growth strategies for PT practices
Expanding a PT clinic requires a strategic approach that considers patient demand, market trends, and operational capacity. Growth strategies should focus on increasing patient volume, diversifying services, and improving brand visibility. Some strategies include:
Expand referral networks
Referrals from physicians, chiropractors, and community organizations are very valuable for attracting new patients:
Develop relationships with local healthcare providers to establish referral partnerships.
Offer continuing education workshops for medical professionals to highlight the benefits of PT.
Use patient testimonials and success stories to build trust within the community.
Partner with local gyms, sports teams, and wellness centers to expand outreach.
Invest in digital marketing
An online presence helps attract new patients and improve brand awareness. Consider the following:
Maintain a user-friendly website with easy appointment booking options.
Take advantage of SEO strategies to improve local search visibility and stand out from the competition.
Engage with potential patients through social media, blog content, and email campaigns.
Leverage paid advertising strategies, such as Google Ads, to increase patient inquiries.
Diversify services and specialties
Offering specialized services broadens a clinic’s patient base and increases revenue opportunities:
Introduce niche services like sports rehabilitation, pelvic health therapy, or pediatric PT.
Implement cash-based wellness programs such as fitness training and injury prevention workshops.
Provide telehealth consultations to expand access to care.
Explore corporate wellness programs for local businesses to increase revenue streams.
Optimize revenue streams
Maximizing profitability involves evaluating existing services and identifying opportunities for financial growth. Some things to try are:
Offer membership-based wellness plans for ongoing patient engagement.
Reduce operational costs by optimizing supplier contracts and overhead expenses.
Consider value-added services like personal training, nutritional counseling, and ergonomic assessments.
Overcoming challenges in PT practice growth
Growing a PT practice involves navigating many different challenges, including competition, staffing shortages, and evolving industry trends. Some common challenges and potential solutions include:
Addressing staff recruitment and retention
Hiring and retaining skilled PTs and administrative staff is one of the most important components for sustained growth. Make sure to:
Provide competitive compensation packages and opportunities for professional development.
Foster a positive workplace culture that prioritizes work-life balance.
Offer mentorship programs to support career advancement.
Implement incentive programs to reward high-performing staff.
Managing increased patient volume
As a practice grows, maintaining high-quality patient care is important. Consider:
Scaling operations gradually to provide a balanced patient load.
Using technology and automation to improve administrative efficiency.
Expanding facility space and equipment as patient demand increases.
Developing standardized treatment protocols to maintain consistent quality of care where possible.
Keeping up with industry trends
The healthcare industry is constantly evolving, requiring PTs to stay informed about new treatment techniques and business innovations. Some ways to keep up with these evolving trends are:
Attend conferences and professional development workshops to stay up to date.
Adopt evidence-based treatment approaches to maintain credibility.
Implement patient feedback to continuously improve services.
Stay informed on insurance policy changes to avoid billing complications.
Conclusion
Successful PT practice management calls for a balance of strong operational practices, strategic marketing, and patient-centered care. By optimizing daily operations, investing in growth strategies, and addressing common challenges, PTs can build sustainable practices that provide high-quality care while remaining financially strong.
Whether expanding services, strengthening referral networks, or improving administrative efficiency, a well-structured approach allows for long-term success in the evolving physical therapy industry. As healthcare trends shift, adaptability and innovation will play key roles in maintaining a thriving practice.