<!-- 2026-05-11T14:56:11.6202540Z -->
<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-05-13T05:24:28.8474412Z */(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}/*$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",pt=/bot|spider|crawl|http|lighthouse/i,z;function ft(){if(z instanceof RegExp)return z;try{z=new RegExp(ht,"i")}catch{z=pt}return z}function gt(a){return!!a&&ft().test(a)}class Q{timestamp;constructor(){this.timestamp=new Date}}class mt extends Q{type;testId;hypothesisId;constructor(t,e,i){super(),this.type=3,this.testId=t,this.hypothesisId=e,this.timestamp=i}}class yt extends Q{type;path;constructor(t){super(),this.type=4,this.path=t}}class vt extends Q{type;cart;constructor(t){super(),this.type=5,this.cart=t}}class et extends Error{isBot;constructor(){super(),this.isBot=!0}}function wt(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 N(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=bt(a,i.cssSelector,o,l)}}return r.length>0&&s?(s(t,e),!0):!1}function bt(a,t,e,i){switch(i.type){case"innerHtml":e.innerHTML=i.value;break;case"attribute":St(e,i.scope,i.value);break;case"css":Ct(a,t,i.value);break;case"js":Tt(a,e,i);break;case"copy":return It(e);case"remove":Pt(e);break;case"move":At(e,parseInt(i.value));break}return e}function St(a,t,e){a.setAttribute(t,e)}function Ct(a,t,e){const i=a.createElement("style");i.innerHTML=`${t} { ${e} }`,a.getElementsByTagName("head")[0]?.appendChild(i)}function Tt(a,t,e){Function("document","element",`"use strict"; ${e.value}`)(a,t)}function It(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 Pt(a){a.remove()}function At(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 Et="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",xt="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 _t(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 Rt(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),h=ot(H(r-s,n,o,!1)),p=a.getAttribute("data-sl-format")||"percent";p==="percent"?a.textContent=`-${d}%`:p==="amount"?a.textContent=`-${h}`:p==="both"&&(a.textContent=`-${d}% (-${h})`)}}function Dt(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 Wt="modulepreload",Gt=function(a){return"/"+a},jt={},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],h=n[c];d&&h&&(l[d]=h)}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 U(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 Ot(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:h,hidePlanIds:p,swapMap:u}=at(i,s,d);a.swapMap=u;const b=D(i,"widgetParent"),E=D(i,"subscriptionPlans"),S=D(i,"subscriptionInput");if(!b.length||!E.length||!S.length)return;const P=document.querySelector(b[0].selector);if(!P?.shadowRoot)return;const _=P.shadowRoot.querySelector(E[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&&(h.includes(v.value)?g.style.display="":p.includes(v.value)&&(g.style.display="none"))}const w=y.some(v=>h.includes(v.value)&&v.checked),T=y.some(v=>p.includes(v.value)&&v.checked);if((w||T)&&(o=!1),!w&&!o){o=!0;for(const v of y)if(h.includes(v.value)){v.closest("label")?.click(),v.dispatchEvent(new Event("change",{bubbles:!0}));break}}const f=y.find(v=>v.checked);m=f&&h.includes(f.value)?f.value:h[0]??null}else if(i.widget.widgetType==="dropdown"){const y=_.shadowRoot.querySelector("select");if(!y)return;for(const w of Array.from(y.options))p.includes(w.value)&&(w.style.display="none",w.disabled=!0);if(p.includes(y.value)){const w=Array.from(y.options).find(T=>h.includes(T.value));w&&(y.value=w.value,y.dispatchEvent(new Event("change",{bubbles:!0})))}m=h.includes(y.value)?y.value:h[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 Lt({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 h of d.items){const p=String(h.selling_plan??"");p?h.selling_plan=r(p):!h.selling_plan&&e&&(h.properties||(h.properties={}),h.properties._slpt=e)}else if(d.id){const h=String(d.selling_plan??"");h?d.selling_plan=r(h):!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 $t({log:a}){if(window.fetch.__shoplift_intercepted)return a("[SUB-PREVIEW-BLOCK] interceptor 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(p){for(const u of n)u.disconnect();n.length=0;for(const u of Array.from(p.querySelectorAll("*")))if(u.shadowRoot){const b=new MutationObserver(s);b.observe(u.shadowRoot,o),n.push(b)}}function c(){const p=B(a);return p?(r&&r.disconnect(),l(p),r=new MutationObserver(u=>{u.some(b=>b.type==="childList"&&b.addedNodes.length>0)&&l(p),s()}),r.observe(p,o),!0):!1}const d=document.body||document.documentElement,h=new MutationObserver(()=>{c()&&s()});return h.observe(d,{childList:!0,subtree:!0}),c()&&s(),t(),function(){i&&(clearTimeout(i),i=null),h.disconnect(),r&&(r.disconnect(),r=null);for(const u of n)u.disconnect();n.length=0}}async function Mt(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),h=K(n,d),p=h.discountMap,u=h.maxDiscount;function b(){const g=W(l);g!==d&&(d=g,h=K(n,d),p=h.discountMap,u=h.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 E(){if(!l)return null;const g=j(l),I=Y(g),A=lt(n,I,d);if(!ct(A,o))return null;const k=I?g.get(I):void 0;return k?{formattedVariantPrice:G(k.priceInCents,l),formattedDiscounted:G(k.priceInCents*(1-u/100),l)}:null}Lt({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"),k=A.length?A[0].selector:'input[name="rc_plan"]';return I.querySelector(`${k}: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 k=g.querySelector(A.selector);k?.textContent&&!k.textContent.includes(`${u}%`)&&$(k,x=>U(x,u))}}function P(g){const I=E();if(!I)return;const A=D(n,"subscriptionCompareAt");for(const k of A){const x=g.querySelector(k.selector)||g.querySelector(`[part~="${k.selector}"]`);x?.textContent&&!x.textContent.includes(I.formattedVariantPrice)&&$(x,R=>/\d/.test(R)?I.formattedVariantPrice:R)}}function _(g,I){const A=D(n,"subscriptionCompareAt"),k=I===0?"none":"";for(const x of A){const R=g.querySelector(x.selector)||g.querySelector(`[part~="${x.selector}"]`);R&&(k==="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"]',k=D(n,"subscriptionPlanDiscount"),x=k.length?k[0].selector:".rc-plans-button__discount";for(const R of Array.from(g.querySelectorAll("label"))){const O=R.querySelector(A),V=R.querySelector(x);if(O&&V){const L=p[O.value];if(L!==void 0){if(L===0)V.style.display!=="none"&&(V.style.display="none");else if(V.style.display==="none"&&(V.style.display=""),V.textContent){const Z=V.textContent.match(/[\d.]+%/)?.[0];Z&&Z!==`${L}%`&&$(V,zt=>U(zt,L))}}}}}function m(g){const I=g.querySelector("select");if(I)for(const A of Array.from(I.options)){const k=p[A.value];if(k!==void 0&&A.textContent){const x=A.textContent.match(/[\d.]+%/)?.[0];x&&x!==`${k}%`&&(A.textContent=U(A.textContent,k))}}}function y(g,I){const k=D(n,"subscriptionDiscount").filter(x=>x.selector.includes("benefit")||x.selector==="rc-benefits");for(const x of k){const R=g.querySelector(x.selector);if(R?.shadowRoot){for(const O of Array.from(R.shadowRoot.querySelectorAll("li")))if(O.textContent?.includes("Save")){const V=O;if(I===0)V.style.display!=="none"&&(V.style.display="none");else{V.style.display==="none"&&(V.style.display="");const L=O.textContent.match(/[\d.]+%/)?.[0];L&&L!==`${I}%`&&$(O,Z=>U(Z,I))}}}}}let w=!1;function T(){if(!w){w=!0;try{if(b(),d!==null&&Object.keys(p).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 k=D(n,"subscriptionInput"),x=k.length?k[0].selector:'input[name="rc_plan"]',R=I.querySelector(`${x}:checked`);if(R){const O=p[R.value];O!==void 0&&(A=O)}c==="buttons"||c==="radio"?C(I):m(I)}_(g,A),y(g,A)}finally{w=!1}}}function f(){const g=E();if(!g)return;const I=B(n);if(!I)return;const A=D(n,"onetimeToggle"),k=A.length?A[0].selector:'input[value="onetime"]';if(!I.querySelector(k)?.checked)return;const R=D(n,"subscriptionPrice");for(const O of R){const V=I.querySelector(O.selector)||I.querySelector(`[part~="${O.selector}"]`);V?.textContent&&!V.textContent.includes(g.formattedDiscounted)&&$(V,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 qt(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,h=d?"control":"variant";a.slptValue=`${n}:${h}:f`,a.updatePriceTestHiddenInputs(n,h,!1);function p(){const u=B(o);if(!u)return;const b=Y(c);if(!b)return;const E=W(l),S=lt(o,b,E);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=p,p()}async function Ht(a,t){const{subscriptionPreviewRender:e}=await Vt(async()=>{const{subscriptionPreviewRender:i}=await Promise.resolve().then(()=>Bt);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 h(){if(!d){d=!0;try{p()}finally{d=!1}}}function p(){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 E(P){b?.disconnect(),b=new MutationObserver(()=>h()),b.observe(P,u)}function S(){const P=document.querySelector(r);if(!P?.shadowRoot)return!1;h(),new MutationObserver(()=>{h();const m=P.shadowRoot.querySelector(n);m?.shadowRoot&&E(m.shadowRoot)}).observe(P.shadowRoot,u);const C=P.shadowRoot.querySelector(n);return C?.shadowRoot&&E(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})}}let ut=!1;class Nt{constructor(t,e,i,s,r,n,o,l,c,d,h,p,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=h.map(E=>({...E,startAt:new Date(E.startAt),statusHistory:E.statusHistory.map(S=>({...S,createdAt:new Date(S.createdAt)}))})),this.inactiveTestConfigs=p,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=h.filter(E=>E.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;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,gt(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 _t(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=xt,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 h=document.createElement("span");if(h.id="shoplift-preview-variant-title",h.innerText=e?this.getDefaultVariantTitle(e):"Untitled variant "+i.toUpperCase(),c.appendChild(h),s.length>1){const b=document.createElement("img");b.src=Et,b.width=12,b.height=12,b.style.height="12px",b.style.width="12px",c.appendChild(b);const E=document.createElement("div");E.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)}),E.appendChild(P)}l.appendChild(E),c.addEventListener("click",()=>{E.className!=="preview-variant-menu preview-variant-menu__visible"?E.classList.add("preview-variant-menu__visible"):E.classList.remove("preview-variant-menu__visible")}),document.addEventListener("click",S=>{S.target instanceof Element&&!c.contains(S.target)&&E.className==="preview-variant-menu preview-variant-menu__visible"&&E.classList.remove("preview-variant-menu__visible")})}else c.style.pointerEvents="none",d.style.margin="0";l.appendChild(c),r.appendChild(l);const p=document.createElement("div"),u=document.createElement("button");u.id="shoplift-exit-preview-button",u.innerText="Exit",p.appendChild(u),u.addEventListener("click",()=>{this.exitPreview()}),r.appendChild(p),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.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&&(N(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 Ht({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,h=c.length,p=d+h,u=Math.random()*p;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,p,d,h,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,h=o.type==="price",p=d>=5;if(h&&p){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 E=this.getReservationForTest(b);E&&!E.isRealized&&E.entryCriteriaKey?this.realizeReservationForCriteria(E.entryCriteriaKey):this.queueAddVisitorToTest(b,o),this.saveState(),this.queuePageView(window.location.pathname),this.syncAllEvents()});continue}if(h&&!p){this.log(`Price test without viewport tracking (v${d}): ${i.id}`);const u=this.getDomSelectorsForHypothesis(o);if(u.length===0)continue;N(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}N(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=Dt(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 h=Math.floor(Math.random()*d.length),p=d[h];this.log("Test dice roll: picked index %d of %d, selected test '%s' (%s)",h+1,l.length,p.id,p.title);const u=this.pickHypothesis(p);if(!u){this.log("No hypothesis picked for test '%s'",p.id);continue}this.sendDiagnosticTelemetry("assignment",p.id,{hypothesisId:u.id,isControl:u.isControl,testType:u.type});const b=this.getReservationType(u.type),E={testId:p.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]=E,this.state.temporary.rolledEntryCriteria.push(o),this.log("Created %s reservation for test '%s' (criteria: %s)",b,p.id,o);for(const S of l)S.id!==p.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(h=>this.state.essential.visitorTests.some(p=>p.testId===h.id&&!p.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((h,p)=>h.id.localeCompare(p.id));this.log("Test dice roll for pool '%s' - available tests: %o",e,s.map(h=>({id:h.id,title:h.title,criteria:this.getEntryCriteriaKey(h)})));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 h of t)h.id!==n.id&&this.markTestAsBlocked(h,`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),N(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 mt(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(ut)return;ut=!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 Ot(this)}async subscriptionPriceChange(){await Mt(this)}async subscriptionOneTimePrice(){await qt(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&&N(document,{testId:t,hypothesisId:m,selectors:T})},h=(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)}},p=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}"`),h(T,p)}});c(p,"initial setup"),n.add(p);const u=new MutationObserver(C=>{C.forEach(m=>{m.addedNodes.forEach(y=>{if(y.nodeType===Node.ELEMENT_NODE){const w=y;E(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&&h(f,p),this.log("Re-running payment placement updates after variant change"),E(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 E=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"),h(y,p)),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(),E(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(),E(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 h=c.getAttribute("data-sl-pid");if(!h){this.log("Hidden input has no data-sl-pid attribute - skipping");return}const p=n.find(S=>{const P=S.cssSelector.match(o);return P&&P[1]===h});if(!p){this.log(`No matching selector found for productId: ${h} - skipping element`);return}const u=p.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 ${h} - skipping`);return}const E=Math.round(b*100);s(l,E)}),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 h=JSON.parse(d);if(h.variants&&Array.isArray(h.variants)){const p=h.variants.find(u=>u.id?.toString()===o);if(p){p.full_price=c.value;const u=parseFloat(c.value.replace(/[^0-9.]/g,""));if(p.number_of_payment_terms&&p.number_of_payment_terms>1){const b=u/p.number_of_payment_terms;p.price_per_term=`$${b.toFixed(2)}`}n.setAttribute("shopify-meta",JSON.stringify(h))}}}catch(h){this.log("Error parsing/updating shoplift-meta:",h)}}}})}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 vt(t))}queuePageView(t){this.queueEvent(new yt(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(p=>p.testId===o)||this.activeViewportObservers.has(o))return;const l=[];if(r.forEach(p=>{t.querySelectorAll(p.cssSelector).forEach(b=>l.push(b))}),l.length===0)return;let c=!1;const d=()=>{c||(c=!0,i(o),h.disconnect(),this.activeViewportObservers.delete(o))},h=this.createViewportObserver(()=>{d()},{triggerOnce:!0,...s});this.activeViewportObservers.set(o,h),this.log(`Created viewport observer for test ${o}, observing ${l.length} elements`),l.forEach(p=>{p.setAttribute(this.DATA_SL_TEST_ID,String(o)),h.observe(p)}),setTimeout(()=>{c||l.forEach(p=>{const u=p.getBoundingClientRect(),b=s?.threshold??this.VIEWPORT_TRACK_THRESHOLD,E=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&&E>0&&S>0&&E>=u.height*b&&(this.log(`Price element already visible in viewport for test ${o}:`,p),d())})},100)};e.selectors.length>0&&N(t,e,()=>{}),wt(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 h="[data-sl-attribute-p], [data-sl-attribute-cap], [data-sl-attribute-discount]",p=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),Rt(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(h);this.log("Scanning for price elements, found: %d",S.length),S.forEach(p)},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"))&&p(C),C.querySelectorAll(h).forEach(p)}}),P.type==="attributes"&&P.target instanceof Element&&p(P.target)}),E=document.body||document.documentElement;b.observe(E,{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 h of d)if(h.isIntersecting&&h.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 Nt("contractor-training-center.myshopify.com","https://app.shoplift.ai","https://events.shoplift.ai",true,false,false,{"sendEvents":false,"mode":"gtag"},false,false,1000,[{"id":"019ce2de-d4f2-7941-9c43-bb17c03e9f86","startAt":"2026-03-12T16:26:20.274169Z","requiresCountry":false,"bayesianRevision":5,"device":"all","status":"active","visitorOption":"all","ignoreTestViewParameterEnforcement":false,"statusHistory":[{"status":"active","createdAt":"2026-03-12T16:26:20.278605Z"}],"hypotheses":[{"visitorCount":0,"trafficPercentage":0.0,"title":"Original","domSelectors":[],"id":"019ce27c-5a27-7438-8f60-475eb6ed58fb","type":"cart","themeId":145715855437,"affix":"","isControl":true},{"visitorCount":4623,"trafficPercentage":1.0,"title":"New Promo Banner","domSelectors":[],"id":"019ce27c-f9ca-7378-9967-a5459d009f53","type":"cart","themeId":145715855437,"affix":"sl-595D4A49","isControl":false}],"targetAudiences":[],"title":"Promo Banner on cart page"},{"id":"019d6da6-b10f-708c-b89a-61072bad7467","startAt":"2026-04-08T15:12:14.095244Z","requiresCountry":false,"bayesianRevision":5,"device":"all","status":"active","visitorOption":"all","ignoreTestViewParameterEnforcement":false,"statusHistory":[{"status":"active","createdAt":"2026-04-08T15:12:14.101304Z"}],"hypotheses":[{"visitorCount":0,"trafficPercentage":0.0,"title":"Original","domSelectors":[],"id":"019d6da2-1d6d-79ab-9d55-24cb5698ba98","type":"product","themeId":145715855437,"affix":"detail-update","isControl":true},{"visitorCount":16845,"trafficPercentage":1.0,"title":"Untitled variant","domSelectors":[],"id":"019d6da2-1d6d-764d-b012-e0057c69dd6a","type":"product","themeId":145715855437,"affix":"sl-8DC1ED79","isControl":false}],"targetAudiences":[[(visitor, isNew, channel, country) => !window.location.href.includes("nascla-commercial-builder-pro-plus-exam-prep-package-v2") && !window.location.href.includes("nascla-commercial-builder-pro-exam-prep-package-v2") && !window.location.href.includes("complete-book-set-national-nascla-commercial-builder-exam-tabbed-and-highlighted-book-bundle-v2")]],"title":"Promo Banner on product pages V2"}],[{"id":"d62fd5ff-8d97-4bc3-966c-6b375eb4b4e3","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"a07829a9-8cdb-49b1-bb5b-9d0e280710dc","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/tennessee-nascla"},{"id":"e7266e3f-8b6b-4b83-a3c5-3705462ad8b4","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/tennessee-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"32b871a1-74c5-454d-bbfa-cda5c76a18db","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"50bddbeb-5e51-4216-8718-7785dad51deb","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/alabama-nascla"},{"id":"0a96febd-f8f3-4ba6-8223-68755448a3f6","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/alabama-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"e2b17d40-8734-4b2e-9ea3-c3b43c2730ef","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"2b61976f-e98f-4a7b-a267-d40831319a41","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/blogs/news/how-to-become-a-general-contractor-in-florida"},{"id":"0446231e-5f9f-40f9-a947-1797aed3d376","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/blogs/news/how-to-become-a-general-contractor-in-florida-2"}],"ignoreTestViewParameterEnforcement":false},{"id":"a236d4df-032d-451d-b812-930a9cfdbde1","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"88c451bc-07e9-4ce6-983a-06bc0da3b993","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/national-nascla"},{"id":"3d13597d-fa1f-4b2c-ac75-d8c1ce2f12ba","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/national-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"83fd2840-50f0-4708-ab19-88c16f26e16f","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"88ad32a4-0b96-4baa-b2d2-ac86fcdfd2ed","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/north-carolina-nascla"},{"id":"e59d1630-be2c-4e7f-8a66-a25fc673d139","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/north-carolina-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"f5f70c72-fa17-40a1-a617-5948c6a12b72","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"112e32ad-9da0-4cd0-b437-2d5e8353ee2b","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/florida-nascla"},{"id":"3e21781a-734b-4f11-b199-de47c857052a","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/florida-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"b1f7d851-d996-4dbf-94a4-e38457d3d7e9","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"0843b1af-e47e-4ee7-abe1-64e43169e314","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/south-carolina-unlimited"},{"id":"fefad671-6f8b-43fc-81ea-dfde7d8d21ac","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/south-carolina-unlimited-builder-nascla-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"8d4ca658-f904-42a3-bcce-c1acce4b70ad","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"5fa2e4b9-8ca5-45b0-8bd5-1910c33b45e9","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/virginia-nascla"},{"id":"0144f64d-a6ae-4119-bba5-1e08d9c2e34b","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/virginia-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"019bbd9c-5160-7d56-919e-fd93f9165564","bayesianRevision":5,"status":"paused","hypotheses":[{"id":"019bb8f1-cb33-7077-9cb9-bbbc6e8bd20a","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/california-general-building-b-contractor-exam-prep-courses"},{"id":"019bb8f8-5d0e-714f-bf11-d937b6144780","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/california-general-building-b-contractor-exam-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"6cdd87fb-6dd9-4539-be55-efb3c150cd7b","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"d20ec80d-336a-4cf7-b2e0-d6e9498322fc","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/national-nascla"},{"id":"c8f20010-bd9d-4b62-b138-e6e14ba074cc","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/national-nascla-2"}],"ignoreTestViewParameterEnforcement":false},{"id":"019ce326-8e63-7a59-91ee-b11a99ea81b9","bayesianRevision":5,"status":"paused","hypotheses":[{"id":"019ce31d-0e53-7782-847e-db2d75f2b13f","type":"product","themeId":145715855437,"affix":"detail-update","isControl":true,"redirectPath":null},{"id":"019ce31d-2b3d-768f-8cb9-dc1471f63e0a","type":"product","themeId":145715855437,"affix":"sl-8DC1ED79","isControl":false,"redirectPath":null}],"ignoreTestViewParameterEnforcement":false},{"id":"cf472a25-ce5a-4616-a960-c0a6d4586b63","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"d5ec812b-b1fc-43de-bb17-07a4bb8f276e","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/louisiana-nascla"},{"id":"7f4fe4ed-4479-448d-a38f-69531ebe8f18","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/louisiana-nascla-commercial-builder-exam-a-b"}],"ignoreTestViewParameterEnforcement":false},{"id":"686d7f35-217c-42b7-9bad-4551e103e78b","bayesianRevision":3,"status":"paused","hypotheses":[{"id":"f83e155d-f09f-45b5-809e-a06694622823","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":true,"redirectPath":"/collections/georgia-nascla"},{"id":"286fdf32-bc6a-4a3f-8c21-bb7c0833b068","type":"urlRedirect","themeId":145715855437,"affix":"","isControl":false,"redirectPath":"/collections/georgia-nascla-general-contractor-exam-a-b"}],"ignoreTestViewParameterEnforcement":false}],null),await window.shopliftInstance.init())})();async function Ft(a,t,e,i){const s=$t({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 h(){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 p(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 k=c[A.value];if(k!==void 0)return k}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=>U(A,d))}}function E(f,v){const g=p(v);if(!g)return;const I=D(a,"subscriptionCompareAt");for(const A of I){const k=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);k?.textContent&&!k.textContent.includes(g.formattedVariantPrice)&&$(k,x=>/\d/.test(x)?g.formattedVariantPrice:x)}}function S(f,v){const g=p(v);if(!g)return;const I=D(a,"subscriptionPrice");for(const A of I){const k=f.querySelector(A.selector)||f.querySelector(`[part~="${A.selector}"]`);k?.textContent&&!k.textContent.includes(g.formattedDiscounted)&&$(k,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 k of Array.from(f.querySelectorAll("label"))){const x=k.querySelector(g),R=k.querySelector(A);if(x&&R?.textContent){const O=c[x.value];if(O!==void 0){const V=R.textContent.match(/[\d.]+%/)?.[0];V&&V!==`${O}%`&&$(R,L=>U(L,O))}}}}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=U(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),k=D(a,"onetimeContainer"),x=k.length?k[0].selector:'[part~="rc-purchase-option__onetime"]',R=f.querySelector(x);if(R)for(const O of v){const V=R.querySelector(`[part~="${O.selector}"]`);V?.textContent&&!V.textContent.includes(A)&&$(V,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 k=f.querySelector(A.selector);if(k?.shadowRoot){for(const x of Array.from(k.shadowRoot.querySelectorAll("li")))if(x.textContent?.includes("Save")){const R=x.textContent.match(/[\d.]+%/)?.[0];R&&R!==`${v}%`&&$(x,O=>U(O,v))}}}}let y=!1;function w(){if(!y){y=!0;try{h();const f=B(a);if(!f)return;const v=u(f);b(f),E(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 Bt=Object.freeze(Object.defineProperty({__proto__:null,subscriptionPreviewRender:Ft},Symbol.toStringTag,{value:"Module"}))})(); })("/", { suffix: "detail-update", type: "product" }, "main", 145715855437, false)</script>
Tabs for Arizona R-11 Residential Electrical Exam Book Bundle
Our Arizona R-11 exam prep tabs help mark the commonly referenced sections of the books used in the exam. Don't waste time flipping through your books in the timed exam - our tabs help you to be able to quickly reference important material in your books and move on to the next question without wasting valuable time.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Description
Our Arizona R-11 exam prep tabs help mark the commonly referenced sections of the books used in the exam. Don't waste time flipping through your books in the timed exam - our tabs help you to be able to quickly reference important material in your books and move on to the next question without wasting valuable time.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Navigating the requirements of becoming a contractor can be confusing, and the process often changes from state to state. Whether you are a first-time applicant or an experienced contractor looking for a license in additional states, getting the answers to your questions can be tedious and time-consuming. Let us help you streamline this process an build a plan to reach your career goals with a 30-minute start-up call and follow-up email support with a contractor licensing expert!
Our exam prep tabs help mark the commonly referenced sections of the books used within the National NASCLA Commercial Builder exam, allowing you to navigate the books more quickly during the timed test. The exam vendor, PSI, will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs.
The National NASCLA Commercial Builder Exam is accepted as a trade exam in 17 states:Alabama, Arizona, Arkansas, California, Florida, Georgia, Louisiana, Mississippi, Nevada, New Mexico, North Carolina, Oregon, South Carolina, Tennessee, Utah, Virginia, West Virginia & the U.S. Virgin Islands.
These are the books you will need to take the NASCLA Commercial Builder Exam at PSI. PSI will allow you to bring up to 24books into the exam; we have determined that the 23books listed below contain all of the material necessary to pass the exam.
Prepare for theNational NASCLA Exam for Master/Unlimited Electrical Contractorsat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
Not sure if you're ready for the National NASCLA Commercial Builder Exam? Review all the vital information you'll need to know in a 4-hour Session hosted by our Exam Experts!
Extend existing access to our online learning system for our NASCLA Commercial Builder Exam Prep Course. This is only available for existing students who have already purchased NASCLA Commercial Builder Exam Prep courses and materials.
NOTICE: Course extensions are for 3 months. If you'd like 6-month access, please repurchase your course.
The NASCLA Accredited Trade Examination for Electrical Contractors is an open-bookexam. This book bundle contains the following reference manuals which are allowed into the exam, with our exam prep tabs and course curriculum highlights applied within each:
National Electrical Code - NFPA 70, 2023 edition
Code of Federal Regulations - 29 CFR 1926 - OSHA Construction Industry Regulations, 2024
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards, 2024
A Guide to the Project Management Body of Knowledge, Project Management Institute, 2021, 7th edition
ANSI/ASHRAE/IES 90.1-2022, Energy Standard for Sites and Buildings Except Low-Rise Residential Buildings
NASCLA Contractors Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 edition
Ugly’s Electrical References, 2023 Edition
Understanding Electrical Theory for NEC Applications
Prepare for the Arizona B-1/B-2/KB-1/KB-2 General Residential Contractor/General Small Commercial Contractor/Dual Contractor combined exam at PSI with this exam-ready pre-tabbed and highlighted book bundle, containing the following references:
References included in both bundle options (with tabs and highlights, allowed into exam):
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
International Building Code, 2018 edition
International Residential Code for One- & Two-Family Dwellings, 2018 edition
References included in Supplemental Study References option (plain books without tabs & highlights, these books not allowed into exam):
Carpentry and Building Construction
Design and Control of Concrete Mixtures
Pipe and Excavation Contracting
Modern Masonry - Brick, Block, Stone
Technical Digest No. 9: Handling and Erection of Steel Joists and Joist Girders
Prepare for the Arizona B-1/B-2/KB-1/KB-2 General Residential Contractor/General Small Commercial Contractor/Dual Contractor combined exam at PSI with this exam prep book bundle, containing the following references:
References included in both bundle options (allowed into exam):
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
International Building Code, 2018 edition
International Residential Code for One- & Two-Family Dwellings, 2018 edition
References included in Supplemental Study References option (NOTallowed into exam):
Carpentry and Building Construction
Design and Control of Concrete Mixtures
Pipe and Excavation Contracting
Modern Masonry - Brick, Block, Stone
Technical Digest No. 9: Handling and Erection of Steel Joists and Joist Girders
This tab set includes tabs for all books allowed inside the Arizona B-1 General Contractor exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
These tabs are for marking important subject areas within the texts for the National NASCLA Electrical Contractor (Master/Unlimited) Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Prepare for theNational NASCLA Exam for Residential Electrical Contractorsat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
Prepare for theNational NASCLA Exam for Electrical Journeymanat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam.
This bundle contains the following references with tabs and our course curriculum highlights within each book.
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
The NASCLA Accredited Trade Examination for Electrical Contractors is an open-bookexam. This book bundle contains the following reference manuals which are allowed into the exam:
National Electrical Code - NFPA 70, 2023 edition
Code of Federal Regulations - 29 CFR 1926 - OSHA Construction Industry Regulations, 2024
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards, 2024
A Guide to the Project Management Body of Knowledge, Project Management Institute, 2021, 7th edition
ANSI/ASHRAE/IES 90.1-2022, Energy Standard for Sites and Buildings Except Low-Rise Residential Buildings
NASCLA Contractors Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 edition
Ugly’s Electrical References, 2023 Edition
Understanding Electrical Theory for NEC Applications
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive. Tabs for this book bundle are sold separately, listed here.
The NASCLA Accredited Trade Examination for Residential Electrical Contractors is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam,with our exam prep tabs and highlights applied within each book:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards, 2024
NASCLA Contractor's Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
This book bundle is for the open book Arizona CR-69 Asphalt Paving Exam. It is an open book exam, and you can tab and highlight the books. We provide an exam prep course with practice exam questions as well.
This is a pre-tabbed and highlighted book bundle. Books contain our permanent tabs as well as our course curriculum highlights. There are three different Asphalt Paving license classifications in Arizona. You only need to take one of the three exams.
Please be sure to select the correct bundle for the Asphalt Paving Exam you are taking.
Per PSI: "Candidates are responsible for bringing their own references to the examination center. Reference materials may be highlighted, underlined, annotated, and/or indexed before the examination session. However, references may not be written in during the examination session."
The following references are allowed into the Arizona CR-69 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Pipe and Excavation Contracting
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
The following references are allowed into the Arizona A-14 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
The following references are allowed into the Arizona R-13 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam.
This bundle contains the following references with tabs and our course curriculum highlights within each book.
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
The NASCLA Accredited Trade Examination for Journeyman Electricians is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam, with our exam prep tabs and highlights applied within:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
Our exam prep tabs mark the specific sections of the book that are most often referenced in questions, helping you navigate the books quickly during the timed exams. You cannot use tabs such as post-its, as tabsmusthave permanent adhesive (per PSI). Our permanent, pre-printed tabs are approved for use within the references for PSI exams.
This tab set includes tabs for the books used in the Arizona Asphalt Paving Exams at PSI. Still need your books for the exam?We offer them in a bundle here.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
The Arizona Asphalt Paving Exam is an open-book exam.
Please be sure to select the correct bundle for the Asphalt Paving Exam you are taking.
The following references are allowed into the Arizona CR-69 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Pipe and Excavation Contracting
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
The following references are allowed into the Arizona A-14 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
The following references are allowed into the Arizona R-13 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
Reference material may be highlighted, underlined, and/or indexed. They must be otherwise unmarked (not written in) and may not contain additional papers (loose or attached).
References may be tabbed/indexed with permanent tabs only. Temporary tabs, such as Post-It notes, are not allowed and must be removed from the reference before the exam will begin.
We offer the reference manual and permanent tabs for the exam. We also offer pre-tabbed and highlighted reference books to save you the time of highlighting yourself!
These tabs are for marking important subject areas within the texts for the National NASCLA Residential Electrical Contractor Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Our Arizona R-11 exam prep tabs help mark the commonly referenced sections of the books used in the exam. Don't waste time flipping through your books in the timed exam - our tabs help you to be able to quickly reference important material in your books and move on to the next question without wasting valuable time.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam. This bundle contains the following references:
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors C-11 Commercial Electrical Contractor exam at PSI. This exam is a partial open-book exam. This bundle contains the following references:
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
These tabs are for marking important subject areas within the texts for the National NASCLA Residential Electrical Contractor Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
The NASCLA Accredited Trade Examination for Residential Electrical Contractors is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards, 2024
NASCLA Contractor's Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
International Residential Code, 2024 edition
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive.
The NASCLA Accredited Trade Examination for Journeyman Electricians is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam:
NFPA 70 - National Electrical Code, 2020 edition
29 CFR 1926 OSHA Construction Industry Regulations, with latest available amendments
Delmar's Standard Textbook of Electricity, 2016, 6th Edition
International Residential Code for One- and Two-Family Dwellings, 2015 edition
NFPA 101 - Standard for Life Safety Code, 2015
NFPA 70E - Standard for Electrical Safety in the Workplace
NFPA 72 - National Fire Alarm and Signaling Code
Ugly’s Electrical References, 2020 Edition
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive.
Navigating the requirements of becoming a contractor can be confusing, and the process often changes from state to state. Whether you are a first-time applicant or an experienced contractor looking for a license in additional states, getting the answers to your questions can be tedious and time-consuming. Let us help you streamline this process an build a plan to reach your career goals with a 30-minute start-up call and follow-up email support with a contractor licensing expert!
Our exam prep tabs help mark the commonly referenced sections of the books used within the National NASCLA Commercial Builder exam, allowing you to navigate the books more quickly during the timed test. The exam vendor, PSI, will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs.
The National NASCLA Commercial Builder Exam is accepted as a trade exam in 17 states:Alabama, Arizona, Arkansas, California, Florida, Georgia, Louisiana, Mississippi, Nevada, New Mexico, North Carolina, Oregon, South Carolina, Tennessee, Utah, Virginia, West Virginia & the U.S. Virgin Islands.
These are the books you will need to take the NASCLA Commercial Builder Exam at PSI. PSI will allow you to bring up to 24books into the exam; we have determined that the 23books listed below contain all of the material necessary to pass the exam.
Prepare for theNational NASCLA Exam for Master/Unlimited Electrical Contractorsat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
Not sure if you're ready for the National NASCLA Commercial Builder Exam? Review all the vital information you'll need to know in a 4-hour Session hosted by our Exam Experts!
Extend existing access to our online learning system for our NASCLA Commercial Builder Exam Prep Course. This is only available for existing students who have already purchased NASCLA Commercial Builder Exam Prep courses and materials.
NOTICE: Course extensions are for 3 months. If you'd like 6-month access, please repurchase your course.
The NASCLA Accredited Trade Examination for Electrical Contractors is an open-bookexam. This book bundle contains the following reference manuals which are allowed into the exam, with our exam prep tabs and course curriculum highlights applied within each:
National Electrical Code - NFPA 70, 2023 edition
Code of Federal Regulations - 29 CFR 1926 - OSHA Construction Industry Regulations, 2024
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards, 2024
A Guide to the Project Management Body of Knowledge, Project Management Institute, 2021, 7th edition
ANSI/ASHRAE/IES 90.1-2022, Energy Standard for Sites and Buildings Except Low-Rise Residential Buildings
NASCLA Contractors Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 edition
Ugly’s Electrical References, 2023 Edition
Understanding Electrical Theory for NEC Applications
Prepare for the Arizona B-1/B-2/KB-1/KB-2 General Residential Contractor/General Small Commercial Contractor/Dual Contractor combined exam at PSI with this exam-ready pre-tabbed and highlighted book bundle, containing the following references:
References included in both bundle options (with tabs and highlights, allowed into exam):
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
International Building Code, 2018 edition
International Residential Code for One- & Two-Family Dwellings, 2018 edition
References included in Supplemental Study References option (plain books without tabs & highlights, these books not allowed into exam):
Carpentry and Building Construction
Design and Control of Concrete Mixtures
Pipe and Excavation Contracting
Modern Masonry - Brick, Block, Stone
Technical Digest No. 9: Handling and Erection of Steel Joists and Joist Girders
Prepare for the Arizona B-1/B-2/KB-1/KB-2 General Residential Contractor/General Small Commercial Contractor/Dual Contractor combined exam at PSI with this exam prep book bundle, containing the following references:
References included in both bundle options (allowed into exam):
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
International Building Code, 2018 edition
International Residential Code for One- & Two-Family Dwellings, 2018 edition
References included in Supplemental Study References option (NOTallowed into exam):
Carpentry and Building Construction
Design and Control of Concrete Mixtures
Pipe and Excavation Contracting
Modern Masonry - Brick, Block, Stone
Technical Digest No. 9: Handling and Erection of Steel Joists and Joist Girders
This tab set includes tabs for all books allowed inside the Arizona B-1 General Contractor exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
These tabs are for marking important subject areas within the texts for the National NASCLA Electrical Contractor (Master/Unlimited) Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Prepare for theNational NASCLA Exam for Residential Electrical Contractorsat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
Prepare for theNational NASCLA Exam for Electrical Journeymanat PSI with our online exam prep course!
This exam prep course includes access to our online self-paced course with discussions of best practices for taking the exam, book highlighting instruction videos, practice quizzes, learning modules, and an exam simulator mirroring the features of the real exam at PSI.
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam.
This bundle contains the following references with tabs and our course curriculum highlights within each book.
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
The NASCLA Accredited Trade Examination for Electrical Contractors is an open-bookexam. This book bundle contains the following reference manuals which are allowed into the exam:
National Electrical Code - NFPA 70, 2023 edition
Code of Federal Regulations - 29 CFR 1926 - OSHA Construction Industry Regulations, 2024
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards, 2024
A Guide to the Project Management Body of Knowledge, Project Management Institute, 2021, 7th edition
ANSI/ASHRAE/IES 90.1-2022, Energy Standard for Sites and Buildings Except Low-Rise Residential Buildings
NASCLA Contractors Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 edition
Ugly’s Electrical References, 2023 Edition
Understanding Electrical Theory for NEC Applications
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive. Tabs for this book bundle are sold separately, listed here.
The NASCLA Accredited Trade Examination for Residential Electrical Contractors is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam,with our exam prep tabs and highlights applied within each book:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards, 2024
NASCLA Contractor's Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
This book bundle is for the open book Arizona CR-69 Asphalt Paving Exam. It is an open book exam, and you can tab and highlight the books. We provide an exam prep course with practice exam questions as well.
This is a pre-tabbed and highlighted book bundle. Books contain our permanent tabs as well as our course curriculum highlights. There are three different Asphalt Paving license classifications in Arizona. You only need to take one of the three exams.
Please be sure to select the correct bundle for the Asphalt Paving Exam you are taking.
Per PSI: "Candidates are responsible for bringing their own references to the examination center. Reference materials may be highlighted, underlined, annotated, and/or indexed before the examination session. However, references may not be written in during the examination session."
The following references are allowed into the Arizona CR-69 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Pipe and Excavation Contracting
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
The following references are allowed into the Arizona A-14 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
The following references are allowed into the Arizona R-13 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam.
This bundle contains the following references with tabs and our course curriculum highlights within each book.
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
The NASCLA Accredited Trade Examination for Journeyman Electricians is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam, with our exam prep tabs and highlights applied within:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards
Code of Federal Regulations - 29 CFR 1910 - OSHA Occupational Safety and Health Standards
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
Our exam prep tabs mark the specific sections of the book that are most often referenced in questions, helping you navigate the books quickly during the timed exams. You cannot use tabs such as post-its, as tabsmusthave permanent adhesive (per PSI). Our permanent, pre-printed tabs are approved for use within the references for PSI exams.
This tab set includes tabs for the books used in the Arizona Asphalt Paving Exams at PSI. Still need your books for the exam?We offer them in a bundle here.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
The Arizona Asphalt Paving Exam is an open-book exam.
Please be sure to select the correct bundle for the Asphalt Paving Exam you are taking.
The following references are allowed into the Arizona CR-69 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Pipe and Excavation Contracting
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
The following references are allowed into the Arizona A-14 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
The Contractor's Guide to Quality Concrete Construction
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
The following references are allowed into the Arizona R-13 exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
Construction, Planning, Equipment, and Methods
Excavation and Grading Handbook
Hot-Mix Asphalt Paving Handbook
Manual on Uniform Traffic Control Devices for Streets and Highways
Pipe and Excavation Contracting
Reference material may be highlighted, underlined, and/or indexed. They must be otherwise unmarked (not written in) and may not contain additional papers (loose or attached).
References may be tabbed/indexed with permanent tabs only. Temporary tabs, such as Post-It notes, are not allowed and must be removed from the reference before the exam will begin.
We offer the reference manual and permanent tabs for the exam. We also offer pre-tabbed and highlighted reference books to save you the time of highlighting yourself!
These tabs are for marking important subject areas within the texts for the National NASCLA Residential Electrical Contractor Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
Our Arizona R-11 exam prep tabs help mark the commonly referenced sections of the books used in the exam. Don't waste time flipping through your books in the timed exam - our tabs help you to be able to quickly reference important material in your books and move on to the next question without wasting valuable time.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors R-11 Residential Electrical Contractor exam at PSI. This exam is a partial open-book exam. This bundle contains the following references:
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
This book bundle contains the reference manuals necessary to prepare for and pass the Arizona Registrar of Contractors C-11 Commercial Electrical Contractor exam at PSI. This exam is a partial open-book exam. This bundle contains the following references:
Books allowed into the exam:
Code of Federal Regulations - 29 CFR Part 1926 (OSHA), with latest available amendments
NFPA 70: National Electrical Code, 2017
NFPA 72: National Fire Alarm Code, 2016
Books not allowed into the exam, but used as study references:
These tabs are for marking important subject areas within the texts for the National NASCLA Residential Electrical Contractor Exam at PSI.
Our exam prep tabs help mark the commonly referenced sections of the books used within the exam, allowing you to navigate the books more quickly during the timed test. PSI will not allow you to use anything other than permanent tabs, such as our pre-printed permanent tabs. These tabs are important to help you pass the exam.
These tabs may come on varied colored tabs or all white tabs; content on tabs and materials does not change, but colors of the tabs may vary from the item photograph above depending on supplier availability.
The NASCLA Accredited Trade Examination for Residential Electrical Contractors is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam:
NFPA 70, National Electrical Code, 2023 edition
29 CFR 1926 OSHA Construction Industry Regulations & Standards, 2024
NASCLA Contractor's Guide to Business, Law and Project Management - Basic, 14th edition
NFPA 70E - Standard for Electrical Safety in the Workplace, 2024 Edition
Ugly Electrical References, 2023 Edition
NFPA 72, National Fire Alarm and Signaling Code, 2022 edition
Understanding Electrical Theory for NEC Applications
International Residential Code, 2024 edition
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive.
The NASCLA Accredited Trade Examination for Journeyman Electricians is an open-bookexam. This book bundle contains each of the following approved reference manuals that PSI will allow you into the exam:
NFPA 70 - National Electrical Code, 2020 edition
29 CFR 1926 OSHA Construction Industry Regulations, with latest available amendments
Delmar's Standard Textbook of Electricity, 2016, 6th Edition
International Residential Code for One- and Two-Family Dwellings, 2015 edition
NFPA 101 - Standard for Life Safety Code, 2015
NFPA 70E - Standard for Electrical Safety in the Workplace
NFPA 72 - National Fire Alarm and Signaling Code
Ugly’s Electrical References, 2020 Edition
Books can be highlighted and/or underlined but not written in. You may also attach tabs to mark important sections of the book, but only using tabs with permanent adhesive.
$999.97
Choosing a selection results in a full page refresh.