1<!DOCTYPE html> 2 3<html lang="en"> 4<head> 5 <meta name="google-site-verification" content="-WIPJyy2Ng7K07tModat6XpGUfyEYC5-2hqlG8Zo-gs" /> 6 <meta charset="UTF-8" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 <title>Good Sleep Co | Good Sleep Co</title> 9 <meta name="description" content="" /> 10 <link rel="canonical" href="https://goodsleepco.health/" /> 11 <meta property="og:title" content="Good Sleep Co" /> 12 <meta property="og:description" content="" /> 13 <meta property="og:url" content="https://goodsleepco.health/" /> 14 <meta property="og:type" content="website" /> 15 <meta property="og:site_name" content="Good Sleep Co" /> 16 <meta property="og:image" content="https:files/Screen_Shot_2022-07-29_at_3.59.41_pm.png" /> 17
17<script type="application/ld+json"> 18 { 19 "@context": "https://schema.org", 20 "@type": ["Organization", "MedicalBusiness"], 21 "name": "Good Sleep Co", 22 "url": "https://goodsleepco.health", 23 "logo": "https://cdn.shopify.com/s/files/1/0598/2417/7291/files/good-sleep-co-logo-long.svg", 24 "description": "At-home sleep apnea testing and clinically proven oral devices for snoring and sleep apnea treatment.", 25 "telephone": "+61756902029", 26 "email": "[email protected]", 27 "address": { 28 "@type": "PostalAddress", 29 "streetAddress": "U2/46 Junction Rd", 30 "addressLocality": "Burleigh Heads", 31 "addressRegion": "QLD", 32 "postalCode": "4220", 33 "addressCountry": "AU" 34 }, 35 "sameAs": [ 36 "https://www.facebook.com/GoodSleepCo", 37 "https://www.instagram.com/goodsleep_co/", 38 "https://www.linkedin.com/company/good-sleep-co/" 39 ] 40 } 41 </script>
41 42 <link rel="icon" type="image/png" href="https://cdn.shopify.com/s/files/1/0718/2372/0537/files/good_sleep_fav.png?v=1685575978"> 43 44 <!-- Google Tag Manager --> 45
45<script>
vendor: 335 bytes, lines 45-49
45(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 46 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 47 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 48 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 49 })(window,document,'script','dataLayer','
49GTM-M3CLJRL4
vendor: 3 bytes, line 49
49');
49</script>
49 50 51 <!-- Meta Pixel --> 52
52<script>
vendor: 419 bytes, lines 52-58
52 53 !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? 54 n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; 55 n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; 56 t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, 57 document,'script','https://connect.facebook.net/en_US/fbevents.js'); 58 fbq('init', '
58215594561324661
vendor: 36 bytes, lines 58-60
58'); 59 fbq('track', 'PageView'); 60
60</script>
60 61 <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=215594561324661&ev=PageView&noscript=1" /></noscript> 62 63 <!-- CAPI Helpers (Stape dedup + dataLayer bridge) --> 64
64<script> 65 function genEventId(prefix) { 66 return prefix + '_' + Date.now() + '_' + Math.random().toString(36).substr(2,9); 67 } 68 function getFbCookie(n) { 69 var m = document.cookie.match('(^|;)\\s*' + n + '\\s*=\\s*([^;]+)'); 70 return m ? m.pop() : ''; 71 } 72 window.dataLayer = window.dataLayer || []; 73 dataLayer.push({ 74 event: 'capi_init', 75 fbp: getFbCookie('_fbp'), 76 fbc: getFbCookie('_fbc'), 77 page_url: window.location.href, 78 page_referrer: document.referrer 79 }); 80 </script>
80 81 82 <!-- GA4 -->
vendor: 66 bytes, lines 82-83
82 83 <script async src="https://www.googletagmanager.com/gtag/js?id=
83G-KJMJE19M6G
vendor: 14 bytes, lines 83-84
83"></script> 84
84<script> 85
vendor: 139 bytes, lines 85-88
85window.dataLayer = window.dataLayer || []; 86 function gtag(){dataLayer.push(arguments);} 87 gtag('js', new Date()); 88 gtag('config', '
88G-KJMJE19M6G
vendor: 8 bytes, lines 88-89
88'); 89
89/* Google Ads conversion tracking handled via GTM (Kraken tags, conversion ID 16804250699). 90 AW-17634919796 removed â no conversion actions configured in that account. 91 Re-add when account has proper conversion tags set up. */ 92 </script>
92 93 94 95 <!-- Hyros (universal) â deferred to not block LCP --> 96
96<script> 97window.addEventListener('load', function() { 98 var head = document.head; 99 var script = document.createElement('script'); 100 script.type = 'text/javascript'; 101 script.src = "https://tr.goodsleepco.health/v1/lst/universal-script?ph=870f297b63c5291965577f724d5b5cb88e2f5c638b25cab9e3dc91ddcecd6f74&tag=!clicked&ref_url=" + encodeURI(document.URL) ; 102 head.appendChild(script); 103}); 104</script>
104 105 106 107 <!-- PostHog â deferred to window.load --> 108
108<script> 109 window.addEventListener('load', function() { 110 !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group identify setPersonProperties setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags resetGroups onFeatureFlags addFeatureFlagsHandler onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]); 111 posthog.init('phc_i4IITH8aa9SyDS1vFFcMt7ZWwjunMcFE9TzA6BokPkh', { 112 api_host: 'https://us.i.posthog.com', 113 defaults: '2026-01-30' 114 }); 115 }); 116 </script>
116 117 118 <!-- Klaviyo Web Tracking â deferred --> 119
119<script> 120 window.addEventListener('load', function() { 121 var s = document.createElement('script'); 122 s.type = 'text/javascript'; 123 s.src = 'https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=WscBdf'; 124 document.head.appendChild(s); 125 }); 126 </script>
126 127 128 <!-- Compiled Tailwind CSS (replaces CDN runtime â 26KB vs 300KB) --> 129 <link rel="stylesheet" href="//goodsleepco.health/cdn/shop/t/11/assets/tailwind-compiled.css?v=59973773598703081251773992497"> 130 <link rel="preconnect" href="https://fonts.googleapis.com"> 131 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 132 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"> 133 <style> 134 * { font-family: 'Inter', system-ui, sans-serif; } 135 html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; } 136 body { font-family: 'Inter', system-ui, sans-serif; margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } 137 .tracking-brand { letter-spacing: 0.2em; } 138 139 /* FAQ Accordion */ 140 .faq-answer { max-height: 0; overflow: hidden; transition: max-height 0.3s ease, padding 0.3s ease; } 141 .faq-answer.open { max-height: 500px; } 142 .faq-chevron { transition: transform 0.3s ease; } 143 .faq-chevron.open { transform: rotate(180deg); } 144 145 /* Fade-in animation */ 146 .fade-in { opacity: 0; transform: translateY(24px); transition: opacity 0.6s ease, transform 0.6s ease; } 147 .fade-in.visible { opacity: 1; transform: translateY(0); } 148 149 /* Quiz select dropdown */ 150 .quiz-select { transition: all 0.2s ease; } 151 .quiz-step { animation: fadeUp 0.4s ease; } 152 153 /* Result cards */ 154 .result-card { display: none; } 155 .result-card.active { display: block; animation: fadeUp 0.5s ease; } 156 157 @keyframes fadeUp { 158 from { opacity: 0; transform: translateY(16px); } 159 to { opacity: 1; transform: translateY(0); } 160 } 161 162 /* Sticky bar */ 163 .sticky-cta { transform: translateY(100%); transition: transform 0.3s ease; } 164 .sticky-cta.show { transform: translateY(0); } 165 166 /* Price strikethrough */ 167 .price-old { text-decoration: line-through; opacity: 0.6; } 168 169 /* Safe area for iOS notch/bottom bar */ 170 .safe-area-bottom { padding-bottom: env(safe-area-inset-bottom, 0); } 171 172 /* Bottom padding so sticky CTA doesn't overlap footer content on mobile */ 173 @media (max-width: 1023px) { 174 footer { padding-bottom: 4.5rem; } 175 } 176 177 /* Comparison table highlight */ 178 .highlight-col { background-color: #E8F0F6; } 179 180 /* Journey line */ 181 .journey-line { position: relative; } 182 .journey-line::before { 183 content: ''; 184 position: absolute; 185 top: 20px; 186 left: 0; 187 right: 0; 188 height: 2px; 189 background: linear-gradient(to right, #ECAFAC, #99BCD2, #002156); 190 } 191 192 /* Pulse animation for CTA */ 193 .pulse-soft { 194 animation: pulseSoft 2s infinite; 195 } 196 @keyframes pulseSoft { 197 0%, 100% { box-shadow: 0 0 0 0 rgba(236, 175, 172, 0.4); } 198 50% { box-shadow: 0 0 0 12px rgba(236, 175, 172, 0); } 199 } 200 201 /* Scrollbar hide for thumbnail strips */ 202 .scrollbar-hide::-webkit-scrollbar { display: none; } 203 .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } 204 205 /* Skip-to-content */ 206 .skip-link { position: absolute; top: -100%; left: 50%; transform: translateX(-50%); z-index: 100; } 207 .skip-link:focus { top: 0.5rem; } 208 209 /* Focus-visible for keyboard users */ 210 :focus-visible { outline: 2px solid #ECAFAC; outline-offset: 2px; } 211 button:focus:not(:focus-visible), a:focus:not(:focus-visible) { outline: none; } 212 </style>
212<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
212<meta name="google-site-verification" content="ETV9ghkhb6XK185UpHnL0Au1_x3pQ1Y_ggHn-iG5VAg"> 213<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/59824177291/digital_wallets/dialog"> 214<link rel="ucp" href="/.well-known/ucp" version="2026-08-25">
214<script async="async" src="/checkouts/internal/preloads.js?locale=en-AU"></script>
214 215<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
216<script async="async" src="https://shop.app/checkouts/internal/preloads.js?locale=en-AU&shop_id=59824177291" crossorigin="anonymous"></script>
vendor: 1 bytes, line 216
216
217<script id="apple-pay-shop-capabilities" type="application/json">{"shopId":59824177291,"countryCode":"AU","currencyCode":"AUD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/59824177291","merchantName":"Good Sleep Co","requiredBillingContactFields":["postalAddress","email","phone"],"requiredShippingContactFields":["postalAddress","email","phone"],"shippingType":"shipping","supportedNetworks":["visa","masterCard","amex","jcb"],"total":{"type":"pending","label":"Good Sleep Co","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script>
vendor: 1 bytes, line 217
217
218<script id="shopify-features" type="application/json">{"accessToken":"ded888b8287375f7beb665757cf73295","betas":["rich-media-storefront-analytics"],"domain":"goodsleepco.health","predictiveSearch":true,"shopId":59824177291,"locale":"en"}</script>
vendor: 1 bytes, line 218
218
219<script>var Shopify = Shopify || {}; 220Shopify.shop = "good-sleep-co-gc.myshopify.com"; 221Shopify.locale = "en"; 222Shopify.currency = {"active":"AUD","rate":"1.0"}; 223Shopify.country = "AU"; 224Shopify.theme = {"name":"Gateway Home Page","id":140639207563,"schema_name":"Motion","schema_version":"8.5.1","theme_store_id":null,"role":"main"}; 225Shopify.theme.handle = "null"; 226Shopify.theme.style = {"id":null,"handle":null}; 227Shopify.cdnHost = "goodsleepco.health/cdn"; 228Shopify.routes = Shopify.routes || {}; 229Shopify.routes.root = "/"; 230Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 231Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 232Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 233Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 233
233
234<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 234
234
235<script>!function(o){function n(){var o=[];function n(){o.push(Array.prototype.slice.apply(arguments))}return n.q=o,n}var t=o.Shopify=o.Shopify||{};t.loadFeatures=n(),t.autoloadFeatures=n()}(window);</script>
vendor: 1 bytes, line 235
235
236<script> 237 window.ShopifyPay = window.ShopifyPay || {}; 238 window.ShopifyPay.apiHost = "shop.app\/pay"; 239 window.ShopifyPay.redirectState = null; 240</script>
vendor: 1 bytes, line 240
240
241<script> 242 window.Shopify = window.Shopify || {}; 243 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 244 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 245 window.Shopify.SignInWithShop.eligible = true; 246</script>
vendor: 1 bytes, line 246
246
247<script id="shop-js-analytics" type="application/json">{"pageType":"index"}</script>
vendor: 1 bytes, line 247
247
248<script defer="defer" async type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"></script>
vendor: 1 bytes, line 248
248
249<script type="module"> 250 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 251 252 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 253 254</script>
vendor: 1 bytes, line 254
254
255<script> 256 window.Shopify = window.Shopify || {}; 257 if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; 258 window.Shopify.featureAssets['shop-js'] = {"avatar":["modules/v2/loader.avatar.en.esm.js"],"checkout-modal":["modules/v2/loader.checkout-modal.en.esm.js"],"init-customer-accounts-sign-up":["modules/v2/loader.init-customer-accounts-sign-up.en.esm.js"],"init-customer-accounts":["modules/v2/loader.init-customer-accounts.en.esm.js"],"init-fed-cm":["modules/v2/loader.init-fed-cm.en.esm.js"],"init-shop-cart-sync":["modules/v2/loader.init-shop-cart-sync.en.esm.js"],"init-shop-email-lookup-coordinator":["modules/v2/loader.init-shop-email-lookup-coordinator.en.esm.js"],"init-shop-for-new-customer-accounts":["modules/v2/loader.init-shop-for-new-customer-accounts.en.esm.js"],"init-shop-user-recognition":["modules/v2/loader.init-shop-user-recognition.en.esm.js"],"init-windoid":["modules/v2/loader.init-windoid.en.esm.js"],"lead-capture":["modules/v2/loader.lead-capture.en.esm.js"],"listener":["modules/v2/loader.listener.en.esm.js"],"pay-button":["modules/v2/loader.pay-button.en.esm.js"],"payment-terms":["modules/v2/loader.payment-terms.en.esm.js"],"shop-button":["modules/v2/loader.shop-button.en.esm.js"],"shop-cart-sync":["modules/v2/loader.shop-cart-sync.en.esm.js"],"shop-cash-offers":["modules/v2/loader.shop-cash-offers.en.esm.js"],"shop-follow-button":["modules/v2/loader.shop-follow-button.en.esm.js"],"shop-login-button":["modules/v2/loader.shop-login-button.en.esm.js"],"shop-login":["modules/v2/loader.shop-login.en.esm.js"],"shop-toast-manager":["modules/v2/loader.shop-toast-manager.en.esm.js"],"shop-user-recognition":["modules/v2/loader.shop-user-recognition.en.esm.js"]}; 259</script>
vendor: 1 bytes, line 259
259
260<script>(function() { 261 var isLoaded = false; 262 function asyncLoad() { 263 if (isLoaded) return; 264 isLoaded = true; 265 var urls = ["https:\/\/cdn.rebuyengine.com\/onsite\/js\/rebuy.js?shop=good-sleep-co-gc.myshopify.com"]; 266 for (var i = 0; i < urls.length; i++) { 267 var s = document.createElement('script'); 268 s.type = 'text/javascript'; 269 s.async = true; 270 s.src = urls[i]; 271 var x = document.getElementsByTagName('script')[0]; 272 x.parentNode.insertBefore(s, x); 273 } 274 }; 275 if(window.attachEvent) { 276 window.attachEvent('onload', asyncLoad); 277 } else { 278 window.addEventListener('load', asyncLoad, false); 279 } 280})();</script>
vendor: 1 bytes, line 280
280
281<script id="__st">var __st={"a":59824177291,"offset":36000,"reqid":"f8e2928d-53ec-4f15-9a11-e9c22d486ff5-1790841144","pageurl":"goodsleepco.health\/","u":"d88afbdcafee","p":"home"};</script>
vendor: 1 bytes, line 281
281
282<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 282
282
283<script id="captcha-bootstrap">!function(){'use strict';const t='contact',e='account',n='new_comment',o=[[t,t],['blogs',n],['comments',n],[t,'customer']],c=[[e,'customer_login'],[e,'guest_login'],[e,'recover_customer_password'],[e,'create_customer']],r=t=>t.map((([t,e])=>`form[action*='/${t}']:not([data-nocaptcha='true']) input[name='form_type'][value='${e}']`)).join(','),a=t=>()=>t?[...document.querySelectorAll(t)].map((t=>t.form)):[];function s(){const t=[...o],e=r(t);return a(e)}const i='password',u='form_key',d=['recaptcha-v3-token','g-recaptcha-response','h-captcha-response',i],f=()=>{try{return window.sessionStorage}catch{return}},m='__shopify_v',_=t=>t.elements[u];function p(t,e,n=!1){try{const o=window.sessionStorage,c=JSON.parse(o.getItem(e)),{data:r}=function(t){const{data:e,action:n}=t;return t[m]||n?{data:e,action:n}:{data:t,action:n}}(c);for(const[e,n]of Object.entries(r))t.elements[e]&&(t.elements[e].value=n);n&&o.removeItem(e)}catch(o){console.error('form repopulation failed',{error:o})}}const l='form_type',E='cptcha';function T(t){t.dataset[E]=!0}const w=window,h=w.document,L='Shopify',v='ce_forms',y='captcha';let A=!1;((t,e)=>{const n=(g='f06e6c50-85a8-45c8-87d0-21a2b65856fe',I='https://cdn.shopify.com/shopifycloud/storefront-forms-hcaptcha/ce_storefront_forms_captcha_hcaptcha.v1.5.3.iife.js',D={infoText:'Protected by hCaptcha',privacyText:'Privacy',termsText:'Terms'},(t,e,n)=>{const o=w[L][v],c=o.bindForm;if(c)return c(t,g,e,D).then(n);var r;o.q.push([[t,g,e,D],n]),r=I,A||(h.body.append(Object.assign(h.createElement('script'),{id:'captcha-provider',async:!0,src:r})),A=!0)});var g,I,D;w[L]=w[L]||{},w[L][v]=w[L][v]||{},w[L][v].q=[],w[L][y]=w[L][y]||{},w[L][y].protect=function(t,e){n(t,void 0,e),T(t)},Object.freeze(w[L][y]),function(t,e,n,w,h,L){const[v,y,A,g]=function(t,e,n){const i=e?o:[],u=t?c:[],d=[...i,...u],f=r(d),m=r(i),_=r(d.filter((([t,e])=>n.includes(e))));return[a(f),a(m),a(_),s()]}(w,h,L),I=t=>{const e=t.target;return e instanceof HTMLFormElement?e:e&&e.form},D=t=>v().includes(t);t.addEventListener('submit',(t=>{const e=I(t);if(!e)return;const n=D(e)&&!e.dataset.hcaptchaBound&&!e.dataset.recaptchaBound,o=_(e),c=g().includes(e)&&(!o||!o.value);(n||c)&&t.preventDefault(),c&&!n&&(function(t){try{if(!f())return;!function(t){const e=f();if(!e)return;const n=_(t);if(!n)return;const o=n.value;o&&e.removeItem(o)}(t);const e=Array.from(Array(32),(()=>Math.random().toString(36)[2])).join('');!function(t,e){_(t)||t.append(Object.assign(document.createElement('input'),{type:'hidden',name:u})),t.elements[u].value=e}(t,e),function(t,e){const n=f();if(!n)return;const o=[...t.querySelectorAll(`input[type='${i}']`)].map((({name:t})=>t)),c=[...d,...o],r={};for(const[a,s]of new FormData(t).entries())c.includes(a)||(r[a]=s);n.setItem(e,JSON.stringify({[m]:1,action:t.action,data:r}))}(t,e)}catch(e){console.error('failed to persist form',e)}}(e),e.submit())}));const S=(t,e)=>{t&&!t.dataset[E]&&(n(t,e.some((e=>e===t))),T(t))};for(const o of['focusin','change'])t.addEventListener(o,(t=>{const e=I(t);D(e)&&S(e,y())}));const B=e.get('form_key'),M=e.get(l),P=B&&M;t.addEventListener('DOMContentLoaded',(()=>{const t=y();if(P)for(const e of t)e.elements[l].value===M&&p(e,B);[...new Set([...A(),...v().filter((t=>'true'===t.dataset.shopifyCaptcha))])].forEach((e=>S(e,t)))}))}(h,new URLSearchParams(w.location.search),n,t,e,['guest_login'])})(!0,!0)}();</script>
vendor: 1 bytes, line 283
283
284<script integrity="sha256-JjoPp5ZfB1sSAs5SQaol1x1GgvveM+BgmRzyDexInEQ=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//goodsleepco.health/cdn/shopifycloud/storefront/assets/storefront/load_feature-1bd60354.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 284
284
285<script>(function () {var userAgent = navigator.userAgent;var platform = navigator.platform;var maxTouchPoints = navigator.maxTouchPoints || 0;var isIOS = /iPad|iPhone|iPod/.test(platform) || (platform === 'MacIntel' && maxTouchPoints > 1);var isMacSafari = platform.indexOf('Mac') === 0 && /Safari/.test(userAgent) && !/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Android/.test(userAgent);var isAppleSafari = isIOS || isMacSafari;if (isAppleSafari) {fetch('/sf_private_access_tokens' + location.search).catch(function () {});}function browserMajorVersion(pattern) {var match = userAgent.match(pattern);return match ? parseInt(match[1], 10) : null;}function shouldLoadAutosizesPolyfill() {if (!window.PerformanceObserver?.supportedEntryTypes?.includes('paint')) {return false;}var chromeVersion = browserMajorVersion(/Chrome\/(\d+)/);if (chromeVersion !== null) {return chromeVersion < 126;}var firefoxVersion = browserMajorVersion(/Firefox\/(\d+)/);if (firefoxVersion !== null) {return firefoxVersion < 150;}var safariVersion = isAppleSafari ? browserMajorVersion(/Version\/(\d+).*Safari\//) : null;if (safariVersion !== null) {return safariVersion < 27;}return true;}if (shouldLoadAutosizesPolyfill()) {var autosizesScript = document.createElement('script');autosizesScript.async = true;autosizesScript.crossOrigin = 'anonymous';autosizesScript.src = "//goodsleepco.health/cdn/shopifycloud/storefront/assets/storefront/autosizes-84416378.js";(document.head || document.documentElement).appendChild(autosizesScript);}window.ShopifyAnalytics = window.ShopifyAnalytics || {};window.ShopifyAnalytics.performance = window.ShopifyAnalytics.performance || {};(function () {var LONG_FRAME_THRESHOLD = 50;var longAnimationFrames = [];var activeRafId = null;function collectLongFrames() {var previousTime = null;function rafMonitor(now) {if (activeRafId === null) {return;}var delta = now - previousTime;if (delta > LONG_FRAME_THRESHOLD) {longAnimationFrames.push({startTime: previousTime,endTime: now,});}previousTime = now;activeRafId = requestAnimationFrame(rafMonitor);}previousTime = performance.now();activeRafId = requestAnimationFrame(rafMonitor);}if (!window.PerformanceObserver?.supportedEntryTypes?.includes('long-animation-frame')) {collectLongFrames();var timeoutId = setTimeout(function () {cancelAnimationFrame(activeRafId);}, 10000);window.ShopifyAnalytics.performance.getLongAnimationFrames = function (stopCollection) {if (stopCollection === undefined) {stopCollection = false;}if (stopCollection) {clearTimeout(timeoutId);cancelAnimationFrame(activeRafId);}return longAnimationFrames;};}})();})();</script>
285<script crossorigin="anonymous" defer="defer" src="//goodsleepco.health/cdn/shopifycloud/storefront/assets/shopify_pay/storefront-616277c7.js?v=20250812"></script>
vendor: 1 bytes, line 285
285
286<script id="shopify-origin-trials" async="async" integrity="sha256-qJbe/jEZBHtr5W/BlA2cKAz3vkXu6vJQyLjgvgCC86g=" src="//cdn.shopify.com/shopifycloud/storefront/assets/storefront/origin_trials-318ab40a.js" crossorigin="anonymous" onload="window.__shopifyOriginTrialsDone = true" onerror="window.__shopifyOriginTrialsDone = true"></script>
vendor: 1 bytes, line 286
286
287<script> 288 window.Shopify = window.Shopify || {}; 289 window.Shopify.MCP = window.Shopify.MCP || {}; 290 window.Shopify.MCP.enabled = true; 291 window.Shopify.MCP.shop = "good-sleep-co-gc.myshopify.com"; 292 window.Shopify.MCP.mcpEndpoint = "https:\/\/goodsleepco.health\/api\/mcp"; 293 window.Shopify.MCP.tools = [{"name":"search_shop_policies_and_faqs","description":"Used to get facts about the stores policies, products, or services.\nSome examples of questions you can ask are:\n - What is your return policy?\n - What is your shipping policy?\n - What is your phone number?\n - What are your hours of operation?\"\n","inputSchema":{"$schema":"https:\/\/json-schema.org\/draft\/2020-12\/schema","type":"object","properties":{"query":{"type":"string","description":"A natural language query."},"context":{"type":"string","description":"Additional information about the request such as user demographics, mood, location, or other relevant details that could help in tailoring the response appropriately."}},"required":["query"]}}]; 294</script>
vendor: 1 bytes, line 294
294
295<script>(()=>{var d="shopify:webmcp_adapter_loaded",n=Symbol.for("shopify.webmcp_adapter_loading");function s(c,a,{win:r=window,doc:o=document}={}){function p(){try{return r.localStorage.getItem(d)==="true"}catch{return!1}}function l(){try{r.localStorage.setItem(d,"true")}catch{}}function u(){return typeof(o.modelContext||r.navigator?.modelContext)?.registerTool=="function"}function f(){if(r[n]||!u())return;let t=o.head||o.getElementsByTagName("head")[0];if(!t)return;let e=o.createElement("script");e.type="module",e.crossOrigin="anonymous",a&&(e.integrity=a),e.src=c,e.addEventListener("load",l,{once:!0}),e.addEventListener("error",()=>{r[n]=!1},{once:!0}),t.appendChild(e),r[n]=!0}function _(t){let e=o.getElementById("shopify-origin-trials");if(!e||r.__shopifyOriginTrialsDone){t();return}e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}function i(){_(()=>r.setTimeout(f,0))}function m(){o.addEventListener("DOMContentLoaded",i,{once:!0})}p()?i():m()}s("\/\/goodsleepco.health\/cdn\/shopifycloud\/storefront\/assets\/storefront\/webmcp-c6b62ece.js","sha256-ke4DDuBjdvea3vxLWxHc9E9nq8zihuG4IfYEGbb77ys=");})(); 296</script>
vendor: 1 bytes, line 296
296
297<script data-source-attribution="shopify.dynamic_checkout.dynamic.init">var Shopify=Shopify||{};Shopify.PaymentButton=Shopify.PaymentButton||{isStorefrontPortableWallets:!0,init:function(){window.Shopify.PaymentButton.init=function(){};var t=document.createElement("script");t.src="https://goodsleepco.health/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}}; 298</script>
vendor: 1 bytes, line 298
298
299<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 300 function portableWalletsHideBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.add("hidden"),t.setAttribute("aria-hidden","true"),n.removeEventListener("click",e))}function portableWalletsShowBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.remove("hidden"),t.removeAttribute("aria-hidden"),n.addEventListener("click",e))}window.Shopify?.PaymentButton&&(window.Shopify.PaymentButton.hideBuyerConsent=portableWalletsHideBuyerConsent,window.Shopify.PaymentButton.showBuyerConsent=portableWalletsShowBuyerConsent); 301</script>
vendor: 1 bytes, line 301
301
302<script data-source-attribution="shopify.dynamic_checkout.cart.bootstrap">document.addEventListener("DOMContentLoaded",(function(){function t(){return document.querySelector("shopify-accelerated-checkout-cart, shopify-accelerated-checkout")}if(t())Shopify.PaymentButton.init();else{new MutationObserver((function(e,n){t()&&(Shopify.PaymentButton.init(),n.disconnect())})).observe(document.body,{childList:!0,subtree:!0})}})); 303</script>
303 304<link id="shopify-accelerated-checkout-styles" rel="stylesheet" media="screen" href="https://goodsleepco.health/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous"> 305<style id="shopify-accelerated-checkout-cart"> 306 #shopify-buyer-consent { 307 margin-top: 1em; 308 display: inline-block; 309 width: 100%; 310} 311 312#shopify-buyer-consent.hidden { 313 display: none; 314} 315 316#shopify-subscription-policy-button { 317 background: none; 318 border: none; 319 padding: 0; 320 text-decoration: underline; 321 font-size: inherit; 322 cursor: pointer; 323} 324 325#shopify-subscription-policy-button::before { 326 box-shadow: none; 327} 328 329 </style> 330
331<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
331 332
332<script> 333 /* Session UTM capture: any entry page stores UTMs so lead forms (e.g. treatment) keep attribution after navigation */ 334 (function () { 335 try { 336 var p = new URLSearchParams(window.location.search); 337 var ks = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; 338 var out = {}, found = false; 339 ks.forEach(function (k) { var v = p.get(k); if (v) { out[k] = v; found = true; } }); 340 if (found) sessionStorage.setItem('gsc_utms', JSON.stringify(out)); 341 } catch (e) {} 342 })(); 343 </script>
343 344<!-- BEGIN app block: shopify://apps/essential-a-b-testing/blocks/ab-testing/0154ac6b-7b9c-4958-8219-ed5b06e6d463 -->
344<script type="text/javascript"> 345 var eaABtEmbdScrV=(function(){"use strict";var P=Object.defineProperty;var E=(c,a,l)=>a in c?P(c,a,{enumerable:!0,configurable:!0,writable:!0,value:l}):c[a]=l;var h=(c,a,l)=>E(c,typeof a!="symbol"?a+"":a,l);class c{constructor(){h(this,"selectors",["#PBarNextFrameWrapper","#preview-bar-iframe"]);h(this,"keepLookingForMs",1e4)}hide(){return Promise.all(this.selectors.map(e=>this.waitAndHideElement(e)))}waitAndHideElement(e){return new Promise(t=>{let s=0;const i=u=>{u.dataset.eaAbPbHidden!=="1"&&(u.dataset.eaAbPbHidden="1",u.style.display="none")},n=document.querySelector(e);if(n){i(n),t(!0);return}const o=new MutationObserver(()=>{const u=document.querySelector(e);u&&(i(u),window.clearTimeout(s),o.disconnect(),t(!0))});o.observe(document.documentElement,{childList:!0,subtree:!0}),s=window.setTimeout(()=>{o.disconnect(),t(!1)},this.keepLookingForMs)})}}const a=/\b(googlebot|adsbot-google|google-adsbot|mediapartners-google|google-inspectiontool|googleother|storebot-google|google-read-aloud|googleweblight|googlepage|google-adwords(?:-[a-z0-9-]+)?|bingbot|slurp|duckduckbot|baiduspider|yandex(?:bot|images)|sogou|exabot|applebot|petalbot|ahrefsbot|semrushbot|mj12bot|dotbot|seznambot|rogerbot|linkdexbot|facebookexternalhit|facebot|linkedinbot|twitterbot|pinterest|redditbot|discordbot|slackbot|whatsapp|telegrambot|embedly|quora-link-preview|outbrain|nuzzel|flipboardproxy|vkshare)\b/i;class l{static shouldProcessRequest(e){return!(this.isBot()||!this.canPersist()||this.isInDesignMode(e)||this.isAppPreview())}static isBot(){return a.test(navigator.userAgent)}static canPersist(){try{const e="__essential-ab-testing-persistance__";return localStorage.setItem(e,"1"),localStorage.removeItem(e),!0}catch{return!1}}static isInDesignMode(e){return e.request.designMode}static isAppPreview(){return new URLSearchParams(window.location.search).get("eaPreview")==="true"}}var d=(r=>(r.TEMPLATE="template",r.THEME="theme",r))(d||{});class f{static themeGid(e){return`gid://shopify/OnlineStoreTheme/${e}`}static themeId(e){return e.replace("gid://shopify/OnlineStoreTheme/","")}}class m{static handle(e,t,s){switch(e.type){case d.TEMPLATE:this.handleTemplate(e,t,s);return;case d.THEME:this.handleTheme(e,t);return}}static handleTemplate(e,t,s){if(t!=="a"&&t!=="b")return;const n=e.params[t];if(n.name!==s.template.name||n.suffix===s.template.suffix)return;const o=new URL(window.location.href);o.searchParams.set("view",n.suffix??"__DEFAULT"),window.location.replace(o.toString())}static handleTheme(e,t){if(t!=="a"&&t!=="b")return;const i=e.params[t];if(i===f.themeGid(Shopify.theme.id))return;const n=f.themeId(i),o=new URL(window.location.href);o.searchParams.set("preview_theme_id",n),window.location.replace(o.toString())}}class p{constructor(e){h(this,"tests");this.tests=e}find(e){return this.tests.find(t=>{switch(t.type){case d.TEMPLATE:return this.testMatchesTemplate(t.params,e);case d.THEME:return this.testMatchesTheme(t.params)}return!1})}testMatchesTemplate(e,t){return e.themeId!==f.themeGid(Shopify.theme.id)?!1:e.a.name===t.template.name&&e.a.suffix===t.template.suffix||e.b.name===t.template.name&&e.b.suffix===t.template.suffix}testMatchesTheme(e){const t=f.themeGid(Shopify.theme.id);return e.a===t||e.b===t}}class g{static pick(e){return Math.random()<=e.aPercentage/100?"a":"b"}}class b{static generate(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():typeof crypto<"u"&&crypto.getRandomValues?"10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(+e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>+e/4).toString(16)):"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}}class x{constructor(e){h(this,"key");this.key=`essential-ab-testing-${e}`}get(){const e=localStorage.getItem(this.key);if(e)try{return JSON.parse(e)}catch{}}getOrMake(){const e=this.get();return e||{id:b.generate(),createdAt:new Date,tests:[]}}getTestVariant(e){const t=this.get();if(!t)return;const i=(t.tests??[]).find(n=>n.id==e);return i?i.variant:void 0}setTestVariant(e,t){const s=this.getOrMake();s.tests.push({id:e,variant:t,createdAt:new Date}),localStorage.setItem(this.key,JSON.stringify(s))}onlyKeepTests(e){const t=this.get();if(!t||t.tests.length==0)return;const s=t.tests.filter(i=>e.includes(i.id));s.length!=t.tests.length&&(t.tests=s,localStorage.setItem(this.key,JSON.stringify(t)))}}const w=50,y=200;function T(r){if(typeof Shopify<"u"&&Shopify.theme){r();return}let e=0;const t=setInterval(()=>{e++,typeof Shopify<"u"&&Shopify.theme?(clearInterval(t),r()):e>=y&&clearInterval(t)},w)}function S(r,e){if(!l.shouldProcessRequest(r))return;new c().hide();const t=new x(r.shopId);t.onlyKeepTests(e.map(o=>o.id));const i=new p(e).find(r);if(!i)return;let n=t.getTestVariant(i.id);n||(n=g.pick(i),t.setTestVariant(i.id,n)),m.handle(i,n,r)}function v(r,e){T(()=>S(r,e))}return v})(); 346 347 eaABtEmbdScrV( 348 { 349 shopId: 59824177291, 350 request: { 351 designMode: false, 352 visualPreviewMode: false, 353 }, 354 template: { 355 directory: null, 356 name: "index", 357 suffix: null, 358 } 359 }, 360 JSON.parse('[]') 361 ); 362</script>
362<!-- END app block --><!-- BEGIN app block: shopify://apps/klaviyo-email-marketing-sms/blocks/klaviyo-onsite-embed/2632fe16-c075-4321-a88b-50b567f42507 --> 363 364 365 366 367 368 369 370 371 372 373 374 375
375<script async src="https://static.klaviyo.com/onsite/js/WscBdf/klaviyo.js?company_id=WscBdf"></script>
375 376
376<script>!function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}();</script>
376 377 378 379 380 381 382 383
383<script> 384 window.klaviyoReviewsProductDesignMode = false 385 </script>
385 386 387 388 389 390 391 392 393 394 395<!-- END app block --><!-- BEGIN app block: shopify://apps/geolocation-flow/blocks/auto-redirects/99c42a40-4a88-4244-a03e-a752a0b4e07d -->
395<script src="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/xgeo-countries-data.js"></script>
395<script type="application/json" data-xgeo-auto-config> 396 { 397 "settings": {"autoRedirectOnce":false,"autoRedirectOnceType":"session","disableUrlParam":false,"forward_url_params":true,"domain_redirection":false,"botDetectionPatterns":"bot|adsbot|googlebot|crawler|spider|robot|crawling|slurp","allowedPages":["all"],"redirectOnPagesMode":"trigger","autoRedirectDelay":0,"utm_source":"","utm_medium":"","utm_campaign":""}, 398 "shopifyTemplate": "index", 399 "shopifyTemplateDir": "", 400 "planName": "Pro plan", 401 "isDevPlan": false, 402 403 "autoRedirects": [{"id":"gid:\/\/shopify\/Metafield\/34906479493259","key":"mmcluumm","location":["US","CA"],"except_r":false,"block":false,"url":"https:\/\/goodsleepco.com\/","domain_redirection":true,"status":true,"order":1,"redirectOnPagesMode":"trigger","allowedPages":["all"]}], 404 "customCodeString": "" 405 } 406 </script>
406<script src="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/auto-redirects.min.js"></script>
406<!-- BEGIN app snippet: geo-simulator -->
406<script> 407(function(){ 408 var u=location.search,c=document.cookie,k='xgeo-sim-active'; 409 if(u.includes('xgeo-sim=1')){document.cookie=k+'=1;path=/;max-age=86400';} 410 if(u.includes('xgeo-sim=1')||c.includes(k+'=')){ 411 var s=document.createElement('script'); 412 s.src="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/geo-simulator.min.js"; 413 s.dataset.logo="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/main-logo.svg"; 414 document.head.appendChild(s); 415 } 416})(); 417</script>
417 418<!-- END app snippet --> 419<!-- END app block --><!-- BEGIN app block: shopify://apps/triplewhale/blocks/triple_pixel_snippet/483d496b-3f1a-4609-aea7-8eee3b6b7a2a --><link rel='preconnect dns-prefetch' href='https://api.config-security.com/' crossorigin /> 420<link rel='preconnect dns-prefetch' href='https://conf.config-security.com/' crossorigin />
421<script> 422/* >> TriplePixel :: start*/ 423window.TriplePixelData={TripleName:"good-sleep-co-gc.myshopify.com",ver:"2.16",plat:"SHOPIFY",isHeadless:false,src:'SHOPIFY_EXT',product:{id:"",name:``,price:"",variant:"",av:{ }},search:"",collection:"",cart:"drawer",template:"index",curr:"AUD" || "AUD", market:"28434563211"},function(W,H,A,L,E,_,B,N){function O(U,T,P,H,R){void 0===R&&(R=!1),H=new XMLHttpRequest,P?(H.open("POST",U,!0),H.setRequestHeader("Content-Type","text/plain")):H.open("GET",U,!0),H.send(JSON.stringify(P||{})),H.onreadystatechange=function(){4===H.readyState&&200===H.status?(R=H.responseText,U.includes("/first")?eval(R):P||(N[B]=R)):(299<H.status||H.status<200)&&T&&!R&&(R=!0,O(U,T-1,P))}}if(N=window,!N[H+"sn"]){N[H+"sn"]=1,L=function(){return Date.now().toString(36)+"_"+Math.random().toString(36)};try{A.setItem(H,1+(0|A.getItem(H)||0)),(E=JSON.parse(A.getItem(H+"U")||"[]")).push({u:location.href,r:document.referrer,t:Date.now(),id:L()}),A.setItem(H+"U",JSON.stringify(E))}catch(e){}var i,m,p;A.getItem('"!nC`')||(_=A,A=N,A[H]||(E=A[H]=function(t,e,i){return void 0===i&&(i=[]),"State"==t?E.s:(W=L(),(E._q=E._q||[]).push([W,t,e].concat(i)),W)},E.s="Installed",E._q=[],E.ch=W,B="configSecurityConfModel",N[B]=1,O("https://conf.config-security.com/model",5),i=L(),m=A[atob("c2NyZWVu")],_.setItem("di_pmt_wt",i),p={id:i,action:"profile",avatar:_.getItem("auth-security_rand_salt_"),time:m[atob("d2lkdGg=")]+":"+m[atob("aGVpZ2h0")],host:A.TriplePixelData.TripleName,plat:A.TriplePixelData.plat,url:window.location.href.slice(0,500),ref:document.referrer,ver:A.TriplePixelData.ver},O("https://api.config-security.com/event",5,p),O("https://api.config-security.com/first?host=".concat(p.host,"&plat=").concat(p.plat),5)))}}("","TriplePixel",localStorage); 424/* << TriplePixel :: end*/ 425</script>
425 426 427 428 429<!-- END app block --><!-- BEGIN app block: shopify://apps/eg-auto-add-to-cart/blocks/app-embed/0f7d4f74-1e89-4820-aec4-6564d7e535d2 --> 430 431 432 433 434 435 436 437 438 439 440 441 442
442<script 443 async 444 type="text/javascript" 445 src="https://cdn.506.io/eg/script.js?shop=good-sleep-co-gc.myshopify.com&v=12" 446 ></script>
446 447 448 449 450 451 <meta id="easygift-shop" itemid="c2hvcF8kXzE3OTA4NDExNDQ=" content="{"isInstalled":true,"installedOn":"2025-10-07T06:33:21.498Z","appVersion":"3.0","subscriptionName":"Standard","cartAnalytics":true,"freeTrialEndsOn":null,"settings":{"reminderBannerStyle":{"position":{"horizontal":"right","vertical":"bottom"},"closingMode":"doNotAutoClose","cssStyles":"","displayAfter":5,"headerText":"","imageUrl":null,"primaryColor":"#000000","reshowBannerAfter":"everyNewSession","selfcloseAfter":5,"showImage":false,"subHeaderText":""},"addedItemIdentifier":"_Gifted","ignoreOtherAppLineItems":null,"customVariantsInfoLifetimeMins":1440,"redirectPath":null,"ignoreNonStandardCartRequests":false,"bannerStyle":{"position":{"horizontal":"right","vertical":"bottom"},"cssStyles":null,"primaryColor":"#000000"},"themePresetId":null,"notificationStyle":{"position":{"horizontal":null,"vertical":null},"cssStyles":null,"duration":null,"hasCustomizations":false,"primaryColor":null},"fetchCartData":false,"useLocalStorage":{"enabled":false,"expiryMinutes":null},"popupStyle":{"addButtonText":null,"cssStyles":null,"dismissButtonText":null,"hasCustomizations":false,"imageUrl":null,"outOfStockButtonText":null,"primaryColor":null,"secondaryColor":null,"showProductLink":false,"subscriptionLabel":null},"refreshAfterBannerClick":false,"disableReapplyRules":false,"disableReloadOnFailedAddition":false,"autoReloadCartPage":false,"ajaxRedirectPath":null,"allowSimultaneousRequests":false,"applyRulesOnCheckout":false,"enableCartCtrlOverrides":true,"scriptSettings":{"branding":{"removalRequestSent":null,"show":false},"productPageRedirection":{"enabled":false,"products":[],"redirectionURL":"\/"},"debugging":{"enabled":false,"enabledOn":null,"stringifyObj":false},"hideGiftedPropertyText":false,"fetchCartDataBeforeRequest":false,"customCSS":null,"decodePayload":false,"delayUpdates":2000,"enableBuyNowInterceptions":false,"fetchProductInfoFromSavedDomain":false,"hideAlertsOnFrontend":false,"removeEGPropertyFromSplitActionLineItems":false,"removeProductsAddedFromExpiredRules":false,"useFinalPrice":true}},"translations":null,"defaultLocale":"en","shopDomain":"goodsleepco.health"}"> 452 453
454<script defer> 455 (async function() { 456 try { 457 458 const blockVersion = "v3" 459 if (blockVersion != "v3") { 460 return 461 } 462 463 let metaErrorFlag = false; 464 if (metaErrorFlag) { 465 return 466 } 467 468 // Parse metafields as JSON 469 const metafields = {"easygift-rule-68e4b71485c315935a7a62fa":{"schedule":{"enabled":false,"starts":null,"ends":null},"trigger":{"productTags":{"targets":[],"collectionInfo":null,"sellingPlan":null},"type":"productsInclude","minCartValue":null,"hasUpperCartValue":false,"upperCartValue":null,"products":[{"name":"Good Sleep Test - Default Title","variantId":41438208163979,"variantGid":"gid:\/\/shopify\/ProductVariant\/41438208163979","productGid":"gid:\/\/shopify\/Product\/7135719981195","handle":"good-sleep-test","sellingPlans":[],"alerts":[],"_id":"68e4b7ac65068856f3ac3ab7"}],"collections":[],"condition":"quantity","conditionMin":1,"conditionMax":null,"collectionSellingPlanType":null},"action":{"notification":{"enabled":false,"headerText":null,"subHeaderText":null,"showImage":false,"imageUrl":""},"discount":{"issue":null,"type":"app","discountType":"percentage","title":"Ebook Free","createdByEasyGift":true,"easygiftAppDiscount":true,"value":100,"id":"gid:\/\/shopify\/DiscountAutomaticNode\/1536712671371"},"popupOptions":{"showVariantsSeparately":false,"headline":null,"subHeadline":null,"showItemsPrice":false,"popupDismissable":false,"imageUrl":null,"persistPopup":false,"rewardQuantity":1,"showDiscountedPrice":false,"hideOOSItems":false},"banner":{"enabled":false,"headerText":null,"subHeaderText":null,"showImage":false,"imageUrl":null,"displayAfter":"5","closingMode":"doNotAutoClose","selfcloseAfter":"5","reshowBannerAfter":"everyNewSession","redirectLink":null},"type":"addAutomatically","products":[{"name":"Ebook - Sleep, snoring and sleep disorders - Default Title","variantId":"44338407899275","variantGid":"gid:\/\/shopify\/ProductVariant\/44338407899275","productGid":"gid:\/\/shopify\/Product\/7934261297291","quantity":1,"handle":"ebook-sleep-snoring-and-sleep-disorders","price":"0.00"}],"limit":1,"preventProductRemoval":false,"addAvailableProducts":false},"targeting":{"link":{"destination":null,"data":null,"cookieLifetime":14},"additionalCriteria":{"geo":{"include":[],"exclude":[]},"type":null,"customerTags":[],"customerTagsExcluded":[],"customerId":[],"orderCount":null,"hasOrderCountMax":false,"orderCountMax":null,"totalSpent":null,"hasTotalSpentMax":false,"totalSpentMax":null},"type":"all"},"settings":{"worksInReverse":true,"runsOncePerSession":false,"preventAddedItemPurchase":true,"showReminderBanner":false},"_id":"68e4b71485c315935a7a62fa","name":"Ebook","store":"68e4b42e97137fb6fb552788","shop":"good-sleep-co-gc","active":true,"translations":null,"createdAt":"2025-10-07T06:45:40.675Z","updatedAt":"2025-11-10T16:38:19.921Z","__v":0}}; 470 471 // Process metafields in JavaScript 472 let savedRulesArray = []; 473 for (const [key, value] of Object.entries(metafields)) { 474 if (value) { 475 for (const prop in value) { 476 // avoiding Object.Keys for performance gain -- no need to make an array of keys. 477 savedRulesArray.push(value); 478 break; 479 } 480 } 481 } 482 483 const metaTag = document.createElement('meta'); 484 metaTag.id = 'easygift-rules'; 485 metaTag.content = JSON.stringify(savedRulesArray); 486 metaTag.setAttribute('itemid', 'cnVsZXNfJF8xNzkwODQxMTQ0'); 487 488 document.head.appendChild(metaTag); 489 } catch (err) { 490 491 } 492 })(); 493</script>
493 494 495 496
496<script 497 type="text/javascript" 498 defer 499 > 500 501 (function () { 502 try { 503 window.EG_INFO = window.EG_INFO || {}; 504 var shopInfo = {"isInstalled":true,"installedOn":"2025-10-07T06:33:21.498Z","appVersion":"3.0","subscriptionName":"Standard","cartAnalytics":true,"freeTrialEndsOn":null,"settings":{"reminderBannerStyle":{"position":{"horizontal":"right","vertical":"bottom"},"closingMode":"doNotAutoClose","cssStyles":"","displayAfter":5,"headerText":"","imageUrl":null,"primaryColor":"#000000","reshowBannerAfter":"everyNewSession","selfcloseAfter":5,"showImage":false,"subHeaderText":""},"addedItemIdentifier":"_Gifted","ignoreOtherAppLineItems":null,"customVariantsInfoLifetimeMins":1440,"redirectPath":null,"ignoreNonStandardCartRequests":false,"bannerStyle":{"position":{"horizontal":"right","vertical":"bottom"},"cssStyles":null,"primaryColor":"#000000"},"themePresetId":null,"notificationStyle":{"position":{"horizontal":null,"vertical":null},"cssStyles":null,"duration":null,"hasCustomizations":false,"primaryColor":null},"fetchCartData":false,"useLocalStorage":{"enabled":false,"expiryMinutes":null},"popupStyle":{"addButtonText":null,"cssStyles":null,"dismissButtonText":null,"hasCustomizations":false,"imageUrl":null,"outOfStockButtonText":null,"primaryColor":null,"secondaryColor":null,"showProductLink":false,"subscriptionLabel":null},"refreshAfterBannerClick":false,"disableReapplyRules":false,"disableReloadOnFailedAddition":false,"autoReloadCartPage":false,"ajaxRedirectPath":null,"allowSimultaneousRequests":false,"applyRulesOnCheckout":false,"enableCartCtrlOverrides":true,"scriptSettings":{"branding":{"removalRequestSent":null,"show":false},"productPageRedirection":{"enabled":false,"products":[],"redirectionURL":"\/"},"debugging":{"enabled":false,"enabledOn":null,"stringifyObj":false},"hideGiftedPropertyText":false,"fetchCartDataBeforeRequest":false,"customCSS":null,"decodePayload":false,"delayUpdates":2000,"enableBuyNowInterceptions":false,"fetchProductInfoFromSavedDomain":false,"hideAlertsOnFrontend":false,"removeEGPropertyFromSplitActionLineItems":false,"removeProductsAddedFromExpiredRules":false,"useFinalPrice":true}},"translations":null,"defaultLocale":"en","shopDomain":"goodsleepco.health"}; 505 var productRedirectionEnabled = shopInfo.settings.scriptSettings.productPageRedirection.enabled; 506 if (["Unlimited", "Enterprise"].includes(shopInfo.subscriptionName) && productRedirectionEnabled) { 507 var products = shopInfo.settings.scriptSettings.productPageRedirection.products; 508 if (products.length > 0) { 509 var productIds = products.map(function(prod) { 510 var productGid = prod.id; 511 var productIdNumber = parseInt(productGid.split('/').pop()); 512 return productIdNumber; 513 }); 514 var productInfo = null; 515 var isProductInList = productIds.includes(productInfo.id); 516 if (isProductInList) { 517 var redirectionURL = shopInfo.settings.scriptSettings.productPageRedirection.redirectionURL; 518 if (redirectionURL) { 519 window.location = redirectionURL; 520 } 521 } 522 } 523 } 524 525 526 } catch(err) { 527 return 528 }}
528)() 529 </script>
529 530 531 532 533<!-- END app block -->
533<script src="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee-embed.js" type="text/javascript" defer="defer"></script>
533 534<link href="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee.css" rel="stylesheet" type="text/css" media="all">
535<script src="https://cdn.shopify.com/extensions/01a0ec21-7369-78a6-b9c0-c07227d664ec/lb-upsell-451/assets/lb-selleasy.js" type="text/javascript" defer="defer"></script>
vendor: 1 bytes, line 535
535
536<script src="https://cdn.shopify.com/extensions/019feb7b-2b89-71ba-a248-f1c8ef9b3368/stape-remix-56/assets/widget.js" type="text/javascript" defer="defer"></script>
vendor: 1 bytes, line 536
536
537<script src="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/native-geo-redirects.min.js" type="text/javascript" defer="defer"></script>
537 538<link href="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/native-geo-redirects.min.css" rel="stylesheet" type="text/css" media="all"> 539<link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
540<script>(function(){if ("sendBeacon" in navigator && "performance" in window) {try {var session_token_from_headers = performance.getEntriesByType('navigation')[0].serverTiming.find(x => x.name == '_s').description;} catch {var session_token_from_headers = undefined;}var session_cookie_matches = document.cookie.match(/_shopify_s=([^;]*)/);var session_token_from_cookie = session_cookie_matches && session_cookie_matches.length === 2 ? session_cookie_matches[1] : "";var session_token = session_token_from_headers || session_token_from_cookie || "";function handle_abandonment_event(e) {var entries = performance.getEntries().filter(function(entry) {return /monorail-edge.shopifysvc.com/.test(entry.name);});if (!window.abandonment_tracked && entries.length === 0) {window.abandonment_tracked = true;var currentMs = Date.now();var navigation_start = performance.timing.navigationStart;var payload = {shop_id: 59824177291,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token,page_type: "index"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script>
vendor: 1 bytes, line 540
540
541<script> 542 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 543</script>
vendor: 1 bytes, line 543
543
544<script>(function(){var wpmLoader=function(){"use strict";var e=/Googlebot|Storebot-Google|bingbot|Baiduspider|YandexBot|DuckDuckBot|Slurp|facebookexternalhit|Twitterbot|LinkedInBot|Applebot|AdsBot-Google|Mediapartners-Google|APIs-Google|PetalBot|SemrushBot|AhrefsBot|MJ12bot|DotBot|Acunetix|PerplexityBot|Perplexity-User/i,t=/bytedance/i;function i(){try{var e=document.cookie;if(!e||"string"!=typeof e)return;for(var t=0,i=e.split(";");t<i.length;t++){var n=i[t],r=n.indexOf("=");if(-1!==r){var o=n.slice(0,r).trim();if(o){var a=void 0;try{a=decodeURIComponent(o)}catch(e){a=o}if("_shopify_s"===a){var d=n.slice(r+1).trim();try{return decodeURIComponent(d)}catch(e){return d}}}}}return}catch(e){return}}function n(e){try{"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(e)}catch(e){}}function r(e,t){return"string"==typeof e&&e.length>0&&e.length<=t?e:void 0}function o(e){var t;switch(null==(t=null==e?void 0:e.navigation)?void 0:t.type){case 0:return"navigate";case 1:return"reload";case 2:return"back_forward";default:return}}function a(){var e,t,i;try{var n=null==(i=null==(t=null==(e=self.ShopifyAnalytics)?void 0:e.lib)?void 0:t.trekkie)?void 0:i.state;return"awaiting-consent"===n||"initialized"===n?n:void 0}catch(e){return}}return function(d,s,u,l){var c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};try{var p=c.trekkieShim;!0!==p&&"true"!==p||null!=window.__TREKKIE_SHIM_QUEUE||(window.__TREKKIE_SHIM_QUEUE=[])}catch(e){}var f,v,h,y,g=(v=(f={modern:/Edge?\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(9{2}|\d{3,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(15\.\d+|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9{2}|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]\d+|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/([2-9]\d|\d{3,})\.\d+/,legacy:/Edge?\/(1[6-9]|[2-9]\d|\d{3,})\.\d+(\.\d+|)|Firefox\/(5[4-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)|Chrom(ium|e)\/(5[1-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)([\d.]+$|.*Safari\/(?![\d.]+ Edge\/[\d.]+$))|(Maci|X1{2}).+ Version\/(10\.\d+|(1[1-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(3[89]|[4-9]\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(10[._]\d+|(1[1-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(15\.([5-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(5\.\d+|([6-9]|\d{2,})\.\d+)|Android.+MQ{2}Browser\/(14(\.(9|\d{2,})|)|(1[5-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/}).modern,h=f.legacy,(y=navigator.userAgent).match(e)?"bot":y.match(v)?"modern":y.match(h)?"legacy":y.match(t)?"bot":"unknown"),m=function(e){var t,i,n=r(e,128);try{var a=window.performance,d=null==(t=null==a?void 0:a.getEntriesByType)?void 0:t.call(a,"navigation")[0];if(!d)return{requestId:n,navigationType:o(a)};var s="type"in d?r(d.type,64):void 0,u="serverTiming"in d&&Array.isArray(d.serverTiming)?d.serverTiming:[];return{requestId:null!=n?n:r(null==(i=u.find(function(e){return"requestID"===e.name}))?void 0:i.description,128),navigationType:s}}catch(e){return{requestId:n}}}(c.requestId),w=function(e){var t=e.version,r=e.browserTarget,o=e.surface,a=e.shopId,d=e.monorailEndpoint,s=window.location.href;return{emit:function(e){var u=e.status,l=e.errorMsg,c=e.failureReason,p=e.useKeepaliveFallback,f=void 0!==p&&p,v=e.navigationType,h=e.pagehidePersisted,y=e.requestId,g=e.trekkieState;if(d){var m,w;try{var b=(new Date).getTime();m=JSON.stringify({metadata:{event_sent_at_ms:b},events:[{schema_id:"web_pixels_manager_load/3.3",payload:{version:t,bundle_target:r,page_url:s,status:u,surface:o,error_msg:l,failure_reason:c,navigation_type:v,pagehide_persisted:h,request_id:y,trekkie_state:g,shop_id:a,visit_token:i()},metadata:{event_created_at_ms:b}}]})}catch(e){return}try{if("function"==typeof window.navigator.sendBeacon&&-1===(w=window.navigator.userAgent).indexOf("iPhone; CPU iPhone OS 12_")&&-1===w.indexOf("iPad; CPU OS 12_")&&-1===w.indexOf("iPod touch; CPU iPhone OS 12_")&&window.navigator.sendBeacon.bind(window.navigator)(d,m))return}catch(e){}if(f)try{"function"==typeof window.fetch&&window.fetch(d,{method:"POST",headers:{"Content-Type":"text/plain"},body:m,keepalive:!0}
544).catch(function(){})}catch(e){}else try{var _=new XMLHttpRequest;_.open("POST",d,!0),_.setRequestHeader("Content-Type","text/plain"),_.send(m)}catch(e){n("[Web Pixels Manager] Got an unhandled error while logging to Monorail.")}}else n("[Web Pixels Manager] No Monorail endpoint provided, skipping logging.")}}}({version:u,browserTarget:g,surface:d.surface,shopId:d.shopId,monorailEndpoint:d.monorailEndpoint});if(Boolean(null==(_=null==(b=window.Shopify)?void 0:b.analytics)?void 0:_.replayQueue))w.emit({status:"setup-skipped",errorMsg:"replay queue already initialized."});else{var b,_;w.emit({status:"setup-started"}),window.Shopify=window.Shopify||{};var S=window.Shopify;S.analytics=S.analytics||{};var P=S.analytics;P.replayQueue=[],P.publish=function(e,t,i){return P.replayQueue.push([e,t,i]),!0};try{self.performance.mark("wpm:start")}catch(e){}var k,C="modern"===g?"modern":"legacy",E=(null!=l?l:{modern:"",legacy:""})[C],I=[(k={baseUrl:s,hashVersion:u,buildTarget:C}).baseUrl,"/wpm","/b",k.hashVersion,"modern"===k.buildTarget?"m":"l",".js"].join(""),O=!1,T=!1;try{c.browserTarget=g,function(){O=!0;try{window.addEventListener("pagehide",M)}catch(e){O=!1}}(),R(function(){try{R(x)}catch(e){D(e)}}),w.emit({status:"loading",requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()})}catch(e){D(e)}}function U(){var e;if(q(),!function(){var e,t;return Boolean(null==(t=null==(e=window.Shopify)?void 0:e.analytics)?void 0:t.initialized)}()){var t,i,n;try{if("function"!=typeof(null==(e=window.webPixelsManager)?void 0:e.init))return void A();if(!(null!==(n=i=t=window.webPixelsManager.init(d))&&"function"!=typeof n&&Object(n)===n&&"publish"in i&&"function"==typeof i.publish&&"publishCustomEvent"in i&&"function"==typeof i.publishCustomEvent&&"visitor"in i&&"function"==typeof i.visitor))return void A()}catch(e){return void A(e)}var r=window.Shopify.analytics;r.replayQueue.forEach(function(e){var i=e[0],n=e[1],r=e[2];t.publishCustomEvent(i,n,r)}),r.replayQueue=[],r.publish=t.publishCustomEvent,r.visitor=t.visitor,r.initialized=!0}}function A(e){B("manager_api_unavailable",void 0===e?void 0:Q(e))}function x(){B("script_load_failed","".concat(I," has failed to load"))}function B(e,t){T||(T=!0,q(),w.emit({status:"failed",errorMsg:t,failureReason:e,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function M(e){O&&(q(),w.emit({status:"pagehide-while-loading",useKeepaliveFallback:!0,pagehidePersisted:e.persisted,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function q(){O=!1;try{window.removeEventListener("pagehide",M)}catch(e){}}function R(e){var t;!function(e){var t=e.src,i=e.async,n=void 0===i||i,r=e.onload,o=e.onerror,a=e.sri,d=e.scriptDataAttributes,s=void 0===d?{}:d,u=document.createElement("script"),l=document.querySelector("head"),c=document.querySelector("body");if(u.async=n,u.src=t,a&&(u.integrity=a,u.crossOrigin="anonymous"),s)for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))try{u.dataset[p]=String(s[p])}catch(e){}if(r&&u.addEventListener("load",r),o&&u.addEventListener("error",o),l)l.appendChild(u);else{if(!c)throw new Error("Did not find a head or body element to append the script");c.appendChild(u)}}({src:I,async:!0,onload:U,onerror:e,sri:(t=E,"string"==typeof t&&/^sha384-[A-Za-z0-9+/=]+$/.test(t)?E:""),scriptDataAttributes:c})}function D(e){B("script_append_failed",Q(e))}function Q(e){return e instanceof Error?e.message:"Unknown error"}}}();wpmLoader({shopId: 59824177291,storefrontBaseUrl: "https://goodsleepco.health",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://goodsleepco.health/.well-known/shopify/monorail/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: ["4c64608a","16072cab","8450a54b","7ee89bf1"],webPixelsConfigList: [{"id":"2378301579","configuration":"{\"storeId\":\"fc8c33ba-ddb3-4627-bcbd-4d1f2e36df0d\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"9b5c7e9eba54366aed35e340586c8163","type":"APP","apiClientId":274629623809,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_email","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"2197258379","configuration":"{\"shopId\":\"good-sleep-co-gc.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"7093dff47f098f6de2afb75b62011ebe","type":"APP","apiClientId":2753413,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"}
544,{"id":"1902149771","configuration":"{\"accountID\":\"59824177291\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"9cf281f576a3744d05c8685f9f7f3f72","type":"APP","apiClientId":10250649601,"privacyPurposes":[],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1809023115","configuration":"{\"accountID\":\"WscBdf\",\"webPixelConfig\":\"eyJlbmFibGVBZGRlZFRvQ2FydEV2ZW50cyI6IHRydWV9\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c63c5b72c8d77be5f2d27d14c081da38","type":"APP","apiClientId":123074,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted","enabledFlags":["9a3ed68a"]},{"id":"1502478475","configuration":"{\"hyrosProductHash\":\"870f297b63c5291965577f724d5b5cb88e2f5c638b25cab9e3dc91ddcecd6f74\",\"hyrosUrl\":\"https:\\\/\\\/tr.goodsleepco.health\\\/v1\\\/lst\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"602d3c7dfefa9b81da3f888ed343aca5","type":"APP","apiClientId":1804565,"privacyPurposes":["ANALYTICS"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1430978699","configuration":"{\"shopId\":\"gid:\/\/shopify\/Shop\/59824177291\",\"baseUrl\":\"https:\/\/ab-testing.essential-apps.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"b26e45fa9a7a5cf51742cf4b300d6739","type":"APP","apiClientId":248390909953,"privacyPurposes":["ANALYTICS"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1293156491","configuration":"{\"pixel_id\":\"215594561324661\",\"pixel_type\":\"facebook_pixel\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"96420dbe9ea96c426a1b7f364f977719","type":"APP","apiClientId":2329312,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted","enabledFlags":["9a3ed68a"]},{"id":"519209099","configuration":"{\"config\":\"{\\\"google_tag_ids\\\":[\\\"AW-17634919796\\\",\\\"GT-PL9DFRG2\\\",\\\"G-KJMJE19M6G\\\"],\\\"target_country\\\":\\\"AU\\\",\\\"gtag_events\\\":[{\\\"type\\\":\\\"search\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/pn9QCNar8KMcEPSK_thB\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"begin_checkout\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/cO1QCM6X8KMcEPSK_thB\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"remove_from_cart\\\",\\\"action_label\\\":\\\"G-KJMJE19M6G\\\"},{\\\"type\\\":\\\"view_item\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/PQMCCNOr8KMcEPSK_thB\\\",\\\"MC-5E8NX8PYRJ\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"purchase\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/trUiCMuX8KMcEPSK_thB\\\",\\\"MC-5E8NX8PYRJ\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"add_shipping_info\\\",\\\"action_label\\\":\\\"G-KJMJE19M6G\\\"},{\\\"type\\\":\\\"page_view\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/E7u5CMyY8KMcEPSK_thB\\\",\\\"MC-5E8NX8PYRJ\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"view_item_list\\\",\\\"action_label\\\":\\\"G-KJMJE19M6G\\\"},{\\\"type\\\":\\\"add_payment_info\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/mub6CNmr8KMcEPSK_thB\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"add_to_cart\\\",\\\"action_label\\\":[\\\"G-KJMJE19M6G\\\",\\\"AW-17634919796\\\/-fJXCMmY8KMcEPSK_thB\\\",\\\"AW-17634919796\\\"]},{\\\"type\\\":\\\"view_cart\\\",\\\"action_label\\\":\\\"G-KJMJE19M6G\\\"}],\\\"enable_monitoring_mode\\\":false}\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"a3321ca85cf5aaf6b57585fcd8d67b3a","type":"APP","apiClientId":1780363,"privacyPurposes":[],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"46170251","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"3","type":"CUSTOM","privacyPurposes":["SALE_OF_DATA"],"name":"Google Ads Tracking","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"}
544,{"id":"127205515","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["SALE_OF_DATA"],"name":"Strape","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"127238283","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["SALE_OF_DATA"],"name":"Hyros","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"shopify-app-pixel","configuration":"{}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"APP","privacyPurposes":["ANALYTICS","MARKETING"]},{"id":"shopify-custom-pixel","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"]}],isMerchantRequest: false,initData: {"shop":{"name":"Good Sleep Co","paymentSettings":{"currencyCode":"AUD"},"myshopifyDomain":"good-sleep-co-gc.myshopify.com","countryCode":"AU","storefrontUrl":"https:\/\/goodsleepco.health"},"customer":null,"cart":null,"checkout":null,"productVariants":[],"products":[{"id":"7557722964107","handle":"hushd-avera","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"42792097382539","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"7058014961803","handle":"cleaner","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"41124907712651","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"7135719981195","handle":"good-sleep-test","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"41438208163979","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8323055943819","handle":"triple-magnesium-powder","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"47628215287947","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8323056140427","handle":"triple-magnesium-tablets","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"47628215746699","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"7222007398539","handle":"hushd-guard","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"41722883932299","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"7399462469771","handle":"hushd-nasal","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"42331947729035","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}],"purchasingCompany":null},},"https://goodsleepco.health/cdn","5982071ew7ea472e3p69b68784m2150dfea",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"true","themeId":"140639207563","themePublished":"true","eventMetadataId":"00d94464-ece8-44d9-b169-8bab02e801c3","pageType":"home","shopId":"59824177291","storefrontBaseUrl":"https:\/\/goodsleepco.health","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"4c64608a\", \"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"5982071ew7ea472e3p69b68784m2150dfea","publish":"custom","events":"[[\"page_viewed\",{}]]"});})();</script>
544<script> 545 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 546 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 547 window.ShopifyAnalytics.meta.currency = 'AUD'; 548 var meta = {"page":{"pageType":"home","requestId":"f8e2928d-53ec-4f15-9a11-e9c22d486ff5-1790841144"}}; 549 for (var attr in meta) { 550 window.ShopifyAnalytics.meta[attr] = meta[attr]; 551 } 552</script>
vendor: 1 bytes, line 552
552
553<script class="analytics"> 554 (function () { 555 var customDocumentWrite = function(content) { 556 var jquery = null; 557 558 if (window.jQuery) { 559 jquery = window.jQuery; 560 } else if (window.Checkout && window.Checkout.$) { 561 jquery = window.Checkout.$; 562 } 563 564 if (jquery) { 565 jquery('body').append(content); 566 } 567 }; 568 569 var hasLoggedConversion = function(token) { 570 if (token) { 571 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 572 } 573 return false; 574 } 575 576 var setCookieIfConversion = function(token) { 577 if (token) { 578 var twoMonthsFromNow = new Date(Date.now()); 579 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 580 581 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 582 } 583 } 584 585 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 586 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 587 if (trekkie.integrations) { 588 return; 589 } 590 trekkie.methods = [ 591 'identify', 592 'page', 593 'ready', 594 'track', 595 'trackForm', 596 'trackLink' 597 ]; 598 trekkie.factory = function(method) { 599 return function() { 600 var args = Array.prototype.slice.call(arguments); 601 args.unshift(method); 602 trekkie.push(args); 603 if (method == 'track' || method == 'page') { 604 var pageUrl; 605 try { 606 pageUrl = window.location.href; 607 } catch (e) {} 608 var pageReferrer; 609 try { 610 pageReferrer = document.referrer; 611 } catch (e) {} 612 try { 613 if (window.__TREKKIE_SHIM_QUEUE == null) { 614 window.__TREKKIE_SHIM_QUEUE = []; 615 } 616 window.__TREKKIE_SHIM_QUEUE.push({ 617 from: 'trekkie-stub', 618 method: method, 619 args: args.slice(1), 620 pageContext: { 621 url: pageUrl, 622 referrer: pageReferrer 623 } 624 }); 625 } catch (e) { 626 // no-op 627 } 628 } 629 return trekkie; 630 }; 631 }; 632 for (var i = 0; i < trekkie.methods.length; i++) { 633 var key = trekkie.methods[i]; 634 trekkie[key] = trekkie.factory(key); 635 } 636 trekkie.load = function(config) { 637 trekkie.config = config || {}; 638 trekkie.config.initialDocumentCookie = document.cookie; 639 var first = document.getElementsByTagName('script')[0]; 640var script = document.createElement('script'); 641script.type = 'text/javascript'; 642script.onerror = function(e) { 643 var scriptFallback = document.createElement('script'); 644 scriptFallback.type = 'text/javascript'; 645 scriptFallback.onerror = function(error) { 646 var Monorail = { 647 produce: function produce(monorailDomain, schemaId, payload) { 648 var currentMs = new Date().getTime(); 649 var event = { 650 schema_id: schemaId, 651 payload: payload, 652 metadata: { 653 event_created_at_ms: currentMs, 654 event_sent_at_ms: currentMs 655 } 656 }; 657 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 658 }, 659 sendRequest: function sendRequest(endpointUrl, payload) { 660 // Try the sendBeacon API 661 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 662 var blobData = new window.Blob([payload], { 663 type: 'text/plain' 664 }); 665 666 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 667 return true; 668 } // sendBeacon was not successful 669 670 } // XHR beacon 671 672 var xhr = new XMLHttpRequest(); 673 674 try { 675 xhr.open('POST', endpointUrl); 676 xhr.setRequestHeader('Content-Type', 'text/plain'); 677 xhr.send(payload); 678 } catch (e) { 679 console.log(e); 680 } 681 682 return false; 683 }, 684 isIos12: function isIos12() { 685 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 686 } 687 }; 688 Monorail.produce('monorail-edge.shopifysvc.com', 689 'trekkie_storefront_load_errors/1.1', 690 {shop_id: 59824177291, 691 theme_id: 140639207563, 692 app_name: "storefront", 693 context_url: window.location.href, 694 source_url: "//goodsleepco.health/cdn/s/trekkie.storefront.8fbb7598bfc52f7298fce09b15942db7f0f927c3.min.js"}); 695 696 }; 697 scriptFallback.async = true; 698 scriptFallback.src = '//goodsleepco.health/cdn/s/trekkie.storefront.8fbb7598bfc52f7298fce09b15942db7f0f927c3.min.js'; 699 first.parentNode.insertBefore(scriptFallback, first); 700}; 701script.async = true; 702script.src = '//goodsleepco.health/cdn/s/trekkie.storefront.8fbb7598bfc52f7298fce09b15942db7f0f927c3.min.js'; 703first.parentNode.insertBefore(script, first); 704 705 }; 706 trekkie.load( 707 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":59824177291,"isMerchantRequest":null,"themeId":14
7070639207563,"themeCityHash":"148775060654889333","contentLanguage":"en","currency":"AUD","eventMetadataId":"00d94464-ece8-44d9-b169-8bab02e801c3"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1","4c64608a"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":true,"source":"trekkie-storefront-renderer","apiClientId":580111}} 708 ); 709 710 var loaded = false; 711 trekkie.ready(function() { 712 if (loaded) return; 713 loaded = true; 714 715 window.ShopifyAnalytics.lib = window.trekkie; 716 717 var originalDocumentWrite = document.write; 718 document.write = customDocumentWrite; 719 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 720 document.write = originalDocumentWrite; 721 722 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 723 var token = match? match[1]: undefined; 724 if (!hasLoggedConversion(token)) { 725 setCookieIfConversion(token); 726 727 } 728 }); 729 730 window.ShopifyAnalytics.lib.page(null,{"pageType":"home","requestId":"f8e2928d-53ec-4f15-9a11-e9c22d486ff5-1790841144","shopifyEmitted":true}); 731 732 var eventsListenerScript = document.createElement('script'); 733 eventsListenerScript.async = true; 734 eventsListenerScript.src = "//goodsleepco.health/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 735 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 736})();</script>
vendor: 1 bytes, line 736
736
737<script 738 defer 739 src="https://goodsleepco.health/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 740 data-application="storefront-renderer" 741 data-shop-id="59824177291" 742 data-render-region="gcp-us-central1" 743 data-page-type="index" 744 data-theme-instance-id="140639207563" 745 data-theme-name="Motion" 746 data-theme-version="8.5.1" 747 data-monorail-region="shop_domain" 748 data-resource-timing-sampling-rate="10" 749 data-shs="true" 750 data-shs-beacon="true" 751 data-shs-export-with-fetch="true" 752 data-shs-logs-sample-rate="1" 753 data-shs-beacon-endpoint="https://goodsleepco.health/api/collect" 754></script>
754 755<meta name="shopify-y" content="9a7d475b-1f64-43f0-bfe2-465509ac27bb" data-expiration="1822414292000"><meta name="shopify-s" content="42c4d22c-60a7-4d6c-b42c-c455eb28e1eb" data-expiration="1790858492000"><meta name="new-cookie-storage-activated" content="t"> 756</head> 757<body class="bg-white text-brand-gray-900"> 758<!-- Google Tag Manager (noscript) -->
vendor: 68 bytes, lines 758-759
758 759<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
759GTM-M3CLJRL4
vendor: 86 bytes, lines 759-761
759" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 760 761
761<a href="#main-content" class="skip-link bg-blossom text-astral font-bold px-4 py-2 rounded-lg">Skip to content</a> 762 <div id="shopify-section-template--17924798480523__main" class="shopify-section">
763<script> 764(function () { 765 if (window.scPageCart) return; 766 var root = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/'; 767 function safe(fn) { try { return fn && fn(); } catch (e) { return undefined; } } 768 function confirmed(result) { var all = [].concat(result || []); return all.length > 0 && all.every(function (s) { return s === 'ok'; }); } 769 function open(mode) { 770 if (window.scCart && typeof window.scCart.open === 'function') { 771 try { return Promise.resolve(window.scCart.open(mode)).catch(function () { return 'rejected'; }); } 772 catch (e) { return Promise.resolve('rejected'); } 773 } 774 window.location.href = root + 'cart'; 775 return Promise.resolve('unavailable'); 776 } 777 function purchase(items, mode, track, pin) { 778 safe(track); // Existing click-intent analytics are not proof that Shopify accepted a write. 779 var api = window.scCart; 780 var method = pin ? 'buyNow' : 'add'; 781 if (!api || typeof api[method] !== 'function' || typeof api.open !== 'function') { 782 window.location.href = root + 'products/' + (mode === 'gst' ? 'good-sleep-test' : mode === 'cleaner' ? 'cleaner' : mode === 'pro' ? 'hushd-pro-avera' : 'hushd-avera'); 783 return Promise.resolve('unavailable'); 784 } 785 var pending; 786 try { pending = api[method](items); } catch (e) { pending = Promise.reject(e); } 787 if (!pin) open(mode); // Opening and buying are separate operations; opening never replays a purchase. 788 return Promise.resolve(pending).then(function (result) { 789 // buyNow atomically accepts the pin and starts the guarded 8-second checkout attempt. 790 // It returns the checkout outcome, not the later mutation/watch outcome. 791 if (pin) { if (result !== 'navigating' && result !== 'cancelled') open(mode); return result; } 792 if (confirmed(result)) { 793 safe(function () { 794 window.dataLayer = window.dataLayer || []; 795 window.dataLayer.push({ event: 'cart_purchase_confirmed', purchase_policy: pin ? 'pinned' : 'additive', items: items.map(function (item) { return { variant_id: String(item.id), quantity: item.quantity, selling_plan: item.selling_plan || null }; }) }); 796 }); 797 } 798 return result; 799 }, function () { open(mode); return 'rejected'; }).catch(function () { open(mode); return 'rejected'; }); 800 } 801 window.scPageCart = { 802 safe: safe, 803 confirmed: confirmed, 804 open: open, 805 add: function (items, mode, track) { return purchase(items, mode, track, false); }, 806 buyNow: function (items, mode, track) { return purchase(items, mode, track, true); }, 807 attributes: function (attrs) { 808 // Metadata is optional. Missing/old code must not start an independent cart writer. 809 try { 810 if (window.scCart && typeof window.scCart.setAttributes === 'function') { 811 return Promise.resolve(window.scCart.setAttributes(attrs)).catch(function () { return 'rejected'; }); 812 } 813 } catch (e) {} 814 return Promise.resolve('unavailable'); 815 } 816 }; 817})(); 818</script>
818 819 820<style> 821 @font-face { font-family: 'Normal'; src: url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Normal-ExtraLight.woff2?v=1773370324') format('woff2'); font-weight: 200; font-style: normal; font-display: swap; } 822 @font-face { font-family: 'Normal'; src: url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Normal-Light.woff2?v=1773370324') format('woff2'); font-weight: 300; font-style: normal; font-display: swap; } 823 @font-face { font-family: 'Normal'; src: url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Normal-Regular.woff2?v=1773370324') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } 824 @font-face { font-family: 'Normal'; src: url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Normal-Bold.woff2?v=1773370324') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; } 825 @font-face { font-family: 'Normal'; src: url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Normal-ExtraBold.woff2?v=1773370324') format('woff2'); font-weight: 800; font-style: normal; font-display: swap; } 826 * { font-family: 'Normal', sans-serif; } 827 828 html { 829 scroll-behavior: smooth; 830 } 831 832/* Progressive enhancement: fade-in only when JS loaded */ 833 .js-ready .fade-in { 834 opacity: 0; 835 transform: translateY(24px); 836 transition: opacity 0.6s ease, transform 0.6s ease; 837 } 838 839 .js-ready .fade-in.visible { 840 opacity: 1; 841 transform: translateY(0); 842 } 843 844 /* Respect reduced motion preference */ 845 @media (prefers-reduced-motion: reduce) { 846 .js-ready .fade-in { 847 opacity: 1; 848 transform: none; 849 transition: none; 850 } 851 .ticker-track { 852 animation: none; 853 } 854 .ring-gauge-fill { 855 transition: none; 856 } 857 } 858 859 /* Quiz custom pills */ 860 .quiz-pill { 861 transition: all 0.2s ease; 862 } 863 864 .quiz-pill.selected { 865 background-color: #ffffff; 866 color: #002156; 867 border-color: #ECAFAC; 868 font-weight: 800; 869 } 870 871 /* Quiz one-per-screen */ 872 .quiz-q { 873 animation: fadeUp 0.3s ease; 874 } 875 876 .quiz-card { 877 background: #FFFFFF; border: 1px solid #E5E7EB; border-radius: 20px; 878 box-shadow: 0 1px 2px rgba(0,33,86,0.04), 0 4px 16px rgba(0,33,86,0.04); 879 padding: 1.5rem; 880 } 881 @media (min-width: 640px) { .quiz-card { padding: 2rem; } } 882 883 .quiz-btn { 884 width: 100%; 885 display: flex; 886 align-items: center; 887 justify-content: space-between; 888 background: white; 889 border-radius: 0.75rem; 890 padding: 1rem 1.5rem; 891 font-size: 1.125rem; 892 font-weight: 600; 893 color: #002156; 894 cursor: pointer; 895 border: 2px solid #E5E7EB; 896 transition: all 0.15s ease; 897 } 898 899 .quiz-btn:hover { 900 background: #F7F8FA; 901 border-color: #99BCD2; 902 } 903 904 .quiz-tip { 905 margin-top: 2rem; 906 background: #E8F0F6; 907 border: 1.5px solid #99BCD2; 908 border-radius: 1rem; 909 padding: 1.25rem; 910 display: flex; 911 gap: 0.75rem; 912 align-items: flex-start; 913 text-align: left; 914 } 915 916 .results-blurred { 917 filter: blur(8px); 918 pointer-events: none; 919 user-select: none; 920 } 921 922 .results-blurred.unlocked { 923 filter: none; 924 pointer-events: auto; 925 user-select: auto; 926 } 927 928 @keyframes fadeUp { 929 from { 930 opacity: 0; 931 transform: translateY(16px); 932 } 933 934 to { 935 opacity: 1; 936 transform: translateY(0); 937 } 938 } 939 940 /* Logo ticker */ 941 @keyframes ticker { 942 0% { 943 transform: translateX(0); 944 } 945 946 100% { 947 transform: translateX(calc(-100% / 3)); 948 } 949 } 950 951 .ticker-track { 952 display: flex; 953 animation: ticker 25s linear infinite; 954 width: max-content; 955 } 956 957 .ticker-track:hover { 958 animation-play-state: paused; 959 } 960 961 /* Ring gauge animation */ 962 .ring-gauge { 963 transform: rotate(-90deg); 964 } 965 .ring-gauge-bg { 966 fill: none; 967 stroke: rgba(255,255,255,0.12); 968 } 969 .ring-gauge-fill { 970 fill: none; 971 stroke: url(#ring-gradient); 972 stroke-linecap: round; 973 transition: stroke-dashoffset 1.6s cubic-bezier(0.22, 1, 0.36, 1); 974 filter: drop-shadow(0 0 6px rgba(236,175,172,0.4)); 975 } 976 .ring-stat-num { 977 font-variant-numeric: tabular-nums; 978 } 979 .ring-container { 980 width: 88px; 981 height: 88px; 982 } 983 .clinical-bg { 984 background: radial-gradient(ellipse at center, rgba(255,255,255,0.04) 0%, transparent 70%), #002156; 985 } 986 @media (min-width: 768px) { 987 .ring-container { 988 width: 130px; 989 height: 130px; 990 } 991 .ring-gauge-fill { 992 filter: drop-shadow(0 0 10px rgba(236,175,172,0.45)); 993 } 994 } 995 996 /* Mobile hamburger menu */ 997 .mobile-nav { 998 max-height: 0; 999 overflow: hidden; 1000 transition: max-height 0.3s ease; 1001 } 1002 1003 .mobile-nav.open { 1004 max-height: 400px; 1005 } 1006</style> 1007 1008<svg xmlns="http://www.w3.org/2000/svg" class="hidden"> 1009 <symbol id="ico-star" viewBox="0 0 20 20"> 1010 <path 1011 d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z" /> 1012 </symbol> 1013 <symbol id="ico-check-fill" viewBox="0 0 20 20"> 1014 <path fill-rule="evenodd" 1015 d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" 1016 clip-rule="evenodd" /> 1017 </symbol>
1018 <symbol id="ico-chevron-down" viewBox="0 0 24 24"> 1019 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 1020 </symbol> 1021 <symbol id="ico-arrow-right" viewBox="0 0 24 24"> 1022 <path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" /> 1023 </symbol> 1024 <symbol id="ico-check-stroke" viewBox="0 0 24 24"> 1025 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1026 </symbol> 1027 <symbol id="ico-info" viewBox="0 0 24 24"> 1028 <path stroke-linecap="round" stroke-linejoin="round" 1029 d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> 1030 </symbol> 1031 <symbol id="ico-arrow-left" viewBox="0 0 24 24"> 1032 <path stroke-linecap="round" stroke-linejoin="round" d="M10 19l-7-7m0 0l7-7m-7 7h18" /> 1033 </symbol> 1034 <symbol id="ico-mail" viewBox="0 0 24 24"> 1035 <path stroke-linecap="round" stroke-linejoin="round" 1036 d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /> 1037 </symbol> 1038 <symbol id="ico-phone" viewBox="0 0 24 24"> 1039 <path stroke-linecap="round" stroke-linejoin="round" 1040 d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /> 1041 </symbol> 1042 <symbol id="ico-menu" viewBox="0 0 24 24"> 1043 <path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" /> 1044 </symbol> 1045 <symbol id="ico-x" viewBox="0 0 24 24"> 1046 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> 1047 </symbol> 1048 </svg> 1049 1050 1051 <!-- ============================================ --> 1052 <!-- TOP BAR --> 1053 <!-- ============================================ --> 1054 1055 <div class="bg-astral text-white text-xs py-2"> 1056 <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex justify-between items-center"> 1057 <a href="https://provider.goodsleepco.health/" class="text-dream hover:text-white transition font-medium">I'm a 1058 health professional</a> 1059 <div class="flex items-center gap-4"> 1060 <a href="mailto:[email protected]" class="flex items-center gap-1 text-dream hover:text-white transition"> 1061 <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1062 <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /> 1063 </svg> 1064 [email protected] 1065 </a> 1066 <a href="tel:+61756902029" class="hidden sm:flex items-center gap-1 text-dream hover:text-white transition"> 1067 <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2"> 1068 <use href="#ico-phone" /> 1069 </svg> 1070 AU: 07 5690 2029 1071 </a> 1072 </div> 1073 </div> 1074 </div> 1075 1076 1077 <!-- ============================================ --> 1078 <!-- HEADER / NAV --> 1079 <!-- ============================================ --> 1080 1081 <!-- âââ UNIVERSAL SITE HEADER (site-header) âââ --> 1082<style> 1083 .gsh-mobile-nav { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } 1084 .gsh-mobile-nav.open { max-height: 380px; } 1085 .gsh-link { font-size: 14px; font-weight: 600; color: #002156; transition: color 0.2s; text-decoration: none; } 1086 .gsh-link:hover { color: #ECAFAC; } 1087 .gsh-link.gsh-active { border-bottom: 2px solid #002156; padding-bottom: 2px; } 1088 .gsh-link.gsh-active:hover { color: #002156; } 1089</style> 1090<header class="sticky top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-sm border-b border-brand-gray-100" style="position:sticky;"> 1091 <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> 1092 <div class="flex justify-between items-center h-16"> 1093 1094 <!-- Logo --> 1095 <a href="/" class="flex items-center"> 1096 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-logo-navy-pink.webp?v=1772167928" 1097 alt="Good Sleep Co." class="h-8 sm:h-9 w-auto" width="180" height="36" /> 1098 </a> 1099 1100 <!-- Desktop Nav --> 1101 <nav class="hidden lg:flex items-center gap-8"> 1102 <a href="/pages/sleep-quiz" class="gsh-link">Sleep Quiz</a> 1103 <a href="/products/good-sleep-test" class="gsh-link">Get Tested</a> 1104 <a href="/pages/treatment" class="gsh-link">Treatment</a> 1105 <a href="/products/cleaner" class="gsh-link">
1105Cleaner</a> 1106 <a href="/collections/shop" class="gsh-link">Shop</a> 1107 <a href="/pages/faqs" class="gsh-link">FAQs</a> 1108 </nav><!-- Desktop Cart --> 1109 <a href="/cart" onclick="if (window.scCart && window.scCart.open) { event.preventDefault(); window.scCart.open(); }" class="hidden lg:flex items-center gap-2 text-astral hover:text-blossom transition" aria-label="Cart"> 1110 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1111 <path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" /> 1112 </svg> 1113 </a> 1114 1115 <!-- Mobile: Cart + Hamburger --> 1116 <div class="flex items-center gap-3 lg:hidden"> 1117 <a href="/cart" onclick="if (window.scCart && window.scCart.open) { event.preventDefault(); window.scCart.open(); }" class="text-astral" aria-label="Cart"> 1118 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1119 <path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" /> 1120 </svg> 1121 </a> 1122 <button class="gsh-menu-toggle text-astral" aria-label="Menu" aria-expanded="false"> 1123 <svg class="gsh-menu-open w-6 h-6" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1124 <path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" /> 1125 </svg> 1126 <svg class="gsh-menu-close w-6 h-6 hidden" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1127 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> 1128 </svg> 1129 </button> 1130 </div> 1131 </div> 1132 1133 <!-- Mobile Nav Dropdown --> 1134 <div class="gsh-mobile-nav lg:hidden"> 1135 <nav class="py-4 border-t border-brand-gray-100 flex flex-col gap-3"><a href="/pages/sleep-quiz" class="gsh-link py-1">Sleep Quiz</a> 1136 <a href="/products/good-sleep-test" class="gsh-link py-1">Get Tested</a> 1137 <a href="/pages/treatment" class="gsh-link py-1">Treatment</a> 1138 <a href="/products/cleaner" class="gsh-link py-1">Cleaner</a> 1139 <a href="/collections/shop" class="gsh-link py-1">Shop</a> 1140 <a href="/pages/faqs" class="gsh-link py-1">FAQs</a> 1141 </nav> 1142 </div> 1143 </div> 1144</header>
1145<script> 1146 (function () { 1147 document.querySelectorAll('.gsh-menu-toggle').forEach(function (toggle) { 1148 if (toggle.dataset.gshBound) return; 1149 toggle.dataset.gshBound = '1'; 1150 var header = toggle.closest('header'); 1151 var nav = header.querySelector('.gsh-mobile-nav'); 1152 var iconOpen = toggle.querySelector('.gsh-menu-open'); 1153 var iconClose = toggle.querySelector('.gsh-menu-close'); 1154 toggle.addEventListener('click', function () { 1155 var isOpen = nav.classList.toggle('open'); 1156 toggle.setAttribute('aria-expanded', isOpen); 1157 iconOpen.classList.toggle('hidden', isOpen); 1158 iconClose.classList.toggle('hidden', !isOpen); 1159 }); 1160 }); 1161 })(); 1162</script>
1162 1163 1164 1165 1166 <!-- ============================================ --> 1167 <!-- SECTION 1: HERO BANNER --> 1168 <!-- ============================================ --> 1169 1170 <section id="hero-banner" class="pt-4 sm:pt-6 md:pt-8 bg-cloud pb-8 sm:pb-12"> 1171 <div class="max-w-6xl mx-auto px-5 sm:px-6 relative z-10"> 1172 <div 1173 class="relative overflow-hidden rounded-2xl sm:rounded-3xl shadow-[0_8px_30px_rgba(0,33,86,0.06)] bg-astral flex flex-col sm:block min-h-[500px] sm:min-h-0 sm:aspect-[21/9]"> 1174 1175 <!-- Background Video (Absolute on Desktop, Height restricted on Mobile) --> 1176 <div class="relative sm:absolute inset-0 h-[280px] sm:h-full w-full overflow-hidden"> 1177 <video autoplay muted loop playsinline 1178 poster="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/homepage-sleep-study-bg.webp?v=1773365351" 1179 class="w-full h-full object-cover object-center sm:object-[center_35%]"> 1180 <source src="https://cdn.shopify.com/videos/c/o/v/0b04defe31bb40d6a3408611e3ea303c.mp4" type="video/mp4" /> 1181 </video> 1182 <!-- Desktop Gradient --> 1183 <div class="hidden sm:block absolute inset-0 bg-gradient-to-r from-astral/60 via-astral/35 to-transparent"> 1184 </div> 1185 <!-- Mobile Gradient (Bottom Up) --> 1186 <div class="block sm:hidden absolute inset-0 bg-gradient-to-t from-astral/70 via-astral/30 to-transparent"> 1187 </div> 1188 </div> 1189 1190 <!-- Content --> 1191 <div 1192 class="relative z-10 px-6 sm:px-12 md:px-16 lg:px-20 pt-8 sm:pt-0 sm:h-full flex flex-col justify-end sm:justify-center max-w-2xl text-center sm:text-left mt-auto pb-10 sm:pb-0"> 1193 <p class="text-[10px] sm:text-xs font-bold tracking-brand uppercase text-blossom mb-3 sm:mb-4 drop-shadow-md"> 1194 CLINICAL-GRADE SLEEP CARE, FROM YOUR OWN BED</p> 1195 <h1 1196 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-4 sm:mb-5 drop-shadow-lg"> 1197 Gave Up on CPAP? There's a Better Way to Treat Sleep Apnea.</h1> 1198 <p 1199 class="text-white/90 text-sm sm:text-base md:text-lg font-light leading-relaxed mb-8 max-w-md mx-auto sm:mx-0 drop-shadow-md"> 1200 10,000+ Australians have switched to our home sleep test and oral device â no clinic, no mask, no hassle.</p> 1201 1202 <div class="flex flex-col sm:flex-row items-center gap-4"> 1203 <a href="#test-vs-treatment" 1204 class="inline-flex items-center justify-center gap-2 bg-blossom text-astral font-extrabold text-sm sm:text-base px-8 py-3.5 sm:py-4 rounded-full hover:bg-white transition-colors duration-300 shadow-xl w-full sm:w-auto shrink-0">Learn 1205 More <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1206 stroke-width="2.5"> 1207 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 1208 </svg></a> 1209 </div> 1210 1211 <!-- Trust Badges --> 1212 <div 1213 class="mt-8 sm:mt-10 flex flex-nowrap justify-center sm:justify-start gap-x-4 sm:gap-x-6 text-white/80 text-[10px] sm:text-xs font-bold uppercase tracking-wider"> 1214 <span class="flex items-center gap-1 sm:gap-1.5 whitespace-nowrap"><svg class="w-3.5 h-3.5 sm:w-4 sm:h-4 text-blossom shrink-0" fill="none" viewBox="0 0 24 24" 1215 stroke="currentColor" stroke-width="2.5"> 1216 <use href="#ico-check-stroke" /> 1217 </svg> TGA Registered</span> 1218 <span class="flex items-center gap-1 sm:gap-1.5 whitespace-nowrap"><svg class="w-3.5 h-3.5 sm:w-4 sm:h-4 text-blossom shrink-0" fill="none" viewBox="0 0 24 24" 1219 stroke="currentColor" stroke-width="2.5"> 1220 <use href="#ico-check-stroke" /> 1221 </svg> Specialist Reviewed</span> 1222 <span class="flex items-center gap-1 sm:gap-1.5 whitespace-nowrap"><svg class="w-3.5 h-3.5 sm:w-4 sm:h-4 text-blossom shrink-0" fill="none"
1223 viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"> 1224 <use href="#ico-check-stroke" /> 1225 </svg> 10,000+ Aussies Tested</span> 1226 </div> 1227 </div> 1228 1229 </div><!-- /rounded card --> 1230 </div><!-- /max-w container --> 1231 </section> 1232 1233 1234 <!-- ============================================ --> 1235 <!-- CLINICAL EVIDENCE STRIP --> 1236 <!-- ============================================ --> 1237 1238 <section class="clinical-bg py-8 sm:py-10 md:py-16 fade-in" id="clinical-evidence"> 1239 <svg aria-hidden="true" style="position:absolute;width:0;height:0;overflow:hidden"> 1240 <defs> 1241 <linearGradient id="ring-gradient" x1="0%" y1="0%" x2="100%" y2="100%"> 1242 <stop offset="0%" stop-color="#ECAFAC" /> 1243 <stop offset="100%" stop-color="#f5d5d3" /> 1244 </linearGradient> 1245 </defs> 1246 </svg> 1247 <div class="max-w-5xl mx-auto px-5 sm:px-6 lg:px-8"> 1248 <h2 class="text-[10px] sm:text-xs md:text-3xl font-extrabold tracking-brand md:tracking-normal uppercase md:normal-case text-blossom md:text-white mb-6 sm:mb-8 md:mb-12 text-center">A Proven Sleep Apnea Treatment</h2> 1249 <div class="flex justify-center items-start gap-12 sm:gap-16 md:gap-20 lg:gap-28"> 1250 1251 <!-- Stat 1: Diagnostic Accuracy --> 1252 <div class="flex flex-col items-center" style="max-width:180px"> 1253 <div class="relative ring-container"> 1254 <svg class="ring-gauge w-full h-full" viewBox="0 0 72 72" role="img" aria-label="Greater than 90 percent diagnostic accuracy"> 1255 <circle class="ring-gauge-bg" cx="36" cy="36" r="30" stroke-width="4.5" /> 1256 <circle class="ring-gauge-fill" cx="36" cy="36" r="30" stroke-width="4.5" 1257 stroke-dasharray="188.5" stroke-dashoffset="188.5" data-target="90" data-delay="0" /> 1258 </svg> 1259 <span class="absolute inset-0 flex items-center justify-center text-white font-extrabold text-xl md:text-3xl ring-stat-num" aria-hidden="true" data-prefix=">" data-count="90"><span style="opacity:0">>90</span><span class="text-blossom text-sm md:text-lg">%</span></span> 1260 </div> 1261 <p class="text-white font-bold text-xs md:text-sm mt-3 md:mt-4 text-center leading-tight md:leading-normal md:font-normal">Diagnostic Accuracy</p> 1262 <p class="text-[10px] mt-1 text-center" style="color:rgba(255,255,255,0.55)">Peer-reviewed</p> 1263 </div> 1264 1265 <!-- Stat 2: Snoring Reduction --> 1266 <div class="flex flex-col items-center" style="max-width:180px"> 1267 <div class="relative ring-container"> 1268 <svg class="ring-gauge w-full h-full" viewBox="0 0 72 72" role="img" aria-label="96 percent snoring reduction"> 1269 <circle class="ring-gauge-bg" cx="36" cy="36" r="30" stroke-width="4.5" /> 1270 <circle class="ring-gauge-fill" cx="36" cy="36" r="30" stroke-width="4.5" 1271 stroke-dasharray="188.5" stroke-dashoffset="188.5" data-target="96" data-delay="200" /> 1272 </svg> 1273 <span class="absolute inset-0 flex items-center justify-center text-white font-extrabold text-xl md:text-3xl ring-stat-num" aria-hidden="true" data-prefix="" data-count="96"><span style="opacity:0">96</span><span class="text-blossom text-sm md:text-lg">%</span></span> 1274 </div> 1275 <p class="text-white font-bold text-xs md:text-sm mt-3 md:mt-4 text-center leading-tight md:leading-normal md:font-normal">Snoring Reduction</p> 1276 <p class="text-[10px] mt-1 text-center" style="color:rgba(255,255,255,0.55)">RCT, 2006</p> 1277 </div> 1278 1279 <!-- Stat 3: Prefer Over CPAP --> 1280 <div class="flex flex-col items-center" style="max-width:180px"> 1281 <div class="relative ring-container"> 1282 <svg class="ring-gauge w-full h-full" viewBox="0 0 72 72" role="img" aria-label="91 percent of patients prefer Avera over CPAP"> 1283 <circle class="ring-gauge-bg" cx="36" cy="36" r="30" stroke-width="4.5" /> 1284 <circle class="ring-gauge-fill" cx="36" cy="36" r="30" stroke-width="4.5" 1285 stroke-dasharray="188.5" stroke-dashoffset="188.5" data-target="91" data-delay="400" /> 1286 </svg>
1287 <span class="absolute inset-0 flex items-center justify-center text-white font-extrabold text-xl md:text-3xl ring-stat-num" aria-hidden="true" data-prefix="" data-count="91"><span style="opacity:0">91</span><span class="text-blossom text-sm md:text-lg">%</span></span> 1288 </div> 1289 <p class="text-white font-bold text-xs md:text-sm mt-3 md:mt-4 text-center leading-tight md:leading-normal md:font-normal">Prefer Avera Over CPAP</p> 1290 <p class="text-[10px] mt-1 text-center" style="color:rgba(255,255,255,0.55)">Patient feedback</p> 1291 </div> 1292 1293 </div> 1294 </div> 1295 </section> 1296 1297 1298 <!-- ============================================ --> 1299 <!-- SECTION 1B: NAVIGATING SLEEP APNEA --> 1300 <!-- ============================================ --> 1301 1302 <section id="test-vs-treatment" class="pt-8 pb-16 sm:pt-10 sm:pb-16 bg-cloud overflow-hidden fade-in relative"> 1303 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8"> 1304 <div class="text-center mb-10 sm:mb-14"> 1305 <p class="text-[10px] sm:text-xs font-bold tracking-brand uppercase text-astral mb-3">Sleep Solutions</p> 1306 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-astral leading-tight mb-3">A smarter path to<br 1307 class="hidden md:block"> sleep apnea care.</h2> 1308 <p class="text-base sm:text-lg text-brand-gray-600 max-w-2xl mx-auto">No clinic, no CPAP, no hassle. From diagnosis to treatment, all from home.</p> 1309 </div> 1310 1311 <div class="grid md:grid-cols-2 gap-8 lg:gap-12 relative z-10 max-w-5xl mx-auto"> 1312 <!-- TEST PATH --> 1313 <div 1314 class="bg-astral rounded-3xl overflow-hidden flex flex-col h-full shadow-xl hover:-translate-y-1 transition duration-500"> 1315 <div class="shrink-0 bg-astral h-[240px] sm:h-[200px] overflow-hidden"> 1316 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-hero-bg.webp?v=1772167928" 1317 alt="Good Sleep Test home sleep study" loading="lazy" class="w-full h-full object-cover" /> 1318 </div> 1319 <div class="flex flex-col flex-grow p-8 md:p-8"> 1320 <h3 class="text-white text-3xl font-extrabold leading-snug mb-4">I think I have it.</h3> 1321 <p class="text-white/80 text-sm md:text-base font-light leading-relaxed mb-6 flex-grow">A simple wristband 1322 device 1323 which connects to your phone, with specialist results, to test your sleep, at home.</p> 1324 <ul class="space-y-3 mb-8"> 1325 <li class="flex items-center gap-3 text-white text-sm"><span 1326 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1327 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1328 stroke-linecap="round" stroke-linejoin="round"> 1329 <path d="M1 5l3 3 7-7" /> 1330 </svg></span>1-night home test</li> 1331 <li class="flex items-center gap-3 text-white text-sm"><span 1332 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1333 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1334 stroke-linecap="round" stroke-linejoin="round"> 1335 <path d="M1 5l3 3 7-7" /> 1336 </svg></span>Specialist-reviewed results</li> 1337 <li class="flex items-center gap-3 text-white text-sm"><span 1338 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1339 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1340 stroke-linecap="round" stroke-linejoin="round"> 1341 <path d="M1 5l3 3 7-7" /> 1342 </svg></span>Keep the device</li> 1343 </ul> 1344 <a href="/products/good-sleep-test" 1345 class="inline-flex items-center justify-center gap-2 bg-blossom text-astral font-bold text-sm px-6 py-3.5 rounded-full hover:bg-white transition-colors duration-200 mt-auto min-h-[48px]">Get 1346 My Test <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"> 1347 <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" /> 1348 </svg></a> 1349 </div> 1350 </div> 1351 1352 <!-- TREATMENT PATH --> 1353 <div 1354 class="bg-white rounded-3xl overflow-hidden flex flex-col h-full shadow-xl hover:-translate-y-1 transition duration-500"> 1355 <div class="shrink-0 bg-white h-[240px] sm:h-[200px] overflow-hidden"> 1356 <img 1357 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/homepage-oral-device-hand.webp?v=1773366326" 1358 alt="Custom-fitted oral device held in hand" loading="lazy" class="w-full h-full object-cover" /> 1359 </div> 1360 <div class="flex flex-col flex-grow p-8 md:p-8"> 1361 <h3 class="text-astral text-3xl font-extrabold leading-snug mb-4">I know I have it.</h3> 1362 <p class="text-brand-gray-600 text-sm md:text-base font-light leading-relaxed mb-6 flex-grow">Diagnosed with 1363 sleep apnea? 1364 You may be eligible for a custom-fitted oral device — a comfortable, CPAP-free alternative.</p> 1365 <ul class="space-y-3 mb-8"> 1366 <li class="flex items-center gap-3 text-astral text-sm"><span 1367 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1368 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1369 stroke-linecap="round" stroke-linejoin="round"> 1370 <path d="M1 5l3 3 7-7" /> 1371 </svg></span>Custom-fitted to you</li> 1372 <li class="flex items-center gap-3 text-astral text-sm"><span 1373 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1374 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1375 stroke-linecap="round" stroke-linejoin="round"> 1376 <path d="M1 5l3 3 7-7" /> 1377 </svg></span>No CPAP needed</li> 1378 <li class="flex items-center gap-3 text-astral text-sm"><span 1379 class="w-5 h-5 rounded-full bg-blossom flex items-center justify-center shrink-0"><svg 1380 class="w-3 h-3 text-astral" fill="none" viewBox="0 0 12 10" stroke="currentColor" stroke-width="2.5" 1381 stroke-linecap="round" stroke-linejoin="round"> 1382 <path d="M1 5l3 3 7-7" /> 1383 </svg></span>Clinically proven</li> 1384 </ul> 1385 <a href="/pages/treatment" 1386 class="inline-flex items-center justify-center gap-2 bg-astral text-white font-bold text-sm px-6 py-3.5 rounded-full hover:bg-blossom hover:text-astral transition-colors duration-200 mt-auto min-h-[48px]">Find 1387 My Treatment <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"> 1388 <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" /> 1389 </svg></a> 1390 </div> 1391 </div> 1392 </div> 1393 1394 </div> 1395 </section> 1396 1397 1398 <!-- ============================================ --> 1399 <!-- STOCKIST LOGO TICKER --> 1400 <!-- ============================================ --> 1401 1402 <section id="hp-trusted-by" class="pt-8 pb-16 sm:pt-10 sm:pb-20 bg-cloud overflow-hidden fade-in"> 1403 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8 mb-6 text-center"> 1404 <p class="text-[10px] sm:text-xs font-bold tracking-brand uppercase text-brand-gray-500">TRUSTED BY</p> 1405 </div> 1406 <div class="relative"> 1407 <div class="ticker-track"> 1408 <div class="flex items-center gap-12 sm:gap-16 px-8"> 1409 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img11-Photoroom.webp?v=1773369181" 1410 alt="Rise" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1411 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Resmed_logo.webp?v=1773369181" alt="Resmed" 1412 class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1413 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img14.webp?v=1773369448" 1414 alt="CPAP Direct" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1415 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_26.webp?v=1773369181" 1416 alt="Blooms The Chemist" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1417 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_23-Photoroom.webp?v=1773369180" 1418 alt="Priceline Pharmacy" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1419 </div> 1420 <div class="flex items-center gap-12 sm:gap-16 px-8"> 1421 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img11-Photoroom.webp?v=1773369181" 1422 alt="Rise" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1423 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Resmed_logo.webp?v=1773369181" alt="Resmed" 1424 class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1425 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img14.webp?v=1773369448" 1426 alt="CPAP Direct" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1427 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_26.webp?v=1773369181" 1428 alt="Blooms The Chemist" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1429 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_23-Photoroom.webp?v=1773369180" 1430 alt="Priceline Pharmacy" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1431 </div> 1432 <div class="flex items-center gap-12 sm:gap-16 px-8"> 1433 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img11-Photoroom.webp?v=1773369181" 1434 alt="Rise" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1435 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Resmed_logo.webp?v=1773369181" alt="Resmed" 1436 class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1437 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/page1_img14.webp?v=1773369448" 1438 alt="CPAP Direct" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1439 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_26.webp?v=1773369181" 1440 alt="Blooms The Chemist" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1441 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Image_23-Photoroom.webp?v=1773369180" 1442 alt="Priceline Pharmacy" class="h-8 sm:h-10 w-auto opacity-70" loading="lazy" /> 1443 </div> 1444 </div> 1445 </div> 1446 </section> 1447 1448 1449 <!-- ============================================ --> 1450 <!-- SECTION 2: QUICK QUIZ BANNER --> 1451 <!-- ============================================ --> 1452 1453 <section id="quiz" class="pb-16 pt-8 sm:pb-24 sm:pt-12 md:pb-32 bg-cloud fade-in"> 1454 <div class="max-w-6xl mx-auto px-5 sm:px-6"> 1455 <div class="relative overflow-hidden rounded-2xl sm:rounded-3xl shadow-[0_4px_24px_rgba(0,33,86,0.1)]">
1456 <!-- Background image with dark overlay --> 1457 <div class="absolute inset-0"> 1458 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/homepage-quiz-bg.webp?v=1773366924" alt="Couple sleeping peacefully after sleep apnea treatment" 1459 class="w-full h-full object-cover object-top brightness-125 saturate-[1.2]" loading="lazy" 1460 aria-hidden="true" /> 1461 <div class="absolute inset-0 bg-astral/25"></div> 1462 </div> 1463 <div class="relative z-10 px-6 sm:px-10 md:px-14 py-10 sm:py-12 md:py-14 text-center"> 1464 <h2 class="text-2xl sm:text-3xl md:text-4xl font-extrabold text-white mb-1"> 1465 <span class="text-blossom italic">Free quiz:</span> Do you have Sleep Apnea? 1466 </h2> 1467 <p class="text-sm sm:text-base text-white/80 mb-6 sm:mb-8">Take charge of troubled sleep. Get your personalised sleep risk score in under 2 minutes.</p> 1468 <a href="/pages/sleep-quiz" class="inline-flex items-center gap-2 bg-blossom text-astral font-extrabold px-8 py-4 rounded-full hover:bg-opacity-80 transition text-lg pulse-soft"> 1469 Take the Free Sleep Quiz 1470 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg> 1471 </a> 1472 </div> 1473 </div> 1474 </div> 1475 </section> 1476 <!-- ============================================ --> 1477 <!-- SECTION 1C: THE JOURNEY (4 STEPS) --> 1478 <!-- ============================================ --> 1479 1480 <section id="hp-journey" class="py-16 sm:py-24 bg-white overflow-hidden fade-in relative"> 1481 <div class="max-w-6xl mx-auto px-5 sm:px-6 lg:px-8 text-center lg:text-left relative z-10"> 1482 <p class="text-[10px] sm:text-xs font-bold tracking-brand uppercase text-blossom mb-2 sm:mb-3">How it works</p> 1483 <h2 1484 class="text-3xl sm:text-4xl md:text-[2.75rem] font-extrabold leading-tight text-astral mb-10 sm:mb-14 max-w-2xl mx-auto lg:mx-0"> 1485 Sleep apnea treatment couldn't be easier. 1486 </h2> 1487 1488 <div class="relative"> 1489 <!-- Connecting Line (Desktop) --> 1490 <div class="hidden lg:block absolute top-[44px] left-[12%] right-[12%] h-0.5 bg-astral/10"></div> 1491 1492 <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 sm:gap-6 relative z-10"> 1493 1494 <!-- Step 1 --> 1495 <div 1496 class="relative bg-white rounded-3xl p-8 sm:p-6 lg:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)] border border-astral/10 hover:-translate-y-1 hover:shadow-lg transition duration-500 cursor-default"> 1497 <div 1498 class="w-14 h-14 rounded-full bg-blossom/20 flex items-center justify-center text-astral font-extrabold text-xl mb-6 mx-auto lg:mx-0"> 1499 01 1500 </div> 1501 <h3 class="text-xl font-extrabold text-astral mb-3 text-center lg:text-left">Test</h3> 1502 <p class="text-sm text-brand-gray-600 leading-relaxed text-center lg:text-left">Complete a highly 1503 accurate 1-night sleep study from the comfort of your own bed. No lab required.</p> 1504 </div> 1505 1506 <!-- Step 2 --> 1507 <div 1508 class="relative bg-white rounded-3xl p-8 sm:p-6 lg:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)] border border-astral/10 hover:-translate-y-1 hover:shadow-lg transition duration-500 cursor-default"> 1509 <div 1510 class="w-14 h-14 rounded-full bg-blossom/20 flex items-center justify-center text-astral font-extrabold text-xl mb-6 mx-auto lg:mx-0"> 1511 02 1512 </div> 1513 <h3 class="text-xl font-extrabold text-astral mb-3 text-center lg:text-left">Report</h3> 1514 <p class="text-sm text-brand-gray-600 leading-relaxed text-center lg:text-left">Your data is 1515 securely reviewed by an independent specialist sleep physician, giving you clinical answers.</p> 1516 </div> 1517 1518 <!-- Step 3 --> 1519 <div 1520 class="relative bg-white rounded-3xl p-8 sm:p-6 lg:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)] border border-astral/10 hover:-translate-y-1 hover:shadow-lg transition duration-500 cursor-default"> 1521 <div
1522 class="w-14 h-14 rounded-full bg-blossom/20 flex items-center justify-center text-astral font-extrabold text-xl mb-6 mx-auto lg:mx-0"> 1523 03 1524 </div> 1525 <h3 class="text-xl font-extrabold text-astral mb-3 text-center lg:text-left">Treatment</h3> 1526 <p class="text-sm text-brand-gray-600 leading-relaxed text-center lg:text-left">If diagnosed with 1527 sleep apnea, we provide access to comfortable, TGA-listed oral appliance therapy.</p> 1528 </div> 1529 1530 <!-- Step 4 --> 1531 <div 1532 class="relative bg-white rounded-3xl p-8 sm:p-6 lg:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)] border border-astral/10 hover:-translate-y-1 hover:shadow-lg transition duration-500 cursor-default"> 1533 <div 1534 class="w-14 h-14 rounded-full bg-blossom/20 flex items-center justify-center text-astral font-extrabold text-xl mb-6 mx-auto lg:mx-0"> 1535 04 1536 </div> 1537 <h3 class="text-xl font-extrabold text-astral mb-3 text-center lg:text-left">Better Sleep</h3> 1538 <p class="text-sm text-brand-gray-600 leading-relaxed text-center lg:text-left">Stop snoring, 1539 protect 1540 your long-term health, and wake up feeling genuinely refreshed and energized.</p> 1541 </div> 1542 1543 </div> 1544 </div> 1545 1546 </div> 1547 </section> 1548 1549 1550 <!-- ============================================ --> 1551 1552 1553 1554 <!-- ============================================ --> 1555 <!-- SECTION 3: REAL RESULTS (DARK BANNER) --> 1556 <!-- ============================================ --> 1557 1558 <section id="hp-results" class="relative overflow-hidden fade-in"> 1559 <div class="absolute inset-0"> 1560 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/homepage-sleep-study-bg.webp?v=1773365351" alt="Home sleep apnea test with wrist device and specialist report" 1561 class="w-full h-full object-cover" loading="lazy" aria-hidden="true" width="1920" height="600" /> 1562 </div> 1563 <div class="absolute inset-0 bg-astral/70"></div> 1564 <div class="relative z-10 max-w-7xl mx-auto px-5 sm:px-6 lg:px-8 py-16 sm:py-20 md:py-24"> 1565 <div class="max-w-4xl mx-auto text-center"> 1566 <p class="text-xs font-bold tracking-brand uppercase text-blossom mb-3">REAL RESULTS</p> 1567 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white mb-4">See the Hushd Pro Avera in action.</h2> 1568 <p class="text-base sm:text-lg text-white/80 max-w-2xl mx-auto mb-8 leading-relaxed">Watch a real patient review of the Hushd Pro Avera — custom-fitted oral appliance therapy for sleep apnea.</p> 1569 <div class="relative w-full max-w-3xl mx-auto rounded-2xl overflow-hidden shadow-lg" style="aspect-ratio:16/9;"> 1570 <iframe src="https://www.youtube.com/embed/M06_PoulLt8?rel=0&modestbranding=1" title="Hushd Pro Avera Review" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen class="absolute inset-0 w-full h-full"></iframe> 1571 </div> 1572 </div> 1573 </div> 1574 </section> 1575 1576 <!-- ============================================ --> 1577 <!-- SECTION 9: BACKED BY EXPERTS --> 1578 <!-- ============================================ --> 1579 1580 <section class="py-20 sm:py-24 bg-white fade-in"> 1581 <div class="max-w-5xl mx-auto px-5 sm:px-6 lg:px-8"> 1582 <div 1583 class="flex flex-col md:flex-row items-center gap-10 md:gap-16 bg-cloud rounded-3xl p-8 md:p-12 shadow-[0_8px_30px_rgba(0,33,86,0.04)]"> 1584 <div class="w-32 h-32 sm:w-48 sm:h-48 rounded-full overflow-hidden shrink-0 border-4 border-white shadow-lg"> 1585 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Dr_Christopher_Pantin_circle.png?v=1678338761" 1586 alt="Dr. Christopher Pantin" class="w-full h-full object-cover" 1587 loading="lazy" /> 1588 </div> 1589 <div> 1590 <p class="text-xs font-bold tracking-brand uppercase text-blossom mb-3">BACKED BY EXPERTS</p> 1591 <h3 class="text-2xl sm:text-3xl font-extrabold text-astral mb-4">“Untreated sleep apnea isn't just about 1592 snoring, it's a critical health risk. Good Sleep Co. brings clinical-standard care directly into the 1593 patient's bedroom.”</h3> 1594 <p class="font-bold text-astral text-lg">Dr. Christopher Pantin</p> 1595 <p class="text-brand-gray-500 text-sm">Independent Sleep Physician & Clinical Reviewer</p> 1596 </div> 1597 </div> 1598 </div> 1599 </section> 1600 1601 <!-- ============================================ --> 1602 <!-- SECTION 4: BUY SLEEP TEST --> 1603 <!-- ============================================ --> 1604
1605 <section id="hp-buy-test" class="py-16 sm:py-20 bg-cloud fade-in"> 1606 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8"> 1607 <div class="grid lg:grid-cols-2 gap-10 lg:gap-16 items-center"> 1608 1609 <div class="flex justify-center items-center order-2 lg:order-1"> 1610 <div class="relative w-72 h-72 sm:w-80 sm:h-80 md:w-96 md:h-96 flex items-center justify-center"> 1611 <div class="absolute inset-4 sm:inset-6 bg-white rounded-full"></div> 1612 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-device-on-wrist.webp?v=1772167929" 1613 alt="Good Sleep Test device" class="relative z-10 w-full h-full object-contain drop-shadow-lg" loading="lazy" width="600" height="600" /> 1614 </div> 1615 </div> 1616 1617 <div class="order-1 lg:order-2"> 1618 <p class="text-xs font-bold tracking-brand uppercase text-blossom mb-3">DIAGNOSIS</p> 1619 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-astral mb-4">Sleep Test at Home.</h2> 1620 <p class="text-base sm:text-lg text-brand-gray-600 mb-6 leading-relaxed">Medical-grade pulse oximetry. Three 1621 nights of data. Sleep physician-reviewed report. All from your own bed.</p> 1622 <a href="/products/good-sleep-test" data-buy 1623 class="inline-flex items-center gap-2 bg-blossom text-astral font-extrabold text-sm sm:text-base px-6 py-3 rounded-full hover:bg-opacity-80 transition"> 1624 Get Tested — $159 1625 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2"> 1626 <use href="#ico-arrow-right" /> 1627 </svg> 1628 </a> 1629 </div> 1630 1631 </div> 1632 </div> 1633 </section> 1634 1635 <!-- ============================================ --> 1636 <!-- SECTION 5: TREATMENTS COMPARISON --> 1637 <!-- ============================================ --> 1638 1639 <section id="hp-treatments" class="py-16 sm:py-16 bg-white fade-in relative overflow-hidden"> 1640 <div class="max-w-6xl mx-auto px-5 sm:px-6 lg:px-8"> 1641 <div class="text-center mb-12 sm:mb-10"> 1642 <p class="text-xs font-bold tracking-brand uppercase text-blossom mb-3">TREATMENT OPTIONS</p> 1643 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-astral mb-4">A device for every sleeper.</h2> 1644 <p class="text-base sm:text-lg text-brand-gray-600 max-w-2xl mx-auto">Discover our clinically-proven oral 1645 appliance therapy. Comfortable alternatives to CPAP, designed to open your airway.</p> 1646 </div> 1647 1648 <div class="grid md:grid-cols-2 gap-6 sm:gap-8 max-w-4xl mx-auto"> 1649 <!-- OTC Avera --> 1650 <div 1651 class="bg-cloud rounded-3xl p-8 sm:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.04)] flex flex-col relative border-t-8 border-dream"> 1652 <div class="absolute top-6 right-6 z-20"> 1653 <span 1654 class="inline-flex items-center gap-1 bg-white text-astral font-bold text-[10px] uppercase tracking-wider px-3 py-1.5 rounded-full shadow-sm">Over-The-Counter</span> 1655 </div> 1656 <div class="relative z-10 flex flex-col h-full"> 1657 <div class="mb-6 mt-4 flex justify-center drop-shadow-md"> 1658 <img 1659 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/OurTechnology_1HushdAvera_400x400px.webp?v=1773371083" 1660 alt="Hushd Avera" 1661 class="w-48 h-48 sm:w-44 sm:h-44 object-contain pointer-events-none hover:scale-105 transition duration-500 bg-white rounded-2xl"> 1662 </div> 1663 <h3 class="font-extrabold text-3xl text-astral mb-2">Hushd Avera</h3> 1664 <p class="text-blossom font-extrabold text-xl mb-4">$139</p> 1665 <p class="text-brand-gray-600 text-sm leading-relaxed mb-8 flex-grow">A high-quality, adjustable 1666 boil-and-bite device. Perfect for immediate relief from snoring and mild sleep apnea symptoms without a 1667 prescription.</p> 1668 <ul class="space-y-3 mb-8"> 1669 <li class="flex items-start gap-3"> 1670 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1671 stroke-width="2.5"> 1672 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1673 </svg>
1674 <span class="text-sm font-semibold text-astral">No prescription required</span> 1675 </li> 1676 <li class="flex items-start gap-3"> 1677 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1678 stroke-width="2.5"> 1679 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1680 </svg> 1681 <span class="text-sm font-semibold text-astral">Fully adjustable at home</span> 1682 </li> 1683 <li class="flex items-start gap-3"> 1684 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1685 stroke-width="2.5"> 1686 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1687 </svg> 1688 <span class="text-sm font-semibold text-astral">Fast shipping</span> 1689 </li> 1690 </ul> 1691 <a href="/products/hushd-avera" 1692 class="block w-full text-center bg-white text-astral font-extrabold border-2 border-astral/10 text-sm px-6 py-3.5 rounded-full hover:border-astral/30 transition shadow-sm mt-auto hover:scale-[1.02]">Try 1693 Hushd Avera</a> 1694 </div> 1695 </div> 1696 1697 <!-- Pro Avera --> 1698 <div 1699 class="bg-astral rounded-3xl p-8 sm:p-8 shadow-xl flex flex-col relative overflow-hidden border-t-8 border-blossom"> 1700 <div class="absolute inset-0 bg-gradient-to-br from-astral to-[#001536] pointer-events-none"></div> 1701 <div class="absolute top-6 right-6 z-20"> 1702 <span 1703 class="inline-flex items-center gap-1 bg-blossom text-astral font-bold text-[10px] uppercase tracking-wider px-3 py-1.5 rounded-full shadow-sm">Premium 1704 Custom</span> 1705 </div> 1706 <div class="relative z-10 flex flex-col h-full"> 1707 <div class="mb-6 mt-4 flex justify-center drop-shadow-2xl"> 1708 <img 1709 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/OurTechnology_9HushdProAvera_400x400px.webp?v=1773371083" 1710 alt="Hushd Pro Avera" 1711 class="w-48 h-48 sm:w-44 sm:h-44 object-contain pointer-events-none hover:scale-105 transition duration-500 bg-white/10 rounded-2xl"> 1712 </div> 1713 <h3 class="font-extrabold text-3xl text-white mb-2">Hushd Pro Avera</h3> 1714 <p class="text-white/80 font-bold text-sm mb-4">Prescription Required</p> 1715 <p class="text-white/80 text-sm leading-relaxed mb-8 flex-grow">A durable, custom-milled oral appliance 1716 precision-fitted by a partner sleep dentist. TGA listed specifically for the treatment of obstructive 1717 sleep apnea.</p> 1718 <ul class="space-y-3 mb-8"> 1719 <li class="flex items-start gap-3"> 1720 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1721 stroke-width="2.5"> 1722 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1723 </svg> 1724 <span class="text-sm font-semibold text-white">Custom-fitted by a dental professional</span> 1725 </li> 1726 <li class="flex items-start gap-3"> 1727 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1728 stroke-width="2.5"> 1729 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1730 </svg> 1731 <span class="text-sm font-semibold text-white">TGA listed Class II medical device</span> 1732 </li> 1733 <li class="flex items-start gap-3"> 1734 <svg class="w-5 h-5 text-blossom shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1735 stroke-width="2.5"> 1736 <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> 1737 </svg> 1738 <span class="text-sm font-semibold text-white">Maximum comfort for long-term use</span> 1739 </li> 1740 </ul> 1741 <a href="/pages/treatment" 1742 class="block w-full text-center bg-blossom text-astral font-extrabold text-sm px-6 py-3.5 rounded-full hover:bg-white transition shadow-lg mt-auto hover:scale-[1.02]">Find 1743 My Treatment</a> 1744 </div> 1745 </div> 1746 </div> 1747 </div> 1748 </section> 1749 1750 1751 1752 1753 <!-- ============================================ --> 1754 <!-- SECTION 8: PHONE SUPPORT BAR --> 1755 <!-- ============================================ --> 1756 1757 <section id="hp-phone-support" class="bg-astral py-8 sm:py-10 fade-in"> 1758 <div class="max-w-4xl mx-auto px-5 sm:px-6 lg:px-8 text-center"> 1759 <h2 class="text-xl sm:text-2xl font-extrabold text-white mb-4">
1759Have questions? We're here to help.</h2> 1760 <div class="flex flex-col sm:flex-row justify-center gap-4 sm:gap-8"> 1761 <a href="mailto:[email protected]" 1762 class="inline-flex items-center justify-center gap-2 text-white font-bold text-base sm:text-lg hover:text-blossom transition"> 1763 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1764 <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /> 1765 </svg> 1766 [email protected] 1767 </a> 1768 <a href="tel:+61756902029" 1769 class="inline-flex items-center justify-center gap-2 text-white font-bold text-base sm:text-lg hover:text-blossom transition"> 1770 <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2"> 1771 <use href="#ico-phone" /> 1772 </svg> 1773 AU: 07 5690 2029 1774 </a> 1775 </div> 1776 </div> 1777 </section> 1778 1779 1780 <!-- ============================================ --> 1781 <!-- SECTION 9B: WALL OF LOVE (REVIEWS) --> 1782 <!-- ============================================ --> 1783 1784 <section id="hp-reviews" class="py-20 sm:py-24 bg-cloud fade-in"> 1785 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8 text-center"> 1786 1787 <div class="mb-12"> 1788 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-astral mb-4">Real results. Better sleep.</h2> 1789 <div class="flex items-center justify-center gap-3"> 1790 <div class="flex gap-1 bg-white px-3 py-1.5 rounded-full shadow-sm"> 1791 <svg class="w-5 h-5 text-amber-400 fill-current"> 1792 <use href="#ico-star" /> 1793 </svg> 1794 <svg class="w-5 h-5 text-amber-400 fill-current"> 1795 <use href="#ico-star" /> 1796 </svg> 1797 <svg class="w-5 h-5 text-amber-400 fill-current"> 1798 <use href="#ico-star" /> 1799 </svg> 1800 <svg class="w-5 h-5 text-amber-400 fill-current"> 1801 <use href="#ico-star" /> 1802 </svg> 1803 <svg class="w-5 h-5 text-brand-gray-300 fill-current"> 1804 <use href="#ico-star" /> 1805 </svg> 1806 </div> 1807 <p class="text-sm sm:text-base text-brand-gray-600 font-semibold">4.3/5</p> 1808 </div> 1809 </div> 1810 1811 <div class="grid md:grid-cols-3 gap-6 sm:gap-8 text-left"> 1812 <!-- Review 1 --> 1813 <div 1814 class="bg-white rounded-2xl p-6 sm:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)]"> 1815 <div class="flex items-center justify-between mb-4"> 1816 <div class="flex gap-1"> 1817 <svg class="w-4 h-4 text-amber-400 fill-current"> 1818 <use href="#ico-star" /> 1819 </svg> 1820 <svg class="w-4 h-4 text-amber-400 fill-current"> 1821 <use href="#ico-star" /> 1822 </svg> 1823 <svg class="w-4 h-4 text-amber-400 fill-current"> 1824 <use href="#ico-star" /> 1825 </svg> 1826 <svg class="w-4 h-4 text-amber-400 fill-current"> 1827 <use href="#ico-star" /> 1828 </svg> 1829 <svg class="w-4 h-4 text-amber-400 fill-current"> 1830 <use href="#ico-star" /> 1831 </svg> 1832 </div> 1833 </div> 1834 <h4 class="font-extrabold text-astral text-lg mb-2">"Life-changing device"</h4> 1835 <p class="text-brand-gray-600 text-sm leading-relaxed mb-6">"I did the sleep test and found out I had moderate 1836 sleep apnea. The whole process was so easy. I'm now using Hushd Pro and sleeping better than I have in 10 1837 years."</p> 1838 <div class="flex items-center gap-2"> 1839 <p class="font-bold text-astral text-sm">— Jennifer D.</p> 1840 <span class="flex items-center gap-1 text-xs font-bold text-green-600 bg-green-50 px-2 py-0.5 rounded"> 1841 <svg class="w-3 h-3 fill-current" viewBox="0 0 20 20"> 1842 <path fill-rule="evenodd" 1843 d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" 1844 clip-rule="evenodd" /> 1845 </svg> 1846 Verified Buyer 1847 </span> 1848 </div> 1849 </div> 1850 1851 <!-- Review 2 --> 1852 <div 1853 class="bg-white rounded-2xl p-6 sm:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)]"> 1854 <div class="flex items-center justify-between mb-4"> 1855 <div class="flex gap-1"> 1856 <svg class="w-4 h-4 text-amber-400 fill-current"> 1857 <use href="#ico-star" /> 1858 </svg> 1859 <svg class="w-4 h-4 text-amber-400 fill-current"> 1860 <use href="#ico-star" /> 1861 </svg> 1862 <svg class="w-4 h-4 text-amber-400 fill-current"> 1863 <use href="#ico-star" /> 1864 </svg> 1865 <svg class="w-4 h-4 text-amber-400 fill-current"> 1866 <use href="#ico-star" /> 1867 </svg> 1868 <svg class="w-4 h-4 text-amber-400 fill-current"> 1869 <use href="#ico-star" /> 1870 </svg> 1871 </div> 1872 </div> 1873 <h4 class="font-extrabold text-astral text-lg mb-2">"No more CPAP mask"</h4> 1874 <p class="text-brand-gray-600 text-sm leading-relaxed mb-6">"I dragged my feet on treating my apnea because I 1875 couldn't stand the idea of a CPAP. The Avera oral device is so comfortable and my snoring is completely 1876 gone."</p> 1877 <div class="flex items-center gap-2"> 1878 <p class="font-bold text-astral text-sm">— Mark T.</p>
1879 <span class="flex items-center gap-1 text-xs font-bold text-green-600 bg-green-50 px-2 py-0.5 rounded"> 1880 <svg class="w-3 h-3 fill-current" viewBox="0 0 20 20"> 1881 <path fill-rule="evenodd" 1882 d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" 1883 clip-rule="evenodd" /> 1884 </svg> 1885 Verified Buyer 1886 </span> 1887 </div> 1888 </div> 1889 1890 <!-- Review 3 --> 1891 <div 1892 class="bg-white rounded-2xl p-6 sm:p-8 shadow-[0_8px_30px_rgba(0,33,86,0.06)]"> 1893 <div class="flex items-center justify-between mb-4"> 1894 <div class="flex gap-1"> 1895 <svg class="w-4 h-4 text-amber-400 fill-current"> 1896 <use href="#ico-star" /> 1897 </svg> 1898 <svg class="w-4 h-4 text-amber-400 fill-current"> 1899 <use href="#ico-star" /> 1900 </svg> 1901 <svg class="w-4 h-4 text-amber-400 fill-current"> 1902 <use href="#ico-star" /> 1903 </svg> 1904 <svg class="w-4 h-4 text-amber-400 fill-current"> 1905 <use href="#ico-star" /> 1906 </svg> 1907 <svg class="w-4 h-4 text-amber-400 fill-current"> 1908 <use href="#ico-star" /> 1909 </svg> 1910 </div> 1911 </div> 1912 <h4 class="font-extrabold text-astral text-lg mb-2">"So simple and fast"</h4> 1913 <p class="text-brand-gray-600 text-sm leading-relaxed mb-6">"I had my sleep test results in under a week. The 1914 physician's report was clear and easy to understand. Best investment I've made in my health by far."</p> 1915 <div class="flex items-center gap-2"> 1916 <p class="font-bold text-astral text-sm">— Sarah L.</p> 1917 <span class="flex items-center gap-1 text-xs font-bold text-green-600 bg-green-50 px-2 py-0.5 rounded"> 1918 <svg class="w-3 h-3 fill-current" viewBox="0 0 20 20"> 1919 <path fill-rule="evenodd" 1920 d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" 1921 clip-rule="evenodd" /> 1922 </svg> 1923 Verified Buyer 1924 </span> 1925 </div> 1926 </div> 1927 </div> 1928 1929 </div> 1930 </section> 1931 1932 1933 <!-- ============================================ --> 1934 <!-- SECTION 9C: FREQUENTLY ASKED QUESTIONS --> 1935 <!-- ============================================ --> 1936 1937 <section id="hp-faq" class="py-16 sm:py-24 bg-white fade-in"> 1938 <div class="max-w-3xl mx-auto px-5 sm:px-6"> 1939 <div class="text-center mb-10 sm:mb-14"> 1940 <h2 class="text-3xl sm:text-4xl font-extrabold text-astral mb-4">You have questions.<br>We have answers.</h2> 1941 <p class="text-brand-gray-600 text-sm md:text-base">Everything you need to know about testing and treating sleep 1942 apnea from home.</p> 1943 </div> 1944 1945 <div class="space-y-4"> 1946 <!-- FAQ 1 --> 1947 <details 1948 class="group bg-white rounded-2xl shadow-sm [&_summary::-webkit-details-marker]:hidden border border-brand-gray-300 hover:border-astral/30 transition duration-300"> 1949 <summary 1950 class="flex cursor-pointer items-center justify-between gap-1.5 p-5 sm:p-6 text-astral font-extrabold text-sm sm:text-base"> 1951 Is the home sleep test accurate? 1952 <span class="shrink-0 transition duration-300 group-open:-rotate-180"> 1953 <svg class="w-5 h-5 text-blossom" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1954 stroke-width="2.5"> 1955 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 1956 </svg> 1957 </span> 1958 </summary> 1959 <div class="px-5 sm:px-6 pb-5 sm:pb-6 text-sm sm:text-base text-brand-gray-600 leading-relaxed font-light"> 1960 Yes. The Good Sleep Test uses clinical-grade sensors to continuously monitor your blood oxygen, heart rate, 1961 and movement while you sleep. This provides the exact diagnostic data that independent sleep physicians use 1962 to accurately diagnose sleep apnea. 1963 </div> 1964 </details> 1965 1966 <!-- FAQ 2 --> 1967 <details 1968 class="group bg-white rounded-2xl shadow-sm [&_summary::-webkit-details-marker]:hidden border border-brand-gray-300 hover:border-astral/30 transition duration-300"> 1969 <summary 1970 class="flex cursor-pointer items-center justify-between gap-1.5 p-5 sm:p-6 text-astral font-extrabold text-sm sm:text-base"> 1971 Can I really treat sleep apnea without a CPAP machine?
1972 <span class="shrink-0 transition duration-300 group-open:-rotate-180"> 1973 <svg class="w-5 h-5 text-blossom" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1974 stroke-width="2.5"> 1975 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 1976 </svg> 1977 </span> 1978 </summary> 1979 <div class="px-5 sm:px-6 pb-5 sm:pb-6 text-sm sm:text-base text-brand-gray-600 leading-relaxed font-light"> 1980 Absolutely. While CPAP is one option, many patients struggle to adhere to it. For mild to moderate 1981 obstructive sleep apnea, oral appliance therapy (like the Hushd Avera range) is clinically proven to be a 1982 highly effective, comfortable, and portable alternative. 1983 </div> 1984 </details> 1985 1986 <!-- FAQ 3 --> 1987 <details 1988 class="group bg-white rounded-2xl shadow-sm [&_summary::-webkit-details-marker]:hidden border border-brand-gray-300 hover:border-astral/30 transition duration-300"> 1989 <summary 1990 class="flex cursor-pointer items-center justify-between gap-1.5 p-5 sm:p-6 text-astral font-extrabold text-sm sm:text-base"> 1991 Do I need a prescription for Avera? 1992 <span class="shrink-0 transition duration-300 group-open:-rotate-180"> 1993 <svg class="w-5 h-5 text-blossom" fill="none" viewBox="0 0 24 24" stroke="currentColor" 1994 stroke-width="2.5"> 1995 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 1996 </svg> 1997 </span> 1998 </summary> 1999 <div class="px-5 sm:px-6 pb-5 sm:pb-6 text-sm sm:text-base text-brand-gray-600 leading-relaxed font-light"> 2000 The standard Hushd Avera is an over-the-counter device, available without a prescription so you can start 2001 treating your snoring immediately. For our premium, custom-fitted Hushd Pro Avera, you will need to see one 2002 of our partner sleep dentists for assessment and fitting. 2003 </div> 2004 </details> 2005 2006 <!-- FAQ 4 --> 2007 <details 2008 class="group bg-white rounded-2xl shadow-sm [&_summary::-webkit-details-marker]:hidden border border-brand-gray-300 hover:border-astral/30 transition duration-300"> 2009 <summary 2010 class="flex cursor-pointer items-center justify-between gap-1.5 p-5 sm:p-6 text-astral font-extrabold text-sm sm:text-base"> 2011 How long does it take to get my sleep test results? 2012 <span class="shrink-0 transition duration-300 group-open:-rotate-180"> 2013 <svg class="w-5 h-5 text-blossom" fill="none" viewBox="0 0 24 24" stroke="currentColor" 2014 stroke-width="2.5"> 2015 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 2016 </svg> 2017 </span> 2018 </summary> 2019 <div class="px-5 sm:px-6 pb-5 sm:pb-6 text-sm sm:text-base text-brand-gray-600 leading-relaxed font-light"> 2020 Once you complete your 1-night sleep study at home, your data is securely uploaded via the app. An 2021 independent specialist sleep physician will review your data, and your comprehensive results report is 2022 typically available within 3-5 business days. 2023 </div> 2024 </details> 2025 2026 <!-- FAQ 5 --> 2027 <details 2028 class="group bg-white rounded-2xl shadow-sm [&_summary::-webkit-details-marker]:hidden border border-brand-gray-300 hover:border-astral/30 transition duration-300"> 2029 <summary 2030 class="flex cursor-pointer items-center justify-between gap-1.5 p-5 sm:p-6 text-astral font-extrabold text-sm sm:text-base"> 2031 What if I can't sleep with an oral device? 2032 <span class="shrink-0 transition duration-300 group-open:-rotate-180"> 2033 <svg class="w-5 h-5 text-blossom" fill="none" viewBox="0 0 24 24" stroke="currentColor" 2034 stroke-width="2.5"> 2035 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" /> 2036 </svg> 2037 </span> 2038 </summary> 2039 <div class="px-5 sm:px-6 pb-5 sm:pb-6 text-sm sm:text-base text-brand-gray-600 leading-relaxed font-light"> 2040 It is completely normal for any new sleep device to feel a little unusual for the first few nights. Our 2041 devices are specifically engineered to be low-profile and comfortable. Most users adapt within 3-7 nights 2042 and report significantly better sleep overall. 2043 </div> 2044 </details> 2045 </div> 2046 2047 </div> 2048 </section> 2049 2050 2051 <!-- ============================================ --> 2052 <!-- SECTION 10: WHAT WE OFFER â PRODUCT GRID --> 2053 <!-- ============================================ --> 2054 2055 <section id="hp-products" class="py-16 sm:py-20 bg-cloud fade-in"> 2056 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8"> 2057 2058 <div class="text-center mb-10 sm:mb-12"> 2059 <p class="text-xs font-bold tracking-brand uppercase text-blossom mb-3">OUR PRODUCTS</p> 2060 <h2 class="text-3xl sm:text-4xl md:text-5xl font-extrabold text-astral">What We Offer</h2> 2061 </div> 2062 2063 <div class="grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6"> 2064 2065 <!-- Hushd Pro Avera --> 2066 <a href="/pages/contact" 2067 class="group bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,33,86,0.06)] text-center hover:shadow-lg transition overflow-hidden"> 2068 <div class="aspect-square overflow-hidden"> 2069 <img 2070 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/OurTechnology_9HushdProAvera_400x400px.webp?v=1773371083" 2071 alt="Hushd Pro Avera" class="w-full h-full object-cover group-hover:scale-105 transition" loading="lazy" 2072 width="400" height="400" /> 2073 </div> 2074 <div class="p-4 sm:p-5"> 2075 <h3 class="font-extrabold text-astral text-sm sm:text-base">Hushd Pro Avera</h3> 2076 <p class="text-xs text-brand-gray-500 mt-1">Custom oral device</p> 2077 </div> 2078 </a> 2079 2080 <!-- Hushd Avera --> 2081 <a href="/products/hushd-avera" 2082 class="group bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,33,86,0.06)] text-center hover:shadow-lg transition overflow-hidden"> 2083 <div class="aspect-square overflow-hidden"> 2084 <img 2085 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/OurTechnology_1HushdAvera_400x400px.webp?v=1773371083" 2086 alt="Hushd Avera" class="w-full h-full object-cover group-hover:scale-105 transition" loading="lazy" 2087 width="400" height="400" /> 2088 </div> 2089 <div class="p-4 sm:p-5"> 2090 <h3 class="font-extrabold text-astral text-sm sm:text-base">Hushd Avera</h3> 2091 <p class="text-xs text-brand-gray-500 mt-1">Anti-snoring mouthpiece</p> 2092 </div> 2093 </a> 2094 2095 <!-- Good Sleep Test --> 2096 <a href="/products/good-sleep-test" 2097 class="group bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,33,86,0.06)] text-center hover:shadow-lg transition overflow-hidden"> 2098 <div class="aspect-square overflow-hidden"> 2099 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-hero-bg.webp?v=1772167928" 2100 alt="Good Sleep Test" class="w-full h-full object-cover group-hover:scale-105 transition" loading="lazy" 2101 width="400" height="400" /> 2102 </div> 2103 <div class="p-4 sm:p-5"> 2104 <h3 class="font-extrabold text-astral text-sm sm:text-base">Good Sleep Test</h3> 2105 <p class="text-xs text-brand-gray-500 mt-1">At-home sleep study</p> 2106 </div> 2107 </a> 2108 2109 <!-- Hushd Guard --> 2110 <a href="/products/hushd-guard" 2111 class="group bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,33,86,0.06)] text-center hover:shadow-lg transition overflow-hidden"> 2112 <div class="aspect-square overflow-hidden"> 2113 <img 2114 src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/OurTechnology_12HushdProGuard_400x400px.webp?v=1773371083" 2115 alt="Hushd Guard" class="w-full h-full object-cover group-hover:scale-105 transition" loading="lazy" 2116 width="400" height="400" /> 2117 </div> 2118 <div class="p-4 sm:p-5"> 2119 <h3 class="font-extrabold text-astral text-sm sm:text-base">Hushd Guard</h3> 2120 <p class="text-xs text-brand-gray-500 mt-1">Night guard for teeth grinding</p> 2121 </div> 2122 </a> 2123 2124 </div> 2125 </div> 2126 </section> 2127 2128 2129 <!-- ============================================ --> 2130 <!-- FOOTER --> 2131 <!-- ============================================ --> 2132 2133 <footer class="bg-astral text-white py-12 sm:py-16"> 2134 <div class="max-w-7xl mx-auto px-5 sm:px-6 lg:px-8"> 2135 2136 <!-- Newsletter --> 2137 <div class="bg-white/10 rounded-2xl p-6 sm:p-8 max-w-lg mx-auto mb-12 text-center"> 2138 <p class="font-extrabold text-white text-base sm:text-lg mb-1">Stay in the loop</p> 2139 <p class="text-dream text-sm mb-4">Get sleep health tips and product updates. No spam.</p> 2140 <form class="flex flex-col sm:flex-row gap-2" onsubmit="event.preventDefault(); subscribeNewsletter(this);"> 2141 <input type="email" required placeholder="[email protected]" 2142 class="flex-1 px-4 py-2.5 rounded-full border border-white/40 bg-white/15 text-white text-sm placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-blossom focus:border-blossom" /> 2143 <button type="submit" 2144 class="bg-blossom text-astral font-bold text-sm px-5 py-2.5 rounded-full hover:bg-opacity-80 transition shrink-0">Subscribe</button> 2145 </form> 2146 </div> 2147 2148 <!-- Footer Grid --> 2149 <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 ga
2149p-8 mb-10"> 2150 2151 <!-- Brand --> 2152 <div class="col-span-2 md:col-span-1"> 2153 <div class="flex items-center mb-4"> 2154 <img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-logo-navy-pink.webp?v=1772167928" 2155 alt="Good Sleep Co." class="h-8 w-auto brightness-0 invert" width="180" height="36" /> 2156 </div> 2157 <p class="text-dream text-sm leading-relaxed mb-4">From testing to treatment to better sleep.</p> 2158 <!-- Social links --> 2159 <div class="flex gap-3"> 2160 <a href="https://www.facebook.com/GoodSleepCo" target="_blank" rel="noopener" 2161 class="text-dream hover:text-white transition" aria-label="Facebook"> 2162 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> 2163 <path 2164 d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" /> 2165 </svg> 2166 </a> 2167 <a href="https://www.instagram.com/goodsleep_co/" target="_blank" rel="noopener" 2168 class="text-dream hover:text-white transition" aria-label="Instagram"> 2169 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> 2170 <path 2171 d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z" /> 2172 </svg> 2173 </a> 2174 <a href="https://www.linkedin.com/company/good-sleep-co/" target="_blank" rel="noopener" 2175 class="text-dream hover:text-white transition" aria-label="LinkedIn"> 2176 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> 2177 <path 2178 d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" /> 2179 </svg> 2180 </a> 2181 </div> 2182 </div> 2183 2184 <!-- Pages --> 2185 <div> 2186 <h4 class="font-extrabold text-sm mb-3 text-blossom tracking-brand uppercase">Pages</h4> 2187 <ul class="space-y-2 text-sm text-dream"> 2188 <li><a href="/pages/treatment" class="hover:text-white transition">Sleep Apnea</a></li> 2189 <li><a href="/products/good-sleep-test" class="hover:text-white transition">Get Tested</a></li> 2190 <li><a href="/pages/sleep-quiz" class="hover:text-white transition">Diagnosis</a></li> 2191 <li><a href="/collections" class="hover:text-white transition">Products</a></li> 2192 <li><a href="/pages/contact" class="hover:text-white transition">Contact</a></li> 2193 </ul> 2194 </div> 2195 2196 <!-- Support --> 2197 <div> 2198 <h4 class="font-extrabold text-sm mb-3 text-blossom tracking-brand uppercase">Support</h4> 2199 <ul class="space-y-2 text-sm text-dream"> 2200 <li><a href="/pages/faqs" class="hover:text-white transition">FAQs</a></li> 2201 <li><a href="/policies/terms-of-service" class="hover:text-white transition">Terms of Service</a></li> 2202 <li><a href="/policies/shipping-policy" class="hover:text-white transition">Shipping</a></li> 2203 <li><a href="/policies/privacy-policy" class="hover:text-white transition">Privacy Policy</a></li> 2204 <li><a href="/policies/refund-policy" class="hover:text-white transition">Refund Policy</a></li> 2205 </ul> 2206 </div> 2207 2208 <!-- Get in Touch --> 2209 <div class="col-span-2 md:col-span-3 lg:col-span-2"> 2210 <h4 class="font-extrabold text-sm mb-3 text-blossom tracking-brand uppercase">Get in Touch</h4> 2211 <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm text-dream"> 2212 <div> 2213 <p class="font-bold text-white mb-1">Email</p> 2214 <p><a href="mailto:[email protected]" class="hover:text-white transition">[email protected]</a></p> 2215 </div> 2216 <div> 2217 <p class="font-bold text-white mb-1">Australia</p> 2218 <p>07 5690 2029</p> 2219 <p>Gold Coast, QLD</p> 2220 </div> 2221 </div> 2222 </div> 2223 2224 </div> 2225 2226 <div class="border-t border-white/10 pt-6 text-center"> 2227 <p class="text-xs text-dream/50">© 2026 Good Sleep Co. All rights reserved. TGA Registered Medical Device.</p> 2228 </div> 2229 2230 </div> 2231 </footer> 2232 2233 2234<!-- JAVASCRIPT --> 2235 <!-- ============================================ --> 2236 2237
2237<script> 2238 document.documentElement.classList.add('js-ready'); 2239 2240 // ===== HERO CAROUSEL (REMOVED) ===== 2241 2242 2243 // ===== TEST VS TREATMENT TOGGLE ===== 2244 2245 var currentToggle = 'think'; 2246 function setToggle(state) { 2247 if (state === currentToggle) return; 2248 currentToggle = state; 2249 var pill = document.getElementById('toggle-pill'); 2250 var cardThink = document.getElementById('card-think'); 2251 var cardKnow = document.getElementById('card-know'); 2252 2253 if (state === 'know') { 2254 pill.style.transform = 'translateX(calc(100% + 4px))'; 2255 cardThink.style.opacity = '0'; 2256 cardThink.style.transform = 'translateX(-40px)'; 2257 cardThink.style.pointerEvents = 'none'; 2258 2259 cardKnow.style.opacity = '1'; 2260 cardKnow.style.transform = 'translateX(0)'; 2261 cardKnow.style.pointerEvents = 'auto'; 2262 } else { 2263 pill.style.transform = 'translateX(0)'; 2264 cardThink.style.opacity = '1'; 2265 cardThink.style.transform = 'translateX(0)'; 2266 cardThink.style.pointerEvents = 'auto'; 2267 2268 cardKnow.style.opacity = '0'; 2269 cardKnow.style.transform = 'translateX(40px)'; 2270 cardKnow.style.pointerEvents = 'none'; 2271 } 2272 } 2273 2274 function syncCardHeight() { 2275 var thinkEl = document.getElementById('card-think'); 2276 var knowEl = document.getElementById('card-know'); 2277 if (thinkEl && knowEl) { 2278 var wrapper = thinkEl.parentElement; 2279 var h1 = thinkEl.scrollHeight; 2280 var h2 = knowEl.scrollHeight; 2281 wrapper.style.minHeight = Math.max(h1, h2) + 'px'; 2282 } 2283 } 2284 2285 document.addEventListener('DOMContentLoaded', syncCardHeight); 2286 window.addEventListener('resize', syncCardHeight); 2287 2288 2289 // ===== MOBILE NAV TOGGLE ===== 2290 2291 (function () { 2292 var toggle = document.getElementById('menuToggle'); 2293 var nav = document.getElementById('mobileNav'); 2294 var iconOpen = document.getElementById('menuOpen'); 2295 var iconClose = document.getElementById('menuClose'); 2296 2297 if (toggle) { 2298 toggle.addEventListener('click', function () { 2299 var isOpen = nav.classList.toggle('open'); 2300 iconOpen.classList.toggle('hidden', isOpen); 2301 iconClose.classList.toggle('hidden', !isOpen); 2302 }); 2303 } 2304 })(); 2305 2306 2307 // ===== QUICK QUIZ ===== 2308 2309 function selectQuizPill(inputId, value, buttonEl) { 2310 document.getElementById(inputId).value = value; 2311 var buttons = buttonEl.parentElement.querySelectorAll('.quiz-pill'); 2312 buttons.forEach(btn => btn.classList.remove('selected')); 2313 buttonEl.classList.add('selected'); 2314 } 2315 2316 function checkQuizResults() { 2317 var snore = document.getElementById('quizSnore').value; 2318 var tired = document.getElementById('quizTired').value; 2319 var breath = document.getElementById('quizBreath').value; 2320 2321 if (!snore || !tired || !breath) { 2322 alert('Please answer all 3 questions.'); 2323 return; 2324 } 2325 2326 // Inline banner results removed â full STOP-BANG quiz reveals on Check and fires its own 2327 // CompleteRegistration / Lead events; banner-level Lead removed to avoid double-counting. 2328 document.getElementById('quizResults').classList.add('hidden'); 2329 } 2330 2331 2332 // ===== BUY BUTTONS ===== 2333 2334 document.querySelectorAll('[data-buy]').forEach(function (el) { 2335 el.addEventListener('click', function (e) { 2336 e.preventDefault(); 2337 return window.scPageCart.add([{ id: '41438208163979', quantity: 1 }], 'gst', function () { 2338 var atcEid = genEventId('atc'); 2339 if (typeof fbq === 'function') fbq('track', 'AddToCart', { content_name: 'Good Sleep Test', content_ids: ['41438208163979'], content_type: 'product', value: 159, currency: 'AUD' }, {eventID: atcEid}); 2340 if (typeof gtag === 'function') gtag('event', 'add_to_cart', { currency: 'AUD', value: 159, items: [{ item_id: '41438208163979', item_name: 'Good Sleep Test', price: 159 }] }); 2341 dataLayer.push({ event: 'add_to_cart', eventID: atcEid, content_name: 'Good Sleep Test', content_ids: ['41438208163979'], value: 159, currency: 'AUD', fbp: getFbCookie('_fbp'), fbc: getFbCookie('_fbc') }); 2342 }); 2343 }); 2344 }); 2345 2346 document.querySelectorAll('[data-buy-avera]').forEach(function (el) { 2347 el.addEventListener('click', function (e) { 2348 e.preventDefault(); 2349 return window.scPageCart.add([{ id: '42792097382539', quantity: 1 }], 'avera', function () { 2350 var atcEid2 = genEventId('atc'); 2351 if (typeof fbq === 'function') fbq('track', 'AddToCart', { content_name: 'Hushd Avera', content_ids: ['42792097382539'], content_type: 'product', value: 139, currency: 'AUD' }, {eventID: atcEid2}); 2352 if (typeof gtag === 'function') gtag('event', 'add_to_cart', { currency: 'AUD', value: 139, items: [{ item_id: '42792097382539', item_name: 'Hushd Avera', price: 139 }] }); 2353 dataLayer.push({ event: 'add_to_cart', eventID: atcEid2, content_name: 'Hushd Avera', content_ids: ['42792097382539'], value: 139, currency: 'AUD', fbp: getFbCookie('_fbp'), fbc: getFbCookie('_fbc') }); 2354 }); 2355 }); 2356 }); 2357 2358 2359 // ===== RING GAUGE ANIMATION ===== 2360 2361 (function () { 2362 var circumference = 2 * Math.PI * 30; 2363 var section = document.getElementById('clinical-evidence'); 2364 if (!section) return; 2365 var fired = false;
2366 2367 function countUp(el, target, prefix, duration) { 2368 var numSpan = el.querySelector('span'); 2369 if (numSpan) numSpan.style.opacity = '1'; 2370 var start = 0; 2371 var startTime = null; 2372 function step(ts) { 2373 if (!startTime) startTime = ts; 2374 var progress = Math.min((ts - startTime) / duration, 1); 2375 var eased = 1 - Math.pow(1 - progress, 3); 2376 var current = Math.round(eased * target); 2377 if (numSpan) numSpan.textContent = prefix + current; 2378 if (progress < 1) requestAnimationFrame(step); 2379 } 2380 requestAnimationFrame(step); 2381 } 2382 2383 var ringObserver = new IntersectionObserver(function (entries) { 2384 entries.forEach(function (entry) { 2385 if (!entry.isIntersecting || fired) return; 2386 fired = true; 2387 ringObserver.unobserve(section); 2388 2389 var rings = section.querySelectorAll('.ring-gauge-fill[data-target]'); 2390 var nums = section.querySelectorAll('.ring-stat-num[data-count]'); 2391 2392 rings.forEach(function (circle, i) { 2393 var pct = parseInt(circle.getAttribute('data-target'), 10); 2394 var delay = parseInt(circle.getAttribute('data-delay') || '0', 10); 2395 var offset = circumference - (pct / 100) * circumference; 2396 2397 setTimeout(function () { 2398 circle.style.strokeDashoffset = offset; 2399 if (nums[i]) { 2400 var target = parseInt(nums[i].getAttribute('data-count'), 10); 2401 var prefix = nums[i].getAttribute('data-prefix') || ''; 2402 countUp(nums[i], target, prefix, 1400); 2403 } 2404 }, delay); 2405 }); 2406 }); 2407 }, { threshold: 0.3 }); 2408 2409 ringObserver.observe(section); 2410 })(); 2411 2412 2413 // ===== FADE-IN OBSERVER ===== 2414 2415 (function () { 2416 var observer = new IntersectionObserver(function (entries) { 2417 entries.forEach(function (entry) { 2418 if (entry.isIntersecting) { 2419 entry.target.classList.add('visible'); 2420 observer.unobserve(entry.target); 2421 } 2422 }); 2423 }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' }); 2424 2425 document.querySelectorAll('.fade-in').forEach(function (el) { observer.observe(el); }); 2426 })(); 2427 2428 2429 // ===== NEWSLETTER ===== 2430 2431 function subscribeNewsletter(form) { 2432 var email = form.querySelector('input[type="email"]').value; 2433 if (!email) return; 2434 var klaviyoListId = 'WejdXE'; 2435 if (klaviyoListId && typeof fetch === 'function') { 2436 fetch('https://a.klaviyo.com/api/v2/list/' + klaviyoListId + '/subscribe', { 2437 method: 'POST', 2438 headers: { 'Content-Type': 'application/json' }, 2439 body: JSON.stringify({ api_key: 'WscBdf', profiles: [{ email: email }] }) 2440 }).then(function () { 2441 form.innerHTML = '<p class="text-blossom font-bold text-sm">Thanks! You\'re subscribed.</p>'; 2442 }).catch(function () { 2443 form.innerHTML = '<p class="text-blossom font-bold text-sm">Thanks! You\'re subscribed.</p>'; 2444 }); 2445 } else { 2446 form.innerHTML = '<p class="text-blossom font-bold text-sm">Thanks! You\'re subscribed.</p>'; 2447 } 2448 } 2449 2450 2451 // ===== STOP-BANG QUIZ (One-per-screen) ===== 2452 2453 const answers = new Array(8).fill(null); 2454 2455 let currentQ = 0; 2456 2457 let actualBmi = 0; 2458 2459 2460 2461 function quizAnswer(index, value) { 2462 2463 answers[index] = value; 2464 2465 if (index === 7) { showResults(); return; } 2466 2467 quizGoTo(index + 1); 2468 2469 } 2470 2471 2472 2473 function quizGoTo(q) { 2474 2475 document.querySelectorAll('.quiz-q').forEach(el => el.classList.add('hidden')); 2476 2477 document.getElementById(`q${q}`).classList.remove('hidden'); 2478 2479 currentQ = q; 2480 2481 document.getElementById('fquizProgress').style.width = `${((q + 1) / 8) * 100}%`; 2482 2483 document.getElementById('fquizCounter').textContent = `${q + 1} / 8`; 2484 2485 document.getElementById('fquizBack').style.visibility = q > 0 ? 'visible' : 'hidden'; 2486 2487 document.getElementById('quizFullWrapper').scrollIntoView({ behavior: 'smooth', block: 'start' }); 2488 2489 } 2490 2491 2492 2493 function quizPrev() { 2494 2495 if (currentQ > 0) quizGoTo(currentQ - 1); 2496 2497 } 2498 2499 2500 2501 // ===== BMI Calculator (Q4) ===== 2502 2503 let bmiUnit = 'metric'; 2504 2505 2506 2507 function setBmiUnit(unit) { 2508 2509 bmiUnit = unit; 2510 2511 const isMetric = unit === 'metric'; 2512 2513 document.getElementById('bmiMetric').classList.toggle('hidden', !isMetric); 2514 2515 document.getElementById('bmiImperial').classList.toggle('hidden', isMetric); 2516 2517 [['unitMetric', isMetric], ['unitImperial', !isMetric]].forEac
2517h(([id, active]) => { 2518 2519 const el = document.getElementById(id); 2520 2521 el.classList.toggle('bg-astral', active); 2522 2523 el.classList.toggle('text-white', active); 2524 2525 el.classList.toggle('text-brand-gray-500', !active); 2526 2527 }); 2528 2529 calcBmi(); 2530 2531 } 2532 2533 2534 2535 function calcBmi() { 2536 2537 let bmi = 0; 2538 2539 if (bmiUnit === 'metric') { 2540 2541 const cm = parseFloat(document.getElementById('bmiCm').value); 2542 2543 const kg = parseFloat(document.getElementById('bmiKg').value); 2544 2545 if (cm > 0 && kg > 0) bmi = kg / ((cm / 100) ** 2); 2546 2547 } else { 2548 2549 const ft = parseFloat(document.getElementById('bmiFt').value) || 0; 2550 2551 const inches = parseFloat(document.getElementById('bmiIn').value) || 0; 2552 2553 const lbs = parseFloat(document.getElementById('bmiLbs').value); 2554 2555 const totalIn = ft * 12 + inches; 2556 2557 if (totalIn > 0 && lbs > 0) bmi = (lbs * 703) / (totalIn ** 2); 2558 2559 } 2560 2561 const btn = document.getElementById('bmiContinue'); 2562 2563 const valid = bmi > 0; 2564 2565 btn.disabled = !valid; 2566 2567 btn.classList.toggle('opacity-40', !valid); 2568 2569 btn.classList.toggle('cursor-not-allowed', !valid); 2570 2571 btn.classList.toggle('hover:bg-opacity-80', valid); 2572 2573 return bmi; 2574 2575 } 2576 2577 2578 2579 function submitBmi() { 2580 2581 const bmi = calcBmi(); 2582 2583 if (bmi > 0) { 2584 2585 actualBmi = Math.round(bmi * 10) / 10; 2586 2587 quizAnswer(4, bmi >= 35); 2588 2589 } 2590 2591 } 2592 2593 2594 2595 function showResults() { 2596 2597 const score = answers.filter(a => a === true).length; 2598 2599 document.getElementById('fquizForm').style.display = 'none'; 2600 2601 document.getElementById('fquizResults').classList.remove('hidden'); 2602 2603 document.querySelectorAll('.quiz-score').forEach(el => el.textContent = score); 2604 2605 2606 2607 // Hide all result panes first 2608 document.querySelectorAll('.result-card').forEach(function (el) { el.classList.remove('active'); }); 2609 2610 let resultId = 'resultHigh'; 2611 2612 // Snoring-only: snore=Yes, tired=No, observed apnea=No -> pivot to Avera 2613 if (answers[0] === true && answers[1] === false && answers[2] === false) { 2614 resultId = 'resultSnore'; 2615 } else if (score <= 2) { 2616 resultId = 'resultLow'; 2617 } else if (score <= 4) { 2618 resultId = 'resultMid'; 2619 } 2620 2621 document.getElementById(resultId).classList.add('active'); 2622 2623 2624 2625 document.getElementById('fquizResults').scrollIntoView({ behavior: 'smooth', block: 'start' }); 2626 2627 // Show optional (non-gating) email capture after a short delay 2628 setTimeout(() => { 2629 const capture = document.getElementById('postResultsCapture'); 2630 if (capture) capture.classList.remove('hidden'); 2631 }, 1500); 2632 2633 // Fire tracking events (previously gated behind email) 2634 // score already declared above in this function 2635 var risk = 'High'; 2636 if (score <= 2) risk = 'Low'; 2637 else if (score <= 4) risk = 'Intermediate'; 2638 if (typeof gtag === 'function') gtag('event', 'quiz_complete', { event_category: 'quiz', event_label: risk + ' risk', value: score }); 2639 if (window.posthog && typeof posthog.capture === 'function') posthog.capture('quiz_completed', { page: 'homepage', score: score, risk_level: risk }); 2640 var eid = genEventId('cr'); 2641 if (typeof fbq !== 'undefined') fbq('track', 'CompleteRegistration', { content_name: 'STOP-BANG Quiz', value: score, status: risk }, { eventID: eid }); 2642 dataLayer.push({ event: 'CompleteRegistration', eventID: eid, content_name: 'STOP-BANG Quiz', value: score, status: risk, fbp: getFbCookie('_fbp'), fbc: getFbCookie('_fbc') }); 2643 } 2644 2645 2646 2647 function unlockResults() { 2648 2649 const firstName = document.getElementById('gateFirstName').value.trim(); 2650 2651 const lastName = document.getElementById('gateLastName').value.trim(); 2652 2653 const email = document.getElementById('gateEmail').value.trim(); 2654 2655 if (!firstName || !lastName || !email) return; 2656 2657 2658 2659 document.getElementById('emailGate').style.display = 'none'; 2660 2661 document.getElementById('resultsContent').classList.add('unlocked'); 2662 2663 document.getElementById('fquizResults').scrollIntoView({ behavior: 'smooth', block: 'center' }); 2664 2665 2666 2667 const score = answers.filter(a => a === true).length; 2668 2669 let risk = 'High'; 2670 2671 if (score <= 2) risk = 'Low'; 2672 2673 else if (score <= 4) risk = 'Intermediate'; 2674 2675 const yn = (v) => { if (v === true) return 'Yes'; if (v === false) return 'No'; return ''; }; 2676 2677 2678 2679 if (typeof gtag === 'function') gtag('event', 'generate_lead', { event_category: 'quiz', event_label: risk + ' r
2679isk', value: score }); 2680 if (window.posthog && typeof posthog.capture === 'function') posthog.capture('quiz_email_submitted', { page: 'homepage' }); 2681 2682 var eid = genEventId('lead'); 2683 if (typeof fbq !== 'undefined') { 2684 fbq('init', '215594561324661', { em: email.toLowerCase(), fn: firstName.toLowerCase(), ln: lastName.toLowerCase() }); 2685 fbq('track', 'Lead', { content_name: 'STOP-BANG Quiz', value: score }, { eventID: eid }); 2686 } 2687 dataLayer.push({ event: 'Lead', eventID: eid, content_name: 'STOP-BANG Quiz', value: score, email: email, fn: firstName, ln: lastName, fbp: getFbCookie('_fbp'), fbc: getFbCookie('_fbc') }); 2688 2689 2690 2691 const payload = { 2692 2693 firstName, lastName, email, score, risk, source: 'Patient Homepage', 2694 2695 snore: yn(answers[0]), 2696 2697 tired: yn(answers[1]), 2698 2699 stopBreathing: yn(answers[2]), 2700 2701 hbp: yn(answers[3]), 2702 2703 bmi: yn(answers[4]), 2704 2705 bmiActual: actualBmi || '', 2706 2707 overFifty: yn(answers[5]), 2708 2709 neckCircumference: yn(answers[6]), 2710 2711 male: yn(answers[7]) 2712 2713 }; 2714 2715 const opts = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }; 2716 2717 fetch('https://n8n.altoraa.com/webhook/quiz-lead', opts).catch(err => console.error('n8n lead error:', err)); 2718 2719 // Zapier forwarding now handled server-side by n8n (CORS preflight was blocking browser-side fetch) 2720 2721 } 2722 2723 2724 2725 // ===== POST-RESULTS EMAIL CAPTURE (Optional, non-gating) ===== 2726 function submitPostResults() { 2727 const firstName = document.getElementById('postFirstName').value.trim(); 2728 const lastName = document.getElementById('postLastName').value.trim(); 2729 const email = document.getElementById('postEmail').value.trim(); 2730 if (!firstName || !lastName || !email) return; 2731 2732 const score = answers.filter(a => a === true).length; 2733 let risk = 'High'; 2734 if (score <= 2) risk = 'Low'; 2735 else if (score <= 4) risk = 'Intermediate'; 2736 const yn = (v) => { if (v === true) return 'Yes'; if (v === false) return 'No'; return ''; }; 2737 2738 if (typeof gtag === 'function') gtag('event', 'generate_lead', { event_category: 'quiz', event_label: risk + ' risk', value: score }); 2739 if (window.posthog && typeof posthog.capture === 'function') posthog.capture('quiz_email_submitted', { page: 'homepage' }); 2740 var eid2 = genEventId('lead'); 2741 if (typeof fbq !== 'undefined') { 2742 fbq('init', '215594561324661', { em: email.toLowerCase(), fn: firstName.toLowerCase(), ln: lastName.toLowerCase() }); 2743 fbq('track', 'Lead', { content_name: 'STOP-BANG Quiz', value: score }, { eventID: eid2 }); 2744 } 2745 dataLayer.push({ event: 'Lead', eventID: eid2, content_name: 'STOP-BANG Quiz', value: score, email: email, fn: firstName, ln: lastName, fbp: getFbCookie('_fbp'), fbc: getFbCookie('_fbc') }); 2746 2747 const payload = { 2748 firstName, lastName, email, score, risk, source: 'Patient Homepage', 2749 snore: yn(answers[0]), tired: yn(answers[1]), stopBreathing: yn(answers[2]), 2750 hbp: yn(answers[3]), bmi: yn(answers[4]), bmiActual: actualBmi || '', 2751 overFifty: yn(answers[5]), neckCircumference: yn(answers[6]), male: yn(answers[7]) 2752 }; 2753 fetch('https://n8n.altoraa.com/webhook/quiz-lead', { 2754 method: 'POST', headers: { 'Content-Type': 'application/json' }, 2755 body: JSON.stringify(payload) 2756 }).catch(err => console.error('n8n lead error:', err)); 2757 2758 // Replace form with thank-you 2759 const captureDiv = document.getElementById('postResultsCapture'); 2760 captureDiv.innerHTML = '<div class="bg-dream-50 border border-dream-200 rounded-2xl p-6 text-center"><svg class="w-10 h-10 text-dream mx-auto mb-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg><h4 class="text-lg font-extrabold text-astral mb-1">Check your inbox!</h4><p class="text-sm text-brand-gray-500">Your personalised Starter Guide is on its way.</p></div>'; 2761 } 2762 2763 // ===== HAND-OFF: banner 3-Q quiz -> full STOP-BANG quiz ===== 2764 (function () { 2765 var btn = document.getElementById('quizCheck'); 2766 if (!btn) return; 2767 btn.addEventListener('click', function () { 2768 setTimeout(function () { 2769 var s = document.getElementById('quizSnore').value; 2770 var t = document.getElementById('quizTired').value; 2771 var b = document.getElementById('quizBreath').value; 2772 if (!s || !t || !b) return; 2773 // Banner Snore/Tired/Breath -> STOP-BANG q0/q1/q2 2774 answers[0] = (s === 'yes');
2775 answers[1] = (t === 'yes'); 2776 answers[2] = (b === 'yes'); 2777 // Reveal the previously-hidden full-quiz section 2778 var section = document.getElementById('quizFullWrapper'); 2779 if (section) section.style.display = 'block'; 2780 // Jump full quiz to Q3 (HBP) 2781 document.querySelectorAll('#quizFullWrapper .quiz-q').forEach(function (el) { el.classList.add('hidden'); }); 2782 var q3el = document.getElementById('q3'); 2783 if (q3el) q3el.classList.remove('hidden'); 2784 currentQ = 3; 2785 var prog = document.getElementById('fquizProgress'); 2786 if (prog) prog.style.width = '50%'; 2787 var ctr = document.getElementById('fquizCounter'); 2788 if (ctr) ctr.textContent = '4 / 8'; 2789 var back = document.getElementById('fquizBack'); 2790 if (back) back.style.visibility = 'visible'; 2791 // Reveal a hint that the full quiz is below 2792 var hint = document.getElementById('fquizHint'); 2793 if (hint) hint.classList.remove('hidden'); 2794 // Scroll the newly-revealed full quiz into view 2795 if (section) { 2796 setTimeout(function () { section.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 150); 2797 } 2798 }, 250); 2799 }); 2800 })(); 2801 2802 </script>
2802 2803 2804 <!-- ============================================ --> 2805 <!-- POSTHOG CUSTOM EVENT TRACKING --> 2806 <!-- ============================================ --> 2807
2807<script> 2808 window.addEventListener('load', function() { 2809 if (typeof posthog === 'undefined') return; 2810 var PAGE = 'homepage'; 2811 2812 // --- TIER 1: Section Visibility --- 2813 var sectionMap = { 2814 'hero-banner': 'hero', 2815 'clinical-evidence': 'clinical_evidence', 2816 'test-vs-treatment': 'test_vs_treatment', 2817 'hp-trusted-by': 'trusted_by', 2818 'quiz': 'quiz', 2819 'hp-journey': 'journey', 2820 'hp-results': 'results', 2821 'hp-buy-test': 'buy_test', 2822 'hp-treatments': 'treatments', 2823 'hp-phone-support': 'phone_support', 2824 'hp-reviews': 'reviews', 2825 'hp-faq': 'faq', 2826 'hp-products': 'products' 2827 }; 2828 var seen = {}; 2829 if ('IntersectionObserver' in window) { 2830 var obs = new IntersectionObserver(function(entries) { 2831 entries.forEach(function(e) { 2832 if (e.isIntersecting && !seen[e.target.id]) { 2833 seen[e.target.id] = true; 2834 posthog.capture('section_viewed', { section: sectionMap[e.target.id], page: PAGE }); 2835 } 2836 }); 2837 }, { threshold: 0.15 }); 2838 Object.keys(sectionMap).forEach(function(id) { 2839 var el = document.getElementById(id); 2840 if (el) obs.observe(el); 2841 }); 2842 } 2843 2844 // --- TIER 2: Buy Button --- 2845 var origHeaderBuyNow = window.headerBuyNow; 2846 if (typeof origHeaderBuyNow === 'function') { 2847 window.headerBuyNow = function(variantId) { 2848 posthog.capture('buy_button_clicked', { page: PAGE, variant_id: String(variantId), location: 'header' }); 2849 return origHeaderBuyNow(variantId); 2850 }; 2851 } 2852 document.querySelectorAll('[data-buy]').forEach(function(btn) { 2853 btn.addEventListener('click', function() { 2854 posthog.capture('buy_button_clicked', { 2855 page: PAGE, 2856 variant_id: btn.getAttribute('data-buy') || '', 2857 location: btn.closest('#hp-buy-test') ? 'buy_test_section' : 'other' 2858 }); 2859 }); 2860 }); 2861 2862 // --- TIER 2: FAQ Clicks (details/summary) --- 2863 document.querySelectorAll('details summary').forEach(function(summary) { 2864 summary.addEventListener('click', function() { 2865 var question = summary.textContent.trim().replace(/\s+/g, ' '); 2866 posthog.capture('faq_question_clicked', { page: PAGE, question: question }); 2867 }); 2868 }); 2869 2870 // --- TIER 3: Scroll Depth --- 2871 var depthFired = {}; 2872 var thresholds = [25, 50, 75, 100]; 2873 window.addEventListener('scroll', function() { 2874 var scrollPct = Math.round((window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100); 2875 thresholds.forEach(function(t) { 2876 if (scrollPct >= t && !depthFired[t]) { 2877 depthFired[t] = true; 2878 posthog.capture('scroll_depth', { page: PAGE, percent: t }); 2879 } 2880 }); 2881 }, { passive: true }); 2882 2883 // --- TIER 3: Time on Page --- 2884 [15, 30, 60, 120].forEach(function(sec) { 2885 setTimeout(function() { 2886 posthog.capture('time_on_page', { page: PAGE, seconds: sec }); 2887 }, sec * 1000); 2888 }); 2889 }); 2890 </script>
2890 2891 2892<!-- âââ UNIFIED SIDE CART DRAWER (side-cart-v2) âââ --> 2893<style> 2894.sc-overlay { 2895 position: fixed; inset: 0; background: rgba(0,0,0,0); z-index: 9998; 2896 pointer-events: none; transition: background 0.2s ease; 2897 } 2898 .sc-overlay.sc-open { background: rgba(0,0,0,0.5); pointer-events: auto; } 2899 .sc-drawer { 2900 position: fixed; top: 0; right: 0; bottom: 0; width: 420px; max-width: 92vw; 2901 background: #fff; z-index: 9999; transform: translateX(100%); 2902 transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1); 2903 display: flex; flex-direction: column; font-family: 'Plus Jakarta Sans', system-ui, sans-serif; 2904 box-shadow: -8px 0 30px rgba(0,0,0,0.15); 2905 } 2906 .sc-drawer.sc-open { transform: translateX(0); } 2907 .sc-header { 2908 display: flex; align-items: center; justify-content: space-between; 2909 padding: 18px 24px; border-bottom: 1px solid #e5e7eb; background: #002156; 2910 } 2911 .sc-header h2 { font-size: 16px; font-weight: 700; color: #fff; margin: 0; letter-spacing: -0.3px; } 2912 .sc-close { 2913 background: none; border: none; cursor: pointer; padding: 4px; 2914 color: rgba(255,255,255,0.6); transition: color 0.2s; 2915 } 2916 .sc-close:hover { color: #fff; } 2917 .sc-close svg { width: 22px; height: 22px; } 2918 .sc-shipping { padding: 14px 24px; background: #f8fafc; border-bottom: 1px solid #e5e7eb; } 2919 .sc-shipping-text { 2920 font-size: 13px; font-weight: 600; color: #002156; margin-bottom: 8px; 2921 display: flex; align-items: center; gap: 6px; 2922 } 2923 .sc-shipping-text .sc-truck { font-size: 16px; } 2924 .sc-shipping-text .sc-amount { color: #16a34a; font-weight: 800; } 2925 .sc-shipping-unlocked .sc-shipping-text { color: #16a34a; } 2926 .sc-bar-track { height: 8px; background: #e5e7eb; border-radius: 100px; overflow: hidden; position: relative; } 2927 .sc-bar-fill { 2928 height: 100%; border-radius: 100px; 2929 background: linear-gradient(90deg, #002156, #16a34a); 2930 width: 0%; transition: width 1.2s cubic-bezier(0.34, 1.56, 0.64, 1); 2931 } 2932 .sc-bar-fill.sc-full { background: linear-gradient(90deg, #16a34a, #22c55e); } 2933 .sc-bar-shimmer { 2934 position: absolute; top: 0; left: -100%; width: 100%; height: 100%; 2935 background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); 2936 animation: sc-shimmer 2s ease-in-out infinite; 2937 } 2938 @keyframes sc-shimmer { 0% { left: -100%; } 100% { left: 100%; } } 2939 .sc-items { flex: 1; overflow-y: auto; padding: 20px 24px; } 2940 .sc-item { display: flex; gap: 14px; padding: 16px 0; border-bottom: 1px solid #f1f3f5; } 2941 .sc-item:last-child { border-bottom: none; } 2942 .sc-item-img { width: 72px; height: 72px; border-radius: 10px; object-fit: cover; background: #f4efe9; flex-shrink: 0; } 2943 .sc-item-info { flex: 1; display: flex; flex-direction: column; justify-content: center; } 2944 .sc-item-name { font-size: 14px; font-weight: 700; color: #1a1a2e; margin-bottom: 2px; } 2945 .sc-item-variant { font-size: 12px; color: #6b7280; margin-bottom: 4px; } 2946 .sc-item-price { font-size: 15px; font-weight: 800; color: #002156; } 2947 .sc-item-row { 2948 display: flex; align-items: center; justify-content: space-between; margin-top: 4px; 2949 } 2950 .sc-qty { 2951 display: flex; align-items: center; gap: 0; border: 1.5px solid #e5e7eb; border-radius: 8px; overflow: hidden; 2952 } 2953 .sc-qty-btn { 2954 width: 32px; height: 32px; border: none; background: #f9fafb; cursor: pointer; 2955 display: flex; align-items: center; justify-content: center; color: #374151; 2956 transition: all 0.15s; 2957 } 2958 .sc-qty-btn:hover { background: #f3f4f6; color: #002156; } 2959 .sc-qty-btn:active { background: #e5e7eb; } 2960 .sc-qty-btn.sc-qty-disabled { opacity: 0.3; cursor: not-allowed; } 2961 .sc-qty-btn:disabled, .sc-flavour-select:disabled { opacity: 0.5; cursor: wait; } 2962 .sc-server-rendered .sc-items > .sc-item, .sc-server-rendered #scSubOffer, .sc-server-rendered #scMagSubOffer { display: none !important; } 2963 .sc-view-unconfirmed [data-sc-server-lines], .sc-view-unconfirmed .sc-items > .sc-item, .sc-view-unconfirmed #scSubOffer, .sc-view-unconfirmed #scMagSubOffer, .sc-view-unconfirmed #scSubtotalWas, .sc-view-unconfirmed #scSaveBadge { display: none !important; } 2964 .sc-line-plan { margin-top: 8px; padding: 8px; border: 1px solid #86efac; border-radius: 6px; background: #f0fdf4; color: #002156; font: inherit; cursor: pointer; } 2965 .sc-line-plan:disabled { opacity: 0.5; cursor: wait; } 2966 .sc-line-original { font-size: 12px; color: #6b7280; } 2967 .sc-empty { padding: 12px 0; color: #6b7280; } 2968 [data-sc-line-key][aria-busy="true"] [data-sc-line-pending] { display: inline !important; } 2969 .sc-qty-num { 2970 width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; 2971 font-size: 13px; font-weight: 700; color: #002156; background: #fff; 2972 border-left: 1.5px solid #e5e7eb; border-right: 1.5px solid #e5e7eb; 2973 } 2974 .sc-upsell { 2975 margin: 4px 0 8px; padding: 16px; border-radius: 12px; 2976 background: linear-gradient(135deg, #f8fafc, #f0fdf4); 2977 border: 1.5px dashed #86efac; position: relative; overflow: hidden; 2978 } 2979 .sc-upsell-badge { 2980 position: absolute; top: 0; right: 0; background: #16a34a; color: #fff; 2981 font-size: 10px; font-weight: 700; padding: 4px 12px 4px 16px; 2982 border-radius: 0 0 0 12px; text-transform: uppercase; letter-spacing: 0.05em; 2983 } 2984 .sc-upsell-top { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; } 2985 .sc-upsell-img { width: 56px; height: 56px; border-radius: 8px; object-fit: cover; background: #f4efe9; flex-shrink: 0; } 2986 .sc-upsell-info { flex: 1; } 2987 .sc-upsell-name { font-size: 13px; font-weight: 700; color: #1a1a2e; } 2988 .sc-upsell-price { font-size: 13px; font-weight: 600; color: #16a34a; } 2989 .sc-upsell-why { font-size: 11px; color: #6b7280; margin-top: 2px; line-height: 1.4; } 2990 .sc-upsell-btn { 2991 width: 100%; padding: 10px; border: none; border-radius: 8px; cursor: pointer; 2992 font-size: 13px; font-weight: 700; letter-spacing: -0.2px; 2993 background: #002156; color: #fff; transition: all 0.2s; 2994 display: flex; align-items: center; justify-content: center; gap: 6px; 2995 } 2996 .sc-upsell-btn:hover { background: #001638; transform: translateY(-1px); } 2997 .sc-upsell-btn.sc-added { background: #16a34a; pointer-events: none; } 2998 .sc-flavour-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; } 2999 .sc-flavour-label { font-size: 12px; font-weight: 600; color: #374151; flex-shrink: 0; } 3000 .sc-flavour-select { 3001 flex: 1; font-size: 13px; font-weight: 600; color: #111827; padding: 8px 28px 8px 10px; 3002 border: 1px solid #d1d5db; border-radius: 8px; background-color: #fff; cursor: pointer; 3003 -webkit-appearance: none; appearance: none; 3004 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.5'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); 3005 background-repeat: no-repeat; background-position: right 10px center; 3006 } 3007 .sc-flavour-select:focus { outline: none; border-color: #16a34a; box-shadow: 0 0 0 2px rgba(22,163,74,0.15); } 3008 .sc-footer { padding: 18px 24px 24px; border-top: 1px solid #e5e7eb; background: #fafafa; } 3009 .sc-subtotal { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; } 3010 .sc-subtotal-right { display: flex; align-items: center; gap: 8px; } 3011 .sc-save-badge { display: none; background: #FCD34D; color: #002156; font-size: 12px; 3012 font-weight: 800; padding: 3px 9px; border-radius: 999px; white-space: nowrap; } 3013 .sc-save-badge.sc-show { display: inline-block; } 3014 .sc-subtotal-was { display: none; font-size: 15px; font-weight: 600; color: #9ca3af; 3015 text-decoration: line-through; white-space: nowrap; } 3016 .sc-subtotal-was.sc-show { display: inline; } 3017 .sc-subtotal-label { font-size: 14px; font-weight: 600; color: #6b7280; } 3018 .sc-subtotal-price { font-size: 22px; font-weight: 800; color: #002156; } 3019 .sc-checkout-btn { 3020 width: 100%; padding: 16px; border: none; border-radius: 12px; cursor: pointer; 3021 font-size: 16px; font-weight: 800; letter-spacing: -0.3px; 3022 background: #ECAFAC; color: #002156; transition: all 0.2s; position: relative; overflow: hidden; 3023 } 3024 .sc-checkout-btn:hover { background: #e89e9a; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(236,175,172,0.4); } 3025 .sc-checkout-btn:active { transform: translateY(0); } 3026 .sc-secure { 3027 display: flex; align-items: center; justify-content: center; gap: 6px; 3028 margin-top: 10px; font-size: 11px; color: #9ca3af; font-weight: 500; 3029 } 3030 .sc-secure svg { width: 13px; height: 13px; } 3031 .sc-upsell { animation: sc-fadeUp 0.2s ease both; } 3032 @keyframes sc-fadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } 3033 .sc-bar-pulse { animation: sc-pulse 0.6s ease; } 3034 @keyframes sc-pulse { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(1.8); } } 3035 @media (prefers-reduced-motion: reduce) { 3036 .sc-overlay, .sc-drawer, .sc-upsell { transition: none !important; } 3037 .sc-upsell, .sc-bar-pulse { animation: none !important; } 3038 } 3039 .sc-fab { position: fixed; right: 16px; bottom: 90px; z-index: 9997; width: 56px; height: 56px; border-radius: 50%; border: none; cursor: pointer; background: #ECAFAC; color: #002156; display: none; align-items: center; justify-content: center; box-shadow: 0 6px 20px rgba(0,33,86,0.28); transition: transform 0.2s ease, box-shadow 0.2s ease; } 3040 .sc-fab.sc-fab-show { display: flex; animation: sc-fab-in 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); } 3041 .sc-fab:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0,33,86,0.34); } 3042 .sc-fab svg { width: 26px;
3042 height: 26px; } 3043 .sc-fab-count { position: absolute; top: -4px; right: -4px; min-width: 22px; height: 22px; padding: 0 5px; border-radius: 999px; background: #002156; color: #fff; font-size: 12px; font-weight: 800; display: flex; align-items: center; justify-content: center; border: 2px solid #fff; } 3044 .sc-item-remove { background: none; border: none; cursor: pointer; padding: 6px 0 6px 6px; color: #9ca3af; align-self: flex-start; line-height: 0; } 3045 .sc-item-remove:hover { color: #dc2626; } 3046 .sc-item-remove svg { width: 16px; height: 16px; } 3047 .sc-item-remove:disabled { opacity: 0.4; pointer-events: none; } 3048 .sc-item-soldout .sc-item-img { opacity: 0.45; filter: grayscale(1); } 3049 .sc-item-soldout .sc-item-name { color: #6b7280; } 3050 .sc-soldout-badge { display: inline-block; margin-left: 6px; font-size: 10px; font-weight: 800; letter-spacing: 0.02em; color: #991b1b; background: #fef2f2; border: 1px solid #fecaca; border-radius: 999px; padding: 1px 8px; vertical-align: 1px; } 3051 .sc-checkout-btn.sc-blocked { background: #9ca3af !important; cursor: not-allowed; } 3052 .sc-note { margin: 0 0 10px; padding: 10px 12px; border-radius: 10px; background: #fff7ed; border: 1px solid #fdba74; color: #7c2d12; font-size: 13px; line-height: 1.4; } 3053 .sc-note-btn { display: inline-block; white-space: nowrap; margin-left: 8px; padding: 4px 10px; border-radius: 999px; border: 1px solid #7c2d12; background: #fff; color: #7c2d12; font-weight: 700; font-size: 12px; cursor: pointer; } 3054 .sc-checking-out .sc-qty-btn, .sc-checking-out .sc-upsell-btn, .sc-checking-out .sc-item-remove, .sc-checking-out .sc-flavour-select, .sc-checking-out [data-sc-action] { pointer-events: none; opacity: 0.55; } 3055 @keyframes sc-fab-in { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(1); } } 3056 @media (min-width: 1024px) { .sc-fab { right: 28px; bottom: 28px; } } 3057 3058 /* ===== footer rating row (both arms) ===== */ 3059 .sc-rating { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 12px; } 3060 .sc-stars { display: inline-flex; gap: 1px; } 3061 .sc-stars svg { width: 15px; height: 15px; fill: #f59e0b; } 3062 .sc-rating-text { font-size: 12px; color: #6b7280; font-weight: 500; } 3063 .sc-rating-text strong { color: #002156; font-weight: 700; } 3064 /* ===== mobile improvements (both arms) ===== */ 3065 @media (max-width: 480px) { 3066 .sc-drawer { width: 100vw; max-width: 100vw; } 3067 .sc-qty-btn { width: 44px; height: 44px; } 3068 .sc-qty-num { width: 40px; height: 44px; font-size: 15px; } 3069 .sc-close { padding: 12px; margin: -8px -8px -8px 0; } 3070 .sc-close svg { width: 24px; height: 24px; } 3071 .sc-item-remove { padding: 12px 0 12px 12px; } 3072 .sc-footer { padding-bottom: calc(24px + env(safe-area-inset-bottom)); } 3073 .sc-checkout-btn { padding: 18px; font-size: 17px; } 3074 } 3075 /* ===== A/B arm B only: horizontal upsell rail (mobile) ===== */ 3076 @media (max-width: 480px) { 3077 .sc-drawer.sc-rail .sc-upsell-rail { display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; 3078 -webkit-overflow-scrolling: touch; padding: 4px 24px 12px 2px; margin-right: -24px; scrollbar-width: none; } 3079 .sc-drawer.sc-rail .sc-upsell-rail::-webkit-scrollbar { display: none; } 3080 .sc-drawer.sc-rail .sc-upsell-rail .sc-upsell { flex: 0 0 80%; scroll-snap-align: start; margin: 0; } 3081 .sc-drawer.sc-rail .sc-upsell-rail .sc-upsell:only-child { flex-basis: 100%; } 3082 .sc-drawer.sc-rail .sc-upsell-rail.sc-rail-solo .sc-upsell { flex: 0 0 100%; } 3083 .sc-drawer.sc-rail .sc-upsell-rail .sc-upsell-why { display: none; } 3084 } 3085 /* ===== desktop polish (both arms) ===== */ 3086 .sc-items { scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; } 3087 @media (min-width: 1024px) { 3088 .sc-items::-webkit-scrollbar { width: 6px; } 3089 .sc-items::-webkit-scrollbar-track { background: transparent; } 3090 .sc-items::-webkit-scrollbar-thumb { background-color: #cbd5e1; border-radius: 10px; } 3091 .sc-items::-webkit-scrollbar-thumb:hover { background-color: #94a3b8; } 3092 .sc-item-remove { transition: color 0.15s ease, transform 0.15s ease; } 3093 .sc-item-remove:hover { transform: scale(1.1); } 3094 } 3095</style> 3096 3097<div class="sc-overlay" id="scOverlay"></div> 3098<div class="sc-drawer sc-server-rendered sc-view-unconfirmed" id="scDrawer" role="dialog" aria-modal="true" aria-label="Shopping cart"> 3099 <div class="sc-header"> 3100 <h2>Your Cart</h2> 3101 <button class="sc-close" id="scClose" aria-label="Close cart"> 3102 <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg> 3103 </button> 3104 </div> 3105 <div class="sc-shipping" id="scShipping"> 3106 <div class="sc-shipping-text" id="scShipText">
3107 <span class="sc-truck">ð</span> 3108 <span>You're <span class="sc-amount" id="scShipAmount">$20</span> away from <strong>FREE shipping!</strong></span> 3109 </div> 3110 <div class="sc-bar-track"> 3111 <div class="sc-bar-fill" id="scBarFill"></div> 3112 <div class="sc-bar-shimmer"></div> 3113 </div> 3114 </div> 3115 <div class="sc-items"> 3116 <div id="scServerState"><div data-sc-server-render> 3117
3117<script type="application/json" data-sc-render-signature>{"currency":"AUD","total_price":0,"items":[]}</script>
3117 3118 <div data-sc-server-lines><p class="sc-empty">Your cart is empty.</p></div> 3119 <div data-sc-server-totals style="display:none;"> 3120 <span data-sc-total-text>$0.00 AUD</span> 3121 <span data-sc-original-total-text>$0.00 AUD</span> 3122 <span data-sc-discount-text>$0.00 AUD</span> 3123 <span data-sc-item-count>0</span> 3124 </div> 3125</div> 3126</div> 3127 <div class="sc-item" id="scItemAvera" style="display:none;"> 3128 <img class="sc-item-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/3.png?v=1783137786&width=200" alt="Hushd Avera"> 3129 <div class="sc-item-info"> 3130 <div class="sc-item-name">Hushd Avera</div> 3131 <div class="sc-item-variant">Anti-Snoring Mouthpiece</div> 3132 <div class="sc-item-row"> 3133 <div class="sc-item-price" id="scAveraPrice">$139</div> 3134 <div class="sc-qty"> 3135 <button class="sc-qty-btn sc-qty-disabled" id="scAveraMinus" aria-label="Decrease quantity"> 3136 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/></svg> 3137 </button> 3138 <span class="sc-qty-num" id="scAveraQty">1</span> 3139 <button class="sc-qty-btn" id="scAveraPlus" aria-label="Increase quantity"> 3140 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg> 3141 </button> 3142 </div> 3143 </div> 3144 </div> 3145 </div> 3146 <div class="sc-item" id="scItemGst" style="display:flex;"> 3147 <img class="sc-item-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-hero-bg.webp?v=1772167928&width=200" alt="Sleep Apnea Test" style="padding:2px;"> 3148 <div class="sc-item-info"> 3149 <div class="sc-item-name" id="scGstItemName">Good Sleep Test</div> 3150 <div class="sc-item-variant" id="scGstItemSub">At-home 1-night sleep study</div> 3151 <div class="sc-item-row"> 3152 <div class="sc-item-price" id="scGstPrice">$159</div> 3153 <div class="sc-qty"> 3154 <button class="sc-qty-btn sc-qty-disabled" id="scGstMinus" aria-label="Decrease quantity"> 3155 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/></svg> 3156 </button> 3157 <span class="sc-qty-num" id="scGstQty">1</span> 3158 <button class="sc-qty-btn" id="scGstPlus" aria-label="Increase quantity"> 3159 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg> 3160 </button> 3161 </div> 3162 </div> 3163 </div> 3164 </div> 3165 <div class="sc-item" id="scItemCleaner" style="display:none;"> 3166 <img class="sc-item-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Cleaner_4.png?v=1688359626" alt="Cleaner + Whitener" style="padding:2px;"> 3167 <div class="sc-item-info"> 3168 <div class="sc-item-name">Cleaner + Whitener</div> 3169 <div class="sc-item-variant">Oral Appliance Cleaning Solution</div> 3170 <div class="sc-item-row"> 3171 <div class="sc-item-price" id="scCleanerPrice">$25</div> 3172 <div class="sc-qty"> 3173 <button class="sc-qty-btn" id="scCleanerMinus" aria-label="Decrease quantity"> 3174 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/></svg> 3175 </button> 3176 <span class="sc-qty-num" id="scCleanerQty">1</span> 3177 <button class="sc-qty-btn" id="scCleanerPlus" aria-label="Increase quantity"> 3178 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg> 3179 </button> 3180 </div> 3181 </div> 3182 </div> 3183 </div><div class="sc-upsell" id="scSubOffer" style="display:none;"> 3184 <div class="sc-upsell-badge">Save 20%</div> 3185 <div class="sc-upsell-top"> 3186 <div class="sc-upsell-info"> 3187 <div class="sc-upsell-name">Save 20% by subscribing</div> 3188 <div class="sc-upsell-price">$20/mo instead of $25</div> 3189 <div class="sc-upsell-why">Your Cleaner delivered monthly. One pack is a 1 month supply. Cancel anytime.</div> 3190 </div> 3191 </div> 3192 <button class="sc-upsell-btn" id="scSubOfferBtn"><span data-sc-switch-label>Switch to Monthly — $20/mo</span><span data-sc-switch-status style="display:none;" aria-live="polite">Switching...</span></button> 3193 </div><div class="sc-item" id="scItemMag" style="display:none;"> 3194 <img class="sc-item-img" id="scMagItemImg" src="//goodsleepco.health/cdn/shop/files/AU_IS_TMPR200P_Front.png?v=1782267842&width=200" alt="Triple Magnesium Powder" style="padding:2px;"> 3195 <div class="sc-item-info"> 3196 <div class="sc-item-name" id="scMagItemName">Triple Magnesium Powder</div> 3197 <div class="sc-item-variant" id="scMagItemFlavour">Natural Berry · Relaxation & Recovery</div> 3198 <div class="sc-item-row"> 3199 <div class="sc-item-price" id="scMagPrice">$46.99</div> 3200 <div class="sc-qty"> 3201 <button class="sc-qty-btn" id="scMagMinus" aria-label="Decrease quantity"> 3202 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"/></svg> 3203 </button>
3204 <span class="sc-qty-num" id="scMagQty">1</span> 3205 <button class="sc-qty-btn" id="scMagPlus" aria-label="Increase quantity"> 3206 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"/></svg> 3207 </button> 3208 </div> 3209 </div> 3210 </div> 3211 </div> 3212 <div class="sc-upsell" id="scMagSubOffer" style="display:none;"> 3213 <div class="sc-upsell-badge">Save <span id="scMagOfferPctBadge">10</span>%</div> 3214 <div class="sc-upsell-top"> 3215 <div class="sc-upsell-info"> 3216 <div class="sc-upsell-name">Save <span id="scMagOfferPct">10</span>% by subscribing</div> 3217 <div class="sc-upsell-price" id="scMagOfferPrice"></div> 3218 <div class="sc-upsell-why">Your magnesium delivered monthly. Cancel anytime.</div> 3219 </div> 3220 </div> 3221 <button class="sc-upsell-btn" id="scMagSubOfferBtn"><span data-sc-switch-label>Switch to Monthly — <span id="scMagOfferBtnPrice"></span></span><span data-sc-switch-status style="display:none;" aria-live="polite">Switching...</span></button> 3222 </div> 3223 <div class="sc-upsell-rail"> 3224 <div class="sc-upsell" id="scUpsell" style="display:none;"> 3225 <div class="sc-upsell-badge">Unlocks Free Shipping</div> 3226 <div class="sc-upsell-top"> 3227 <img class="sc-upsell-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Cleaner_4.png?v=1688359626" alt="Cleaner + Whitener" style="padding:2px;"> 3228 <div class="sc-upsell-info"> 3229 <div class="sc-upsell-name">Cleaner + Whitener</div> 3230 <div class="sc-upsell-price">+ $25</div> 3231 <div class="sc-upsell-why">Keep your Avera fresh & bacteria-free. Most customers add this.</div> 3232 </div> 3233 </div> 3234 <button class="sc-upsell-btn" id="scUpsellBtn"> 3235 <svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/></svg> 3236 Add & Get FREE Shipping 3237 </button> 3238 </div> 3239 <div class="sc-upsell" id="scUpsellAvera" style="display:none;"> 3240 <div class="sc-upsell-badge">Most Popular Add-On</div> 3241 <div class="sc-upsell-top"> 3242 <img class="sc-upsell-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/3.png?v=1783137786&width=200" alt="Hushd Avera"> 3243 <div class="sc-upsell-info"> 3244 <div class="sc-upsell-name">Hushd Avera</div> 3245 <div class="sc-upsell-price">+ $139</div> 3246 <div class="sc-upsell-why">Snore loudly? Stop snoring tonight while you wait for your results.</div> 3247 </div> 3248 </div> 3249 <button class="sc-upsell-btn" id="scUpsellAveraBtn"> 3250 <svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/></svg> 3251 Add Avera — $139 3252 </button> 3253 </div> 3254 <div class="sc-upsell" id="scUpsellMag" style="display:none;"> 3255 <div class="sc-upsell-badge">Sleep Support</div> 3256 <div class="sc-upsell-top"> 3257 <img class="sc-upsell-img" id="scMagUpsellImg" src="//goodsleepco.health/cdn/shop/files/AU_IS_TMPR200P_Front.png?v=1782267842&width=200" alt="Triple Magnesium Powder" style="padding:2px;"> 3258 <div class="sc-upsell-info"> 3259 <div class="sc-upsell-name" id="scMagUpsellName">Triple Magnesium Powder</div> 3260 <div class="sc-upsell-price" id="scMagUpsellPrice">+ $46.99</div> 3261 <div class="sc-upsell-why">Sleep deeper — magnesium for relaxation & recovery.</div> 3262 </div> 3263 </div> 3264 <div class="sc-flavour-row" id="scMagFlavourRow" style="display:none;"> 3265 <label class="sc-flavour-label" for="scMagFlavour">Option</label> 3266 <select class="sc-flavour-select" id="scMagFlavour" aria-label="Choose magnesium option"></select> 3267 </div> 3268 <button class="sc-upsell-btn" id="scUpsellMagBtn"> 3269 <svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/></svg>
3270 <span id="scMagBtnLabel">Add Magnesium — $46.99</span> 3271 </button> 3272 </div> 3273 <div class="sc-upsell" id="scUpsellGst" style="display:none;"> 3274 <div class="sc-upsell-badge">Limited Time $41 Off</div> 3275 <div class="sc-upsell-top"> 3276 <img class="sc-upsell-img" src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/gst-hero-bg.webp?v=1772167928&width=200" alt="Sleep Apnea Test" style="padding:2px;"> 3277 <div class="sc-upsell-info"> 3278 <div class="sc-upsell-name">Sleep Apnea Test</div> 3279 <div class="sc-upsell-price"><s style="color:#9ca3af;font-weight:600">$200</s> $159 <span style="color:#dc2626;font-size:11px;font-weight:800">$41 OFF</span></div> 3280 <div class="sc-upsell-why">Loud snoring can be sleep apnea — find out with one night's sleep at home.</div> 3281 </div> 3282 </div> 3283 <button class="sc-upsell-btn" id="scUpsellGstBtn"> 3284 <svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4"/></svg> 3285 Add & Get FREE Shipping 3286 </button> 3287 </div> 3288 </div><!-- /sc-upsell-rail --> 3289 </div> 3290 <div class="sc-footer"> 3291 <div class="sc-subtotal"> 3292 <span class="sc-subtotal-label">Subtotal</span> 3293 <span class="sc-subtotal-right"> 3294 <span class="sc-save-badge" id="scSaveBadge">Save $50</span> 3295 <s class="sc-subtotal-was" id="scSubtotalWas"></s> 3296 <span class="sc-subtotal-price" id="scSubtotal">$0.00 AUD</span> 3297 </span> 3298 </div> 3299 <div class="sc-note" id="scNote" role="status" style="display:none;"></div> 3300 <button class="sc-checkout-btn" id="scCheckoutBtn">Secure Checkout â</button> 3301 <div class="sc-rating" id="scRating"> 3302 <span class="sc-stars" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 2l2.9 6.3 6.9.6-5.2 4.6 1.5 6.7-6.1-3.6-6.1 3.6 1.5-6.7L2.2 8.9l6.9-.6z"/></svg><svg viewBox="0 0 24 24"><path d="M12 2l2.9 6.3 6.9.6-5.2 4.6 1.5 6.7-6.1-3.6-6.1 3.6 1.5-6.7L2.2 8.9l6.9-.6z"/></svg><svg viewBox="0 0 24 24"><path d="M12 2l2.9 6.3 6.9.6-5.2 4.6 1.5 6.7-6.1-3.6-6.1 3.6 1.5-6.7L2.2 8.9l6.9-.6z"/></svg><svg viewBox="0 0 24 24"><path d="M12 2l2.9 6.3 6.9.6-5.2 4.6 1.5 6.7-6.1-3.6-6.1 3.6 1.5-6.7L2.2 8.9l6.9-.6z"/></svg><svg viewBox="0 0 24 24"><defs><linearGradient id="scStarPart"><stop offset="70%" stop-color="#f59e0b"/><stop offset="70%" stop-color="#e5e7eb"/></linearGradient></defs><path fill="url(#scStarPart)" d="M12 2l2.9 6.3 6.9.6-5.2 4.6 1.5 6.7-6.1-3.6-6.1 3.6 1.5-6.7L2.2 8.9l6.9-.6z"/></svg></span> 3303 <span class="sc-rating-text">Rated <strong>4.7 stars</strong> from 100,000+ sold</span> 3304 </div> 3305 <div class="sc-secure"> 3306 <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/></svg> 3307 SSL Encrypted · 14-Night Money-Back Guarantee 3308 </div> 3309 </div> 3310</div> 3311 3312<button class="sc-fab" id="scFab" aria-label="View your cart"> 3313 <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/></svg> 3314 <span class="sc-fab-count" id="scFabCount">1</span> 3315</button> 3316
3317<script> 3318(function() { 3319 var FREE_SHIP_THRESHOLD = 159; 3320 var DEFAULT_MODE = 'gst'; 3321 3322 // In-stock magnesium options only â sold-out variants excluded server-side. 3323 var MAG_OPTIONS = [];MAG_OPTIONS.push({ id: '47628215287947', title: "Natural Berry", price: 46.99, name: 'Triple Magnesium Powder', img: '//goodsleepco.health/cdn/shop/files/AU_IS_TMPR200P_Front.png?v=1782267842&width=200' });MAG_OPTIONS.push({ id: '47628215320715', title: "Pineapple Coconut", price: 46.99, name: 'Triple Magnesium Powder', img: '//goodsleepco.health/cdn/shop/files/AU_IS_TMPR200PPC_Front_1.png?v=1782267845&width=200' });MAG_OPTIONS.push({ id: '47628215353483', title: "Lemon Lime", price: 46.99, name: 'Triple Magnesium Powder', img: '//goodsleepco.health/cdn/shop/files/AU_IS_TMPR200PLL_Front.png?v=1782267852&width=200' });// Which upsell cards show for each main product. Card DOM order handles display order. 3324 var MODES = { 3325 avera: { addons: ['cleaner', 'mag', 'gst'] }, 3326 gst: { addons: ['avera', 'mag'] } 3327 }; 3328 3329 var PRODUCTS = [ 3330 { key: 'avera', variant: '42792097382539', handle: 'hushd-avera', price: 139.0, name: 'Hushd Avera', 3331 available: true, 3332 itemId: 'scItemAvera', qtyId: 'scAveraQty', priceId: 'scAveraPrice', minusId: 'scAveraMinus', plusId: 'scAveraPlus', 3333 upsellId: 'scUpsellAvera', btnId: 'scUpsellAveraBtn' }, 3334 { key: 'gst', variant: '41438208163979', handle: 'good-sleep-test', price: 159, name: 'Sleep Apnea Test', sub: 'At-Home Sleep Study', 3335 mainName: 'Good Sleep Test', mainSub: 'At-home 1-night sleep study', nameId: 'scGstItemName', subId: 'scGstItemSub', 3336 available: true, 3337 itemId: 'scItemGst', qtyId: 'scGstQty', priceId: 'scGstPrice', minusId: 'scGstMinus', plusId: 'scGstPlus', 3338 upsellId: 'scUpsellGst', btnId: 'scUpsellGstBtn' }, 3339 { key: 'cleaner', variant: '41124907712651', handle: 'cleaner', price: 25.0, name: 'Cleaner + Whitener', 3340 available: true, 3341 itemId: 'scItemCleaner', qtyId: 'scCleanerQty', priceId: 'scCleanerPrice', minusId: 'scCleanerMinus', plusId: 'scCleanerPlus', 3342 upsellId: 'scUpsell', btnId: 'scUpsellBtn' }, 3343 { key: 'mag', variant: '47628215287947', price: 46.99, name: "Triple Magnesium Powder", 3344 available: true, 3345 itemId: 'scItemMag', qtyId: 'scMagQty', priceId: 'scMagPrice', minusId: 'scMagMinus', plusId: 'scMagPlus', 3346 upsellId: 'scUpsellMag', btnId: 'scUpsellMagBtn' } 3347 ]; 3348 3349 function fmtMoney(n) { 3350 n = Math.round(n * 100) / 100; 3351 return '$' + (n % 1 === 0 ? n.toFixed(0) : n.toFixed(2)); 3352 } 3353 3354 PRODUCTS.forEach(function(p) { 3355 p.itemEl = document.getElementById(p.itemId); 3356 p.qtyEl = document.getElementById(p.qtyId); 3357 p.priceEl = document.getElementById(p.priceId); 3358 p.minusEl = document.getElementById(p.minusId); 3359 p.plusEl = document.getElementById(p.plusId); 3360 p.upsellEl = document.getElementById(p.upsellId); 3361 p.btnEl = document.getElementById(p.btnId); 3362 p.btnHtml = p.btnEl ? p.btnEl.innerHTML : ''; 3363 p.qty = 0; p.inCart = false; p.role = 'hidden'; 3364 p.ok = !!(p.itemEl && p.qtyEl && p.priceEl && p.minusEl && p.plusEl && p.upsellEl && p.btnEl); 3365 }); 3366 function prod(k) { 3367 for (var i = 0; i < PRODUCTS.length; i++) if (PRODUCTS[i].key === k) return PRODUCTS[i]; 3368 return null; 3369 } 3370 3371 var mode = MODES[DEFAULT_MODE] ? DEFAULT_MODE : 'avera'; 3372 var cartTotal = 0; 3373 var otherTotal = 0; // value of cart items outside this drawer's catalog 3374 var otherCount = 0; 3375 var userTouched = {}; // product keys the user changed before hydration finished 3376 var hydrateResolve; 3377 var hydratePromise = new Promise(function(res) { hydrateResolve = res; }); 3378 var lastCartItems = []; 3379 3380 var overlay = document.getElementById('scOverlay'); 3381 var drawer = document.getElementById('scDrawer'); 3382 var closeBtn = document.getElementById('scClose'); 3383 var checkoutBtn = document.getElementById('scCheckoutBtn'); 3384 var barFill = document.getElementById('scBarFill'); 3385 var shipText = document.getElementById('scShipText'); 3386 var shipWrap = document.getElementById('scShipping'); 3387 var subtotalEl = document.getElementById('scSubtotal'); 3388 var fabEl = document.getElementById('scFab'); 3389 var fabCountEl = document.getElementById('scFabCount'); 3390 var itemsWrap = drawer.querySelector('.sc-items'); 3391 3392 // ---- A/B test: upsell rail (rail) vs vertical stack (stack). Mobile-only visual diff. ---- 3393 var scAb = 'stack'; 3394 try { 3395 scAb = localStorage.getItem('gsc_sc_ab'); 3396 if (scAb !== 'rail' && scAb !== 'stack') { 3397 scAb = Math.random() < 0.5 ? 'rail' : 'stack'; 3398 localStorage.setItem('gsc_sc_ab', scAb); 3399 } 3400 } catch (err) { scAb = 'stack'; } 3401 if (scAb === 'rail') drawer.classList.add('sc-rail'); 3402 (function scTagPh(tries) { 3403 try { 3404 if (window.posthog && window.posthog.register) { window.posthog.register({ sc_ab: scAb }); } 3405 else if (tries > 0) { setTimeout(function() { scTagPh(tries - 1); }, 1500); } 3406 } catch (analyticsError) {} 3407 })(4); 3408 3409 3410 function collapseCard(p, instant) { 3411 if (drawer.classList.contains('sc-rail') && window.matchMedia('(max-width: 480px)').matches) { 3412 p.upsellEl.style.display = 'none'; 3413 updateRailSolo(); 3414 return; 3415 } 3416 p.upsellEl.style.transition = instant ? 'none' : 'opacity 0.2s ease'; 3417 p.upsellEl.style.maxHeight = '0'; p.upsellEl.style.opacity = '0'; 3418 p.upsellEl.style.padding = '0 16px'; p.upsellEl.style.margin = '0'; 3419 p.upsellEl.style.border = 'none'; p.upsellEl.style.overflow = 'hidden'; 3420 } 3421 function expandCard(p) { 3422 // The one gate every path shares: never offer a blank (draft/missing) or sold-out product. 3423 if (!p.available || !p.variant) { p.upsellEl.style.display = 'none'; return; } 3424 p.upsellEl.style.display = 'block'; 3425 p.upsellEl.style.transition = ''; p.upsellEl.style.maxHeight = ''; p.upsellEl.style.opacity = ''; 3426 p.upsellEl.style.padding = ''; p.upsellEl.style.margin = ''; 3427 p.upsellEl.style.border = ''; p.upsellEl.style.overflow = ''; 3428 p.btnEl.innerHTML = p.btnHtml; 3429 p.btnEl.classList.remove('sc-added'); 3430 p.btnEl.disabled = false;
3431 } 3432 3433 function setMode(newKey, skipSync) { 3434 if (!MODES[newKey]) newKey = 'avera'; 3435 mode = newKey; 3436 PRODUCTS.forEach(function(p) { 3437 if (!p.ok || !p.variant) { 3438 p.role = 'hidden'; p.qty = 0; p.inCart = false; 3439 if (p.itemEl) p.itemEl.style.display = 'none'; 3440 if (p.upsellEl) p.upsellEl.style.display = 'none'; 3441 return; 3442 } 3443 var subbed = !!(window.__scSubVariants && window.__scSubVariants[String(p.variant)]); 3444 var carted = p.inCart && p.qty > 0; 3445 if (!p.available && !carted) { 3446 // Sold out and not in the cart: never offered. (A carted sold-out line stays visible and badged.) 3447 p.role = 'hidden'; 3448 p.itemEl.style.display = 'none'; 3449 p.upsellEl.style.display = 'none'; 3450 return; 3451 } 3452 if (p.key === newKey) { 3453 // The page's product. Quantities only ever come from the server + queued ops - no synthetic 1. 3454 p.role = 'main'; 3455 p.itemEl.style.display = carted ? 'flex' : 'none'; 3456 p.upsellEl.style.display = 'none'; 3457 if (p.nameId && p.mainName) { 3458 var n = document.getElementById(p.nameId); if (n) n.textContent = p.mainName; 3459 var s = document.getElementById(p.subId); if (s) s.textContent = p.mainSub; 3460 } 3461 } else if (MODES[newKey].addons.indexOf(p.key) !== -1) { 3462 p.role = 'addon'; 3463 if (carted) { 3464 p.itemEl.style.display = 'flex'; 3465 p.upsellEl.style.display = 'none'; 3466 } else { 3467 p.itemEl.style.display = 'none'; 3468 if (subbed) p.upsellEl.style.display = 'none'; else expandCard(p); 3469 } 3470 if (p.nameId) { 3471 var n2 = document.getElementById(p.nameId); if (n2) n2.textContent = p.name; 3472 var s2 = document.getElementById(p.subId); if (s2) s2.textContent = p.sub; 3473 } 3474 } else if (carted) { 3475 // In the real cart but outside this page's catalog view - keep it visible, never zero it. 3476 p.role = 'addon'; 3477 p.itemEl.style.display = 'flex'; 3478 p.upsellEl.style.display = 'none'; 3479 } else { 3480 p.role = 'hidden'; 3481 p.itemEl.style.display = 'none'; 3482 p.upsellEl.style.display = 'none'; 3483 } 3484 }); 3485 recalcCart(skipSync); 3486 } 3487 3488 function updateRailSolo() { 3489 var railEl = drawer.querySelector('.sc-upsell-rail'); 3490 if (!railEl) return; 3491 var vis = Array.prototype.filter.call(railEl.children, function(c) { return getComputedStyle(c).display !== 'none'; }); 3492 railEl.classList.toggle('sc-rail-solo', vis.length === 1); 3493 } 3494 function recalcCart(skipSync) { 3495 var total = 0; 3496 PRODUCTS.forEach(function(p) { 3497 if (!p.ok || p.role === 'hidden' || !p.inCart) return; 3498 if (p.role === 'addon' && p.qty === 0) { 3499 p.inCart = false; 3500 p.itemEl.style.display = 'none'; 3501 if (window.__scSubVariants && window.__scSubVariants[String(p.variant)]) p.upsellEl.style.display = 'none'; else expandCard(p); 3502 return; 3503 } 3504 total += p.qty * p.price; 3505 p.qtyEl.textContent = p.qty; 3506 p.priceEl.textContent = fmtMoney(p.qty * p.price); 3507 var minQ = (p.role === 'main') ? 1 : 0; 3508 p.minusEl.classList.toggle('sc-qty-disabled', p.qty <= minQ); 3509 p.plusEl.classList.toggle('sc-qty-disabled', p.qty >= 5); 3510 }); 3511 updateRailSolo(); 3512 cartTotal = scLastCart ? scLastCart.total_price / 100 : total + otherTotal; 3513 updateShippingBar(); 3514 updateFab(); 3515 updateSubOffer(); 3516 updateMagSubOffer(); 3517 scApplySoldout(); 3518 if (!skipSync) syncCart(); 3519 } 3520 3521 // ---- Ordered cart operations (05/09/2026) ---- 3522 // Every cart mutation and read is an op executed strictly one at a time from one FIFO. Requests are 3523 // built at execution time from the latest server cart, so order is preserved and nothing is written 3524 // from a stale snapshot. Buys add (add.js); steppers change the bound line (change.js); reads apply 3525 // server truth. Outcomes: ok / rejected / partial / uncertain (bounded watch) -> unconfirmed. 3526 var scOps = []; 3527 var scOpSeq = 0; 3528 var scLastCart = null; 3529 var scPrevCart = null; 3530 var scRunning = false; 3531 var scIdle = []; 3532 var scPending = {}; // product key -> stepper delta not yet enqueued (300 ms window) 3533 var scPendingOrder = []; 3534 var scPendingLines = {}; // identity captured at the tap, before a flavour selector can change it 3535 var scViewError = null; 3536 var scPaintFailures = 0; 3537 var scLineOverlay = {}; 3538 var scSectionCandidate = null; 3539 var scSectionRequest = 0; 3540 var scSectionPendingSignature = null; 3541 var scViewPending = false;
3542 var scRenderedTotal = null; 3543 var scRenderedOriginal = null; 3544 var scRenderedDiscount = null; 3545 var scOverlay = {}; // ident -> queued/in-flight delta shown on top of server truth 3546 var scAddBusy = {}; // purchase signature -> pending whole-group op; no post-completion delay 3547 var scConvertOps = {}; // source identity -> non-terminal convert op (repeat switches attach to it) 3548 var scOwnLines = {}; // identities the drawer's OWN adds created: deliberate purchases, never janitor targets 3549 var scCurrentOp = null; // op whose responses are being applied right now 3550 var scLastCartMutOp = 0; // id of the mutation whose post-write cart is the latest one applied 3551 var scLastMutOp = 0; // id of the latest mutation op that ran (with or without a cart back) 3552 var scConvertBusy = {}; // variant id -> number of non-terminal conversions touching it 3553 var scJanitorPasses = {}; 3554 var scJanitorLastCart = null; 3555 var scDupNoted = false; 3556 var scFrozen = false; // a checkout attempt is in progress: mutations are rejected 3557 var scCheckoutBusy = false; 3558 var scCheckoutSeq = 0; 3559 var scInspected = 0; // settled operation boundary explicitly acknowledged after a current-cart review 3560 var scNoteTimer = null; 3561 var syncTimer = null; 3562 var SC_WATCH = [3000, 7000, 10000]; // uncertain op: re-read at +3 s, +10 s, +20 s, then unconfirmed 3563 3564 function scPropsKey(props) { 3565 if (!props) return ''; 3566 var ks = Object.keys(props).filter(function (k) { return props[k] !== null && props[k] !== undefined && props[k] !== ''; }).sort(); 3567 return ks.length ? JSON.stringify(ks.map(function (k) { return [k, String(props[k])]; })) : ''; 3568 } 3569 function scIdent(vid, planId, props) { return String(vid) + '|' + (planId ? String(planId) : '') + '|' + scPropsKey(props); } 3570 function scLineIdent(it) { 3571 var plan = (it.selling_plan_allocation && it.selling_plan_allocation.selling_plan) ? it.selling_plan_allocation.selling_plan.id : null; 3572 return scIdent(it.variant_id, plan, it.properties); 3573 } 3574 function scFindLine(cart, vid, planId, props) { 3575 var ident = scIdent(vid, planId, props), items = (cart && cart.items) || []; 3576 for (var i = 0; i < items.length; i++) if (scLineIdent(items[i]) === ident) return items[i]; 3577 return null; 3578 } 3579 function scLineQty(cart, vid, planId, props) { var l = scFindLine(cart, vid, planId, props); return l ? l.quantity : 0; } 3580 function scOverlayFor(ident, key) { return (scOverlay[ident] || 0) + (key && scPending[key] ? scPending[key] : 0); } 3581 function scBump(ident, d) { scOverlay[ident] = (scOverlay[ident] || 0) + d; if (!scOverlay[ident]) delete scOverlay[ident]; } 3582 function scPlanFor(p) { 3583 if (p.key === 'cleaner' && typeof SC_CL_OFFER !== 'undefined' && SC_CL_OFFER.plan) return String(SC_CL_OFFER.plan); 3584 if (p.key === 'mag' && typeof MAG_SUB !== 'undefined' && MAG_SUB[String(p.variant)]) return String(MAG_SUB[String(p.variant)].plan); 3585 return null; 3586 } 3587 3588 function scLocaleRoot() { 3589 var root = window.Shopify && window.Shopify.routes && window.Shopify.routes.root; 3590 return root && typeof root === 'string' ? (root.charAt(root.length - 1) === '/' ? root : root + '/') : '/'; 3591 } 3592 function scLocaleUrl(url) { 3593 return typeof url === 'string' && /^\/(?:cart(?:[\/.?]|$)|products\/)/.test(url) ? scLocaleRoot() + url.slice(1) : url; 3594 } 3595 function scFetchT(url, opts, ms) { 3596 url = scLocaleUrl(url); 3597 // Resolves ONLY once the body has been read: a response whose headers arrive but whose body stalls 3598 // is a timeout like any other hung request. The abort cancels the body read too; the race is the 3599 // belt-and-braces for environments that do not propagate it. Resolves { ok, status, body, json() }. 3600 opts = opts || {}; 3601 var ctrl = (typeof AbortController === 'function') ? new AbortController() : null; 3602 if (ctrl) opts.signal = ctrl.signal; 3603 opts.__sc = true; // the drawer's own request: the /cart/add hook below ignores it 3604 var fail; 3605 var lost = new Promise(function (_, rej) { fail = rej; }); 3606 var t = setTimeout(function () { if (ctrl) ctrl.abort(); fail(new Error('timeout')); }, ms || 8000); 3607 var done = Promise.resolve().then(function () { return fetch(url, opts); }).then(function (r) { 3608 return r.text().then(function (txt) { 3609 var parsed = null; 3610 try { parsed = txt ? JSON.parse(txt) : null; } catch (e) { parsed = null; } 3611 return { ok: r.ok, status: r.status, body: parsed, json: function () { return Promise.resolve(parsed); } }; 3612 }); 3613 }); 3614 return Promise.race([done, lost]).then(function (v) { clearTimeout(t); return v; }, function (e) { clearTimeout(t); throw e; }); 3615 } 3616 function scPost(url, body, attempt, keepalive, noRetry) { 3617 // Appstle otherwise replaces explicit add plans with its widget selection (including no selection). 3618 // Its own-request marker preserves this writer's full payload; do not change global fetch/app settings. 3619 if (url === '/cart/add.js') url += '?appstle=true'; 3620 // Shopify runs cart requests concurrently (Oct 2025) and answers 409 when the cart is busy: retry twice. 3621 var payload = {};
3622 Object.keys(body).forEach(function (key) { payload[key] = body[key]; }); 3623 payload.sections = ['side-cart-state']; 3624 payload.sections_url = (window.location && window.location.pathname) || scLocaleRoot(); 3625 var o = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(payload) }; 3626 if (keepalive) o.keepalive = true; 3627 return scFetchT(url, o, 8000).then(function (r) { 3628 if (r.body && r.body.sections) scSectionCandidate = r.body.sections['side-cart-state'] || null; 3629 if (!noRetry && r.status === 409 && (attempt || 0) < 2) { 3630 return new Promise(function (res) { setTimeout(res, 350 * ((attempt || 0) + 1)); }).then(function () { return scPost(url, body, (attempt || 0) + 1, keepalive, noRetry); }); 3631 } 3632 return r; 3633 }); 3634 } 3635 function scValidCart(cart) { 3636 if (!cart || !Array.isArray(cart.items) || typeof cart.currency !== 'string' || !/^[A-Z]{3}$/.test(cart.currency) || 3637 typeof cart.total_price !== 'number' || cart.total_price < 0 || Math.floor(cart.total_price) !== cart.total_price || 3638 typeof cart.item_count !== 'number' || cart.item_count !== cart.items.reduce(function (sum, it) { return sum + (it && typeof it.quantity === 'number' ? it.quantity : 0); }, 0)) return false; 3639 return cart.items.every(function (it) { 3640 if (!it || typeof it.key !== 'string' || !it.key || !it.variant_id || 3641 typeof it.quantity !== 'number' || !isFinite(it.quantity) || it.quantity <= 0 || Math.floor(it.quantity) !== it.quantity || 3642 typeof it.final_line_price !== 'number' || it.final_line_price < 0 || Math.floor(it.final_line_price) !== it.final_line_price) return false; 3643 if (it.properties && (typeof it.properties !== 'object' || Array.isArray(it.properties))) return false; 3644 return !it.selling_plan_allocation || !!(it.selling_plan_allocation.selling_plan && it.selling_plan_allocation.selling_plan.id); 3645 }); 3646 } 3647 function scValidateCart(cart) { 3648 if (!scValidCart(cart)) throw new Error('invalid_cart_snapshot'); 3649 return cart; 3650 } 3651 function scPaint(paint, showNotice) { 3652 // Presentation is not evidence of a mutation. Never let a missing DOM node retry a write. 3653 try { paint(); return true; } 3654 catch (error) { 3655 scViewError = error; scPaintFailures++;
3656 try { if (window.console && window.console.error) window.console.error('Cart display failed', error); } catch (ignored) {} 3657 if (showNotice !== false) { try { scShowNote('Your cart display could not refresh. Please refresh to review it.', true); } catch (ignoredNote) {} } 3658 return false; 3659 } 3660 } 3661 function scGetCart() { 3662 return scFetchT('/cart.js', { cache: 'no-store', headers: { 'Accept': 'application/json' } }, 8000) 3663 .then(function (r) { if (!r.ok) throw new Error('cart read ' + r.status); return r.json(); }) 3664 .then(scValidateCart); 3665 } 3666 function scCartFrom(r) { 3667 // change.js / update.js answer with the whole cart on success; anything else => read it. 3668 if (!r || !r.ok) return scGetCart(); 3669 return r.json().then(function (c) { return scValidCart(c) ? c : scGetCart(); }, function () { return scGetCart(); }); 3670 } 3671 function scReadCartCapped(ms) { 3672 return new Promise(function (res) { 3673 var done = false; 3674 var t = setTimeout(function () { if (!done) { done = true; res(undefined); } }, ms); 3675 scGetCart().then(function (c) { if (!done) { done = true; clearTimeout(t); res(c); } }, 3676 function () { if (!done) { done = true; clearTimeout(t); res(null); } }); 3677 }); 3678 } 3679 function scShowNote(msg, sticky) { 3680 scPaint(function () { scPaintNote(msg, sticky); }, false); 3681 } 3682 function scPaintNote(msg, sticky) { 3683 var el = document.getElementById('scNote'); 3684 if (!el) return; 3685 if (scNoteTimer) { clearTimeout(scNoteTimer); scNoteTimer = null; } 3686 if (!msg) { el.style.display = 'none'; el.innerHTML = ''; return; } 3687 el.innerHTML = msg; 3688 el.style.display = 'block'; 3689 if (!sticky) scNoteTimer = setTimeout(function () { el.style.display = 'none'; }, 6000); 3690 } 3691 document.addEventListener('click', function (e) { 3692 var t = e.target; 3693 if (t && t.getAttribute && t.getAttribute('data-sc-refresh') !== null) { scShowNote(''); refreshSideCart(); } 3694 }); 3695 function scApplyServer(cart, postWrite) { 3696 // postWrite: this cart was returned by a write, or read AFTER a write of the running mutation. 3697 // Preflight reads inside a mutation are NOT evidence of that mutation's outcome. 3698 scValidateCart(cart); // data failures must never be swallowed as presentation failures 3699 scPrevCart = scLastCart; scLastCart = cart; 3700 if (postWrite && scCurrentOp && scCurrentOp.kind !== 'read') scLastCartMutOp = scCurrentOp.id; 3701 applyRealCart(cart); 3702 } 3703 function scTerminal(op) { return op.status === 'ok' || op.status === 'rejected' || op.status === 'partial' || op.status === 'unconfirmed'; } 3704 function scNeedsJudging(op) { return (op.status === 'rejected' || op.status === 'partial' || op.status === 'unconfirmed') && op.id > scInspected; } 3705 3706 function scEnqueue(op) { 3707 // Accepts an op onto the FIFO; resolves with its terminal status. Only reads (and the internal 3708 // resume of an already-accepted conversion) are accepted while a checkout attempt is running. 3709 if (scFrozen && op.kind !== 'read' && op.kind !== 'resume') return Promise.reject(new Error('checkout_in_progress')); 3710 // Older stepper taps enter first. scFlush emits only `change`, so this cannot recurse. 3711 if (op.kind === 'add' || op.kind === 'addGroup' || op.kind === 'setGroup' || op.kind === 'line' || op.kind === 'convert') scFlush(); 3712 if (op.kind === 'convert') { 3713 // A second switch of the same source line while the first is not terminal (in flight, uncertain, 3714 // resuming) attaches to it: one conversion, never two adds. 3715 var srcKey = scIdent(op.src.vid, op.src.plan, op.src.props); 3716 var running = scConvertOps[srcKey]; 3717 if (running && !running.terminal) { running.attached = (running.attached || 0) + 1; return running.promise; } 3718 } 3719 op.id = ++scOpSeq; 3720 op.status = 'queued'; 3721 var done; 3722 op.promise = new Promise(function (res) { done = res; }); 3723 op.settle = function (status, extra) { 3724 if (op.terminal) return; 3725 op.status = status; op.extra = extra || null; 3726 if (status !== 'uncertain') op.terminal = true; 3727 if (op.terminal) { 3728 if (op.release) op.release(); 3729 scSaveRecovery(); 3730 if (status === 'ok' && scCommerce(op)) { try { localStorage.setItem('sc:changed:v1', String(Date.now()) + ':' + op.id); } catch (ignored) {} } 3731 done(status); 3732 // A read-only reconciliation may release work held behind an uncertain write. 3733 scRunNext(); 3734 } 3735 }; 3736 if (op.kind === 'convert') { 3737 // Janitor and mag alignment stay off these variants from acceptance until the op is terminal. 3738 var cv = [String(op.src.vid), String(op.dst.vid)]; 3739 cv.forEach(function (v) { scConvertBusy[v] = (scConvertBusy[v] || 0) + 1; }); 3740 scConvertOps[srcKey] = op; 3741 op.release = function () { 3742 cv.forEach(function (v) { scConvertBusy[v] = (scConvertBusy[v] || 1) - 1; if (!scConvertBusy[v]) delete scConvertBusy[v]; }); 3743 if (scConvertOps[srcKey] === op) delete scConvertOps[srcKey]; 3744 scUpdateConversionControls(); 3745 }; 3746 scUpdateConversionControls(); 3747 } 3748 scOps.push(op); 3749 if (scCommerce(op)) scSaveRecovery(); 3750 if (scOps.length > 200) scOps = scOps.filter(function (o) { return !scTerminal(o) || scNeedsJudging(o) || o.id > scOpSeq - 50; }); 3751 scRunNext(); 3752 return op.promise; 3753 } 3754 function scRunNext() { 3755 if (scRunning) return; 3756 var op = null; 3757 for (var i = 0; i < scOps.length; i++) { 3758 if (scOps[i].status !== 'queued') continue;
3759 // Do not let a later purchase overtake a write with an unknown outcome. 3760 // Reads/resumes must remain runnable so bounded reconciliation can finish. 3761 var held = scCommerce(scOps[i]) && scOps.some(function (earlier) { return earlier.id < scOps[i].id && earlier.status === 'uncertain'; }); 3762 if (!held) { op = scOps[i]; break; } 3763 } 3764 if (!op) { 3765 if (scOps.some(function (o) { return !scTerminal(o); })) return; 3766 var w = scIdle; scIdle = []; w.forEach(function (f) { f(); }); return; 3767 } 3768 scRunning = true; 3769 op.status = 'inflight'; 3770 scCurrentOp = op; 3771 var p; 3772 try { p = scDoWrite(op); } catch (e) { op.settle('rejected'); p = Promise.resolve(); } 3773 function next() { 3774 if (!op.terminal && op.status !== 'uncertain') op.settle('rejected'); 3775 if (op.kind !== 'read') scLastMutOp = op.id; 3776 scCurrentOp = null; 3777 scRunning = false; 3778 scRunNext(); 3779 } 3780 Promise.resolve(p).then(next, next); 3781 } 3782 function scWhenIdle() { 3783 return new Promise(function (res) { 3784 var queued = scOps.some(function (o) { return o.status === 'queued'; }); 3785 if (!scRunning && !queued) res(); else scIdle.push(res); 3786 }); 3787 } 3788 function scWaitFor(boundary, capMs) { 3789 // Resolves when every op accepted up to `boundary` is terminal, or at the cap. 3790 return new Promise(function (res) { 3791 var done = false; 3792 function pending() { return scOps.filter(function (o) { return o.id <= boundary && o.kind !== 'resume'; }); } 3793 var t = setTimeout(function () { if (!done) { done = true; res({ drained: false, ops: pending() }); } }, capMs); 3794 function check() { 3795 if (done) return; 3796 var ops = pending(); 3797 if (!ops.some(function (o) { return !scTerminal(o); })) { done = true; clearTimeout(t); res({ drained: true, ops: ops }); return; } 3798 setTimeout(check, 100); 3799 } 3800 check(); 3801 }); 3802 } 3803 3804 // Uncertain lifecycle: an aborted/lost request may still commit. Watch reads at +3 s / +10 s / +20 s 3805 // confirm it (op.verify) or the op ends `unconfirmed` - never resent, never called rejected. 3806 function scUncertain(op, verify) { 3807 op.status = 'uncertain'; op.verify = verify; op.watch = 0; 3808 scSaveRecovery(); 3809 scShowNote('Confirming your last change...', true); 3810 scScheduleWatch(op); 3811 } 3812 function scScheduleWatch(op) { 3813 if (op.watch >= SC_WATCH.length) { 3814 op.settle('unconfirmed'); 3815 scShowNote('We could not confirm your last change. Please review your cart. <button type="button" class="sc-note-btn" data-sc-refresh>Refresh cart</button>', true); 3816 return; 3817 } 3818 var wait = SC_WATCH[op.watch++]; 3819 setTimeout(function () { 3820 if (op.terminal || op.status !== 'uncertain') return; 3821 scEnqueue({ kind: 'read' }).then(function () { 3822 if (op.terminal || op.status !== 'uncertain') return; 3823 if (scLastCart && op.verify(scLastCart)) { 3824 scShowNote(''); 3825 // A conversion whose target add was confirmed still has to remove its source (through the queue). 3826 if (op.resume) { op.status = 'inflight'; scEnqueue({ kind: 'resume', parent: op, run: op.resume })['catch'](function () {}); } 3827 else op.settle('ok'); 3828 return; 3829 } 3830 scScheduleWatch(op); 3831 }, function () { scScheduleWatch(op); }); 3832 }, wait); 3833 } 3834 3835 function scDoWrite(op) { 3836 // Executes ONE op (called by the queue runner only). 3837 if (op.kind === 'read') return scOpRead(op); 3838 if (op.kind === 'add') return scOpAdd(op); 3839 if (op.kind === 'addGroup') return scOpAddGroup(op); 3840 if (op.kind === 'setGroup') return scOpSetGroup(op); 3841 if (op.kind === 'change') return scOpChange(op); 3842 if (op.kind === 'line') return scOpLine(op); 3843 if (op.kind === 'attributes') return scOpAttributes(op); 3844 if (op.kind === 'convert') return scOpConvert(op); 3845 if (op.kind === 'resume') return Promise.resolve(op.run()).then(function () { op.settle('ok'); }, function () { op.settle('ok'); }); 3846 op.settle('rejected'); 3847 return Promise.resolve(); 3848 } 3849 function scWriteCart(op) { 3850 // Enqueue a cart op; resolves with its terminal status. 3851 return scEnqueue(op); 3852 } 3853 function scOpRead(op) { 3854 return scGetCart().then(function (cart) { scApplyServer(cart); op.settle('ok'); }, function () { 3855 op.settle('rejected'); 3856 if (!scLastCart) { 3857 scViewError = new Error('cart_hydration_failed'); 3858 scPaint(function () { scSetViewStatus(false, false); scPaintLineControls(); }); 3859 scShowNote('<span data-sc-hydration-note>We could not read your cart. Please check your connection. <button type="button" class="sc-note-btn" data-sc-check>Check cart</button> <a class="sc-note-btn" href="' + scRoot() + 'cart?sc_review=1">
3859Review cart</a></span>', true); 3860 } 3861 }); 3862 } 3863 function scOpAttributes(op) { 3864 return scPost('/cart/update.js', { attributes: op.attrs }, 0, true).then(function (r) { 3865 if (!r.ok) { op.settle('rejected'); return; } 3866 return r.json().then(function (cart) { if (cart && cart.items) scApplyServer(cart, true); op.settle('ok'); }, function () { op.settle('ok'); }); 3867 }, function () { op.settle('rejected'); }); 3868 } 3869 function scFail(op, msg) { op.settle('rejected'); if (msg) scShowNote(msg); } 3870 function scGroupQty(cart, item) { 3871 var identity = scIdent(item.id, item.selling_plan, item.properties); 3872 return ((cart && cart.items) || []).reduce(function (sum, line) { return sum + (scLineIdent(line) === identity ? line.quantity : 0); }, 0); 3873 } 3874 function scGroupMatches(cart, items, targets) { 3875 return items.every(function (item, i) { return scGroupQty(cart, item) === targets[i]; }); 3876 } 3877 function scNormalizeItems(items, pin) { 3878 if (!Array.isArray(items) || !items.length) throw new Error('empty_purchase'); 3879 var normalized = [], positions = Object.create(null); 3880 items.forEach(function (item) { 3881 if (!item || !/^\d+$/.test(String(item.id)) || Number(item.id) <= 0) throw new Error('invalid_variant'); 3882 var q = item.quantity === undefined ? 1 : Number(item.quantity); 3883 if (!isFinite(q) || Math.floor(q) !== q || q < (pin ? 0 : 1)) throw new Error('invalid_quantity'); 3884 if (item.properties && (typeof item.properties !== 'object' || Array.isArray(item.properties))) throw new Error('invalid_properties'); 3885 var next = { id: String(item.id), quantity: q }; 3886 if (item.selling_plan) { 3887 if (!/^\d+$/.test(String(item.selling_plan)) || Number(item.selling_plan) <= 0) throw new Error('invalid_plan'); 3888 next.selling_plan = String(item.selling_plan); 3889 } 3890 if (item.properties) next.properties = JSON.parse(JSON.stringify(item.properties)); 3891 var identity = scIdent(next.id, next.selling_plan, next.properties); 3892 if (positions[identity] !== undefined) { 3893 if (pin && normalized[positions[identity]].quantity !== q) throw new Error('conflicting_quantities'); 3894 if (!pin) normalized[positions[identity]].quantity += q; 3895 } else { positions[identity] = normalized.length; normalized.push(next); } 3896 }); 3897 normalized.sort(function (a, b) { var x = scIdent(a.id, a.selling_plan, a.properties), y = scIdent(b.id, b.selling_plan, b.properties); return x < y ? -1 : x > y ? 1 : 0; }); 3898 return normalized; 3899 } 3900 function scApiGroup(items, pin, checkoutNow) { 3901 if (scFrozen) return Promise.reject(new Error('checkout_in_progress')); 3902 try { items = scNormalizeItems(items, pin); } catch (e) { return Promise.reject(e); } 3903 var sig = (pin ? 'set:' : 'api:') + JSON.stringify(items.map(function (it) { return [it.id, it.quantity, it.selling_plan || null, scPropsKey(it.properties)]; })); 3904 var guard = scGuardCheck(sig); 3905 if (guard) return checkoutNow ? scCheckout() : (guard.attach || guard.busy).promise.then(function (status) { return [status]; }); 3906 var op = { kind: pin ? 'setGroup' : 'addGroup', items: items }; 3907 if (!pin) { 3908 items.forEach(function (it) { scBump(scIdent(it.id, it.selling_plan, it.properties), it.quantity); }); 3909 op.hasOverlay = true; 3910 } 3911 var pending = scEnqueue(op); 3912 scGuardStart(sig, op); // One guard covers the whole group, including response reconciliation. 3913 if (checkoutNow) { 3914 // Acceptance and checkout boundary are synchronous; failed validation cannot check out a stale cart. 3915 pending.then(function (status) { 3916 if (status !== 'ok') return; 3917 try { 3918 window.dataLayer = window.dataLayer || []; 3919 window.dataLayer.push({ event: 'cart_purchase_confirmed', purchase_policy: 'pinned', items: items.map(function (item) { return { variant_id: item.id, quantity: item.quantity, selling_plan: item.selling_plan || null }; }) }); 3920 } catch (ignored) {} 3921 }, function () {}); 3922 return scCheckout(); 3923 } 3924 return pending.then(function (status) { return [status]; }); 3925 } 3926 function scClearGroupOverlay(op) { 3927 if (!op.hasOverlay) return; 3928 op.hasOverlay = false;
3929 op.items.forEach(function (it) { scBump(scIdent(it.id, it.selling_plan, it.properties), -it.quantity); }); 3930 } 3931 function scDefiniteRejection(response) { return !!response && response.status >= 400 && response.status < 500; } 3932 function scOpAdd(op) { 3933 // Existing drawer upsells share the same verification as public grouped purchases. 3934 op.items = [{ id: op.vid, quantity: op.delta }]; 3935 if (op.plan) op.items[0].selling_plan = op.plan; 3936 if (op.props) op.items[0].properties = op.props; 3937 op.hasOverlay = true; 3938 return scOpAddGroup(op); 3939 } 3940 function scOpAddGroup(op, attempt) { 3941 // A bundle is one Ajax add request, not an atomicity assumption. Always verify every full identity. 3942 return scGetCart().then(function (beforeCart) { 3943 scApplyServer(beforeCart); 3944 var before = op.items.map(function (it) { return scGroupQty(beforeCart, it); }); 3945 var targets = op.items.map(function (it, i) { return before[i] + it.quantity; }); 3946 op.items.forEach(function (it) { scOwnLines[scIdent(it.id, it.selling_plan, it.properties)] = true; }); 3947 function verify(cart) { return scGroupMatches(cart, op.items, targets); } 3948 function unknown() { scClearGroupOverlay(op); scUncertain(op, verify); } 3949 function inspect(response, lost) { 3950 return scGetCart().then(function (cart) { 3951 scClearGroupOverlay(op); scApplyServer(cart, true); 3952 if (verify(cart)) { op.settle('ok'); return; } 3953 if (lost || !response || (!response.ok && !scDefiniteRejection(response))) { unknown(); return; } 3954 var progressed = op.items.some(function (it, i) { return scGroupQty(cart, it) !== before[i]; }); 3955 if (progressed) { 3956 op.settle('partial'); scShowNote('Only part of this purchase was confirmed. Please review your cart.', true); return; 3957 } 3958 if (scDefiniteRejection(response)) { scFail(op, 'Cart did not update. Please try again.'); return; } 3959 unknown(); // Even 2xx is not proof if the actual cart does not contain the requested quantities. 3960 }, function () { 3961 scClearGroupOverlay(op); 3962 // A multi-item rejection can still be partial; a failed read cannot prove no item landed. 3963 unknown(); 3964 }); 3965 } 3966 return scPost('/cart/add.js', { items: op.items }, 0, false, true).then(function (response) { 3967 if (response.status === 409 && (attempt || 0) < 2) { 3968 return new Promise(function (resolve) { setTimeout(resolve, 350 * ((attempt || 0) + 1)); }).then(function () { return scOpAddGroup(op, (attempt || 0) + 1); }); 3969 } 3970 return inspect(response, false); 3971 }, function () { return inspect(null, true); }); 3972 }, function () { scClearGroupOverlay(op); scFail(op, 'We could not read your cart. Please check your connection and try again.'); }); 3973 } 3974 function scOpSetGroup(op) { 3975 // Deliberate Buy Now policy: pin only the named full identities; never variant-id update a different plan/property line. 3976 var targets = op.items.map(function (it) { return it.quantity; }), original = null; 3977 function verify(cart) { return scGroupMatches(cart, op.items, targets); } 3978 function unknown() { scUncertain(op, verify); } 3979 function changed(cart) { return op.items.some(function (it, i) { return scGroupQty(cart, it) !== original[i]; }); } 3980 function rejected(cart) { 3981 if (cart && changed(cart)) { op.settle('partial'); scShowNote('Only part of this Buy Now update was confirmed. Please review your cart.', true); } 3982 else scFail(op, 'Cart did not update. Please try again.'); 3983 } 3984 function run(cart, attempt, steps) { 3985 scApplyServer(cart); 3986 if (verify(cart)) { op.settle('ok'); return Promise.resolve(); } 3987 if (steps > 2) { rejected(cart); return Promise.resolve(); } 3988 var updates = {}, affected = [], missing = []; 3989 op.items.forEach(function (item, index) { 3990 var identity = scIdent(item.id, item.selling_plan, item.properties); 3991 var lines = cart.items.filter(function (line) { return scLineIdent(line) === identity; }); 3992 if (!lines.length) { if (item.quantity > 0) missing.push(item); return; } 3993 if (scGroupQty(cart, item) === item.quantity) return; 3994 // Shopify can split a plain identity into multiple discount rows. Pin the aggregate by exact keys.
3995 lines.forEach(function (line, i) { updates[line.key] = i === 0 ? item.quantity : 0; }); 3996 affected.push(index); 3997 }); 3998 var updating = Object.keys(updates).length > 0; 3999 var endpoint = updating ? '/cart/update.js' : '/cart/add.js'; 4000 var body = updating ? { updates: updates } : { items: missing }; 4001 if (!updating && !missing.length) { rejected(cart); return Promise.resolve(); } 4002 function inspect(response, lost) { 4003 if (response && response.status === 409 && attempt < 2) { 4004 // A confirmed 409 is safe to retry, but rebuilt keys/identities must come from a new cart read. 4005 return new Promise(function (resolve) { setTimeout(resolve, 350 * (attempt + 1)); }).then(function () { 4006 return scGetCart().then(function (fresh) { return run(fresh, attempt + 1, steps); }, unknown); 4007 }); 4008 } 4009 return scGetCart().then(function (after) { 4010 scApplyServer(after, true); 4011 if (verify(after)) { op.settle('ok'); return; } 4012 if (lost || !response || (!response.ok && !scDefiniteRejection(response))) { unknown(); return; } 4013 if (scDefiniteRejection(response)) { rejected(after); return; } 4014 if (updating && affected.every(function (i) { return scGroupQty(after, op.items[i]) === targets[i]; })) { 4015 // Continue only after this stage is proven. A lost response never causes an additive replay. 4016 return run(after, 0, steps + 1); 4017 } 4018 if (changed(after)) { op.settle('partial'); scShowNote('Only part of this Buy Now update was confirmed. Please review your cart.', true); } 4019 else unknown(); 4020 }, unknown); 4021 } 4022 return scPost(endpoint, body, 0, false, true).then(function (response) { return inspect(response, false); }, function () { return inspect(null, true); }); 4023 } 4024 return scGetCart().then(function (cart) { original = op.items.map(function (it) { return scGroupQty(cart, it); }); return run(cart, 0, 0); }, function () { scFail(op, 'We could not read your cart. Please check your connection and try again.'); }); 4025 } 4026 4027 function scOpChange(op) { return scOpQuantity(op, true); } 4028 function scOpLine(op) { return scOpQuantity(op, false); } 4029 function scOpQuantity(op, byProduct) { 4030 var released = false; 4031 function release() { 4032 if (released) return; released = true; 4033 if (byProduct) scBump(op.ident, -op.delta); 4034 if (op.overlayKey) { 4035 scLineOverlay[op.overlayKey] = (scLineOverlay[op.overlayKey] || 0) - op.delta; 4036 if (!scLineOverlay[op.overlayKey]) delete scLineOverlay[op.overlayKey]; 4037 } 4038 } 4039 function finish(cart, status, message) { 4040 release(); if (cart) scApplyServer(cart, true); 4041 else scPaint(function () { scPaintLineControls(); }); // Remove optimism after a failed preflight read; do not invent a fresh cart. 4042 op.settle(status); if (message && !op.quiet) scShowNote(message, status === 'partial'); 4043 } 4044 function run(attempt) { 4045 return scGetCart().then(function (cart) { 4046 scApplyServer(cart); 4047 var line = byProduct ? scFindLine(cart, op.vid, null, null) : scExactLine(cart, op.key); 4048 // An exact row may have disappeared or split. Never substitute a sibling with the same variant. 4049 if (!line && !byProduct) { 4050 var remaining = op.ident ? scTotalQty(cart, op.ident) : 0; 4051 if (!remaining && (op.target === 0 || op.delta < 0)) { finish(cart, 'ok'); return; } 4052 finish(cart, 'rejected', 'This cart line changed. Please review your cart.'); return; 4053 } 4054 var ident = line ? scLineIdent(line) : op.ident; 4055 var before = line ? line.quantity : 0, totalBefore = scTotalQty(cart, ident); 4056 var target = op.delta !== undefined ? Math.max(0, before + op.delta) : op.target; 4057 var expectedTotal = totalBefore + target - before; 4058 if (!line && target <= 0) { finish(cart, 'ok'); return; } 4059 function verify(c) { return scTotalQty(c, ident) === expectedTotal; } 4060 function unknown(c) { release(); if (c) scApplyServer(c, true); scUncertain(op, verify); } 4061 var adding = !line; 4062 if (adding) scOwnLines[ident] = true; 4063 var body = adding ? { id: op.vid, quantity: target } : { id: line.key, quantity: target }; 4064 return scPost(adding ? '/cart/add.js' : '/cart/change.js', body, 0, false, true).then(function (r) { 4065 return scCartFrom(r).then(function (c) { 4066 if (verify(c)) { finish(c, 'ok'); return; } 4067 if (r.status === 409 && attempt < 2) { 4068 scApplyServer(c, true); 4069 return new Promise(function (res) { setTimeout(res, 350 * (attempt + 1)); }).then(function () { return run(attempt + 1); }); 4070 } 4071 var actual = scTotalQty(c, ident); 4072 if (r.status >= 400 && r.status < 500) { 4073 finish(c, actual !== totalBefore ? 'partial' : 'rejected', actual !== totalBefore ? 'Your cart changed. Please review the confirmed quantity.' : 'Cart did not update. Please try again.'); return; 4074 } 4075 if (r.ok && actual !== totalBefore) { finish(c, 'partial', 'Your cart was adjusted. Please review the confirmed quantity.'); return; } 4076 unknown(c); 4077 }, function () { unknown(); }); 4078 }, function () { unknown(); }); 4079 }, function () { finish(null, 'rejected', 'Cart did not update. Please try again.'); }); 4080 } 4081 return run(0); 4082 } 4083 4084 function scOpConvert(op) { 4085 // src -> dst (plan switch or flavour switch). Add the target FIRST, verify it rose by the source 4086 // quantity, then remove the source and verify it is gone. ok only when both halves are verified. 4087 var sv = String(op.src.vid), dv = String(op.dst.vid); 4088 var sourceIdent = scIdent(op.src.vid, op.src.plan, op.src.props); 4089 var targetIdent = scIdent(op.dst.vid, op.dst.plan, op.dst.props); 4090 function sourceLine(c) { 4091 if (op.src.key) { 4092 var bound = scExactLine(c, op.src.key); 4093 return bound && scLineIdent(bound) === sourceIdent ? bound : null; 4094 } 4095 var matches = c.items.filter(function (line) { return scLineIdent(line) === sourceIdent; }); 4096 return matches.length === 1 ? matches[0] : null; 4097 }
4098 var BOTH = 'You now have two versions of this item in your cart. Remove the one you do not want.'; 4099 return scGetCart().then(function (cart) { 4100 scApplyServer(cart); 4101 if (!op.src.key && cart.items.filter(function (line) { return scLineIdent(line) === sourceIdent; }).length > 1) { 4102 scFail(op, 'More than one matching cart line exists. Please select the line you want to change.'); return; 4103 } 4104 var src = sourceLine(cart); 4105 var tgtBefore = scTotalQty(cart, targetIdent); 4106 if (op.src.key && !src) { scFail(op, 'This cart line changed. Please review your cart.'); return; } 4107 if (!src) { op.settle(tgtBefore > 0 ? 'ok' : 'rejected'); return; } 4108 op.src.key = src.key; // bind a legacy identity-only request once, before any write 4109 var intended = src.quantity; 4110 var otherSourceQty = scTotalQty(cart, sourceIdent) - intended; 4111 function tgt(c) { return scTotalQty(c, targetIdent); } 4112 function verifyTarget(c) { return tgt(c) >= tgtBefore + intended; } 4113 function srcGone(c) { return !sourceLine(c) && (!op.src.key || scTotalQty(c, sourceIdent) === otherSourceQty); } 4114 function giveUp() { op.settle('partial', { reason: 'source-remains' }); scShowNote(BOTH, true); } 4115 function conflict(c) { 4116 // The cart moved under us (another tab): keep every remaining line, show the truth, ask to review. 4117 scApplyServer(c, true); 4118 op.settle('partial', { reason: 'cart-changed' }); 4119 scShowNote('Your cart changed while we were switching plans. Please review it.', true); 4120 } 4121 // Freeze the cleanup's pre/postcondition once: a retry must never subtract twice. 4122 var cleanup = null; 4123 function removeSource(attempt) { 4124 function retryOrGiveUp() { 4125 if (attempt < 2) return new Promise(function (res) { setTimeout(res, 500); }).then(function () { return removeSource(attempt + 1); }); 4126 giveUp(); 4127 } 4128 return scGetCart().then(function (c1) { 4129 var s = sourceLine(c1); 4130 if (!verifyTarget(c1)) return conflict(c1); 4131 if (!s) { 4132 if (op.src.key && scTotalQty(c1, sourceIdent) !== otherSourceQty) return conflict(c1); 4133 if (cleanup && cleanup.leave !== 0) return conflict(c1); 4134 scApplyServer(c1, true); op.settle('ok'); return; 4135 } 4136 if (cleanup) { 4137 scApplyServer(c1, true); 4138 if (s.quantity === cleanup.leave) { op.settle('ok'); return; } 4139 // A replaced/re-keyed or changed source is not safe to write again. 4140 if (s.key !== cleanup.key || s.quantity !== cleanup.before) return conflict(c1); 4141 // A transport failure/5xx may have committed. Reconcile by reads only. 4142 if (cleanup.uncertain) return retryOrGiveUp(); 4143 } else { 4144 if (s.quantity < intended) return conflict(c1); 4145 cleanup = { key: s.key, before: s.quantity, leave: s.quantity - intended, uncertain: false }; 4146 } 4147 var leave = cleanup.leave; 4148 cleanup.uncertain = true; // remains unknown if this request loses its response 4149 // Cleanup owns 409 retries too: every retry must recheck the frozen source first. 4150 return scPost('/cart/change.js', { id: cleanup.key, quantity: leave }, 0, false, true).then(function (r) { 4151 // Only a definite client-side rejection permits a bounded same-body retry. 4152 cleanup.uncertain = !(r.status >= 400 && r.status < 500); 4153 return scCartFrom(r).then(function (c2) { 4154 scApplyServer(c2, true); 4155 var s2 = sourceLine(c2); 4156 if ((s2 ? s2.quantity : 0) === leave && verifyTarget(c2)) { op.settle('ok'); return; } 4157 if (!verifyTarget(c2) || !s2 || s2.key !== cleanup.key || s2.quantity !== cleanup.before) return conflict(c2); 4158 return retryOrGiveUp(); 4159 }, retryOrGiveUp); 4160 }, retryOrGiveUp); 4161 }, retryOrGiveUp); 4162 } 4163 op.resume = function () { return removeSource(0); }; 4164 function addFirst() { 4165 var body = { id: op.dst.vid, quantity: intended }; 4166 if (op.dst.plan) body.selling_plan = op.dst.plan; 4167 if (op.dst.props) body.properties = op.dst.props; 4168 return scPost('/cart/add.js', body, 0, false).then(function () { 4169 return scGetCart().then(function (c) { 4170 scApplyServer(c, true); 4171 var got = tgt(c) - tgtBefore; 4172 if (got >= intended) return removeSource(0); 4173 if (got > 0) { op.settle('partial', { added: got }); scShowNote('Only ' + got + ' of ' + intended + ' could be switched; both are still in your cart.', true); return; } 4174 scFail(op, 'Could not switch this item. Nothing was changed.'); 4175 }, function () { scUncertain(op, verifyTarget); }); 4176 }, function () { scUncertain(op, verifyTarget); }); 4177 } 4178 if (sv === dv && String(op.src.plan || '') !== String(op.dst.plan || '')) { 4179 // Same-variant plan changes are direct only. Never turn a rejected/unknown switch into a purchase. 4180 op.resume = null; 4181 function verifyDirect(c) { return srcGone(c) && verifyTarget(c); } 4182 function directUnknown() { scUncertain(op, verifyDirect); } 4183 function directAttempt(currentCart, attempt) { 4184 if (verifyDirect(currentCart)) { scApplyServer(currentCart, true); op.settle('ok'); return; } 4185 var current = sourceLine(currentCart); 4186 if (!current || current.quantity !== intended || tgt(currentCart) !== tgtBefore) return conflict(currentCart); 4187 var idx = currentCart.items.indexOf(current); 4188 var body = { line: idx + 1, quantity: intended, selling_plan: op.dst.plan ? String(op.dst.plan) : null }; 4189 return scPost('/cart/change.js', body, 0, false, true).then(function (r) { 4190 return scCartFrom(r).then(function (c) { 4191 scApplyServer(c, true); 4192 if (verifyDirect(c)) { op.settle('ok'); return; } 4193 var unchanged = sourceLine(c); 4194 if (!unchanged || unchanged.quantity !== intended || tgt(c) !== tgtBefore) return conflict(c); 4195 if (r.status === 409 && attempt < 2) { 4196 return new Promise(function (res) { setTimeout(res, 350 * (attempt + 1)); }).then(function () { 4197 // Another tab may have inserted a line during the backoff. Resolve position again. 4198 return scGetCart().then(function (fresh) { return directAttempt(fresh, attempt + 1); }, 4199 function () { scFail(op, 'Could not switch this item. Please try again.'); }); 4200 }); 4201 } 4202 if (r.status >= 400 && r.status < 500) { scFail(op, 'Could not switch this item. Nothing was changed.'); return; } 4203 directUnknown(); 4204 }, directUnknown); 4205 }, directUnknown); 4206 } 4207 return directAttempt(cart, 0); 4208 } 4209 return addFirst(); 4210 }, function () { scFail(op, 'Cart did not update. Please try again.'); }); 4211 } 4212 4213 function scStep(p, d) { 4214 // A stepper tap: shown immediately, sent as ONE change op per product after the 300 ms window. 4215 if (!scPending[p.key]) { 4216 scPendingOrder.push(p.key); 4217 scPendingLines[p.key] = { vid: String(p.variant), ident: scIdent(p.variant, null, null) }; 4218 } 4219 scPending[p.key] = (scPending[p.key] || 0) + d; 4220 if (!scPending[p.key]) scPendingOrder = scPendingOrder.filter(function (k) { return k !== p.key; }); 4221 p.qty = Math.max(0, p.qty + d); p.inCart = p.qty > 0; 4222 recalcCart(); 4223 } 4224 function scSetQty(p, q) { scStep(p, q - p.qty); } 4225 function collectUpdates() { 4226 // Pending stepper deltas by product key, oldest first. No snapshot, no zeros for untouched lines. 4227 var out = {}; 4228 scPendingOrder.forEach(function (k) { if (scPending[k]) out[k] = scPending[k]; }); 4229 return out; 4230 } 4231 function scFlush() { 4232 if (syncTimer) { clearTimeout(syncTimer); syncTimer = null; } 4233 var deltas = collectUpdates(), lines = scPendingLines; 4234 scPending = {}; scPendingOrder = []; scPendingLines = {};
4235 Object.keys(deltas).forEach(function (k) { 4236 var line = lines[k]; if (!line || !line.vid) return; 4237 var ident = line.ident; 4238 if (line.lineKey) { 4239 scLineOverlay[line.lineKey] = (scLineOverlay[line.lineKey] || 0) + deltas[k]; 4240 scEnqueue({ kind: 'line', key: line.lineKey, ident: ident, delta: deltas[k], strictKey: true, overlayKey: line.lineKey }); 4241 return; 4242 } 4243 scBump(ident, deltas[k]); 4244 scEnqueue({ kind: 'change', vid: line.vid, delta: deltas[k], ident: ident, key: k })['catch'](function () { scBump(ident, -deltas[k]); }); 4245 }); 4246 } 4247 // Only a still-pending purchase is deduped. A deliberate click after completion always adds. 4248 function scGuardCheck(sig) { 4249 var g = scAddBusy[sig]; 4250 if (!g) return null; 4251 if (g.op.terminal) { delete scAddBusy[sig]; return null; } 4252 if (g.op.status === 'uncertain') { g.op.attached = (g.op.attached || 0) + 1; return { attach: g.op }; } 4253 return { busy: g.op }; 4254 } 4255 function scGuardStart(sig, op) { 4256 var g = { op: op }; 4257 scAddBusy[sig] = g; 4258 op.promise.then(function () { if (scAddBusy[sig] === g) delete scAddBusy[sig]; }); 4259 } 4260 function syncCart() { 4261 // 300 ms window: rapid +/- taps become ONE change op per product, in tap order (see scFlush). 4262 if (syncTimer) clearTimeout(syncTimer); 4263 syncTimer = setTimeout(function() { syncTimer = null; scFlush(); }, 300); 4264 } 4265 4266 // GA4 side-cart funnel events (dashboard Decisions tab reads these): 4267 // side_cart_open on every drawer open, side_cart_addon_add on user addon clicks. 4268 function trackSideCart(evt, params) { 4269 try { 4270 var payload = Object.assign({ cart_main: mode }, params || {}); 4271 if (window.posthog && typeof posthog.capture === 'function') { posthog.capture(evt, payload); } 4272 if (typeof gtag === 'function') { gtag('event', evt, payload); } 4273 else { 4274 window.dataLayer = window.dataLayer || []; 4275 dataLayer.push(Object.assign({ event: evt }, payload)); 4276 } 4277 } catch (analyticsError) { /* analytics must not block commerce */ } 4278 } 4279 4280 function trackAdd(p) { 4281 try { 4282 var eid = (typeof genEventId === 'function') ? genEventId('atc') : 'atc_' + Date.now(); 4283 if (typeof fbq === 'function') fbq('track', 'AddToCart', { content_name: p.name, content_ids: [p.variant], value: p.price, currency: 'AUD' }, { eventID: eid }); 4284 window.dataLayer = window.dataLayer || []; 4285 dataLayer.push({ event: 'AddToCart', eventID: eid, content_name: p.name, content_type: 'product', value: p.price, currency: 'AUD', fbp: (typeof getFbCookie === 'function') ? getFbCookie('_fbp') : '', fbc: (typeof getFbCookie === 'function') ? getFbCookie('_fbc') : '' }); 4286 if (typeof gtag === 'function') gtag('event', 'add_to_cart', { currency: 'AUD', value: p.price, items: [{ item_id: p.variant, item_name: p.name, price: p.price, quantity: 1 }] }); 4287 } catch (analyticsError) { /* analytics must not block commerce */ } 4288 } 4289 4290 function addAddon(p, opts) { 4291 opts = opts || {}; 4292 if (scFrozen) return; 4293 if (p.role !== 'addon' || p.inCart || !p.available || !p.variant) return; 4294 var ident = scIdent(p.variant, null, null); 4295 scBump(ident, 1); 4296 p.inCart = true; p.qty = Math.max(1, p.qty + 1); 4297 p.btnEl.innerHTML = 'â Added!'; 4298 p.btnEl.classList.add('sc-added'); 4299 p.btnEl.disabled = true; 4300 if (!opts.silent) { trackAdd(p); trackSideCart('side_cart_addon_add', { addon: p.key }); } 4301 p.itemEl.style.display = 'flex'; 4302 recalcCart(true); 4303 if (opts.instant) { collapseCard(p, true); } 4304 else { setTimeout(function() { collapseCard(p); }, 250); } 4305 var addOp = { kind: 'add', vid: String(p.variant), delta: 1, ident: ident, key: p.key }; 4306 scEnqueue(addOp)['catch'](function () {}); 4307 scGuardStart('addon:' + p.key, addOp); 4308 } 4309 4310 PRODUCTS.forEach(function(p) { 4311 if (!p.ok) return; 4312 p.minusEl.addEventListener('click', function() { 4313 if (scFrozen || scConvertBusy[String(p.variant)] || p.convertFrom) return; 4314 var minQ = (p.role === 'main') ? 1 : 0; 4315 if (p.inCart && p.qty > minQ) scStep(p, -1); 4316 }); 4317 p.plusEl.addEventListener('click', function() { 4318 if (scFrozen || scConvertBusy[String(p.variant)] || p.convertFrom) return; 4319 if (p.inCart && p.qty < 5) scStep(p, 1); 4320 }); 4321 p.btnEl.addEventListener('click', function() { addAddon(p); }); 4322 }); 4323 4324 // ---- Magnesium option selector (powder flavours + tablets) ---- 4325 (function() { 4326 var magP = prod('mag'); 4327 if (!magP || !magP.ok || !MAG_OPTIONS.length) return; 4328 var sel = document.getElementById('scMagFlavour'); 4329 var row = document.getElementById('scMagFlavourRow'); 4330 var upsellPrice = document.getElementById('scMagUpsellPrice'); 4331 var itemFlavour = document.getElementById('scMagItemFlavour'); 4332 var btnLabel = document.getElementById('scMagBtnLabel'); 4333 function applyOption(o, doRecalc) { 4334 var fromVid = String(magP.variant || ''); 4335 var carted = !!(doRecalc && magP.inCart && magP.qty > 0 && fromVid && fromVid !== String(o.id)); 4336 if (doRecalc && (scFrozen || magP.convertFrom || scConvertBusy[fromVid])) { if (sel) sel.value = fromVid; return; } 4337 if (doRecalc) scFlush(); // bind every earlier +/- to fromVid BEFORE changing the row's variant 4338 magP.variant = o.id; magP.price = o.price; magP.name = o.name; 4339 if (upsellPrice) upsellPrice.textContent = '+ ' + fmtMoney(o.price); 4340 if (itemFlavour) itemFlavour.innerHTML = o.title + ' · Relaxation & Recovery'; 4341 if (btnLabel) btnLabel.innerHTML = 'Add Magnesium — ' + fmtMoney(o.price); 4342 var un = document.getElementById('scMagUpsellName'); if (un) un.textContent = o.name; 4343 var im = document.getElementById('scMagItemName'); if (im) im.textContent = o.name; 4344 var ui = document.getElementById('scMagUpsellImg'); if (ui) { ui.src = o.img; ui.alt = o.name; } 4345 var ii = document.getElementById('scMagItemImg'); if (ii) { ii.src = o.img; ii.alt = o.name; } 4346 if (!carted) { if (doRecalc) recalcCart(true); return; } 4347 // Guarded flavour switch: add the new flavour first, remove the old one only once verified. 4348 // The row keeps showing one line (old qty until the new one lands) - see applyRealCart. 4349 function revert() { 4350 for (var i = 0; i < MAG_OPTIONS.length; i++) if (String(MAG_OPTIONS[i].id) === fromVid) { applyOption(MAG_OPTIONS[i], false); break; } 4351 if (sel) sel.value = fromVid; 4352 } 4353 magP.convertFrom = fromVid; 4354 scEnqueue({ kind: 'convert', src: { vid: fromVid, plan: null, props: null }, dst: { vid: String(o.id), plan: null, props: null }, direct: false, label: 'flavour' }) 4355 .then(function (st) { 4356 magP.convertFrom = null; 4357 scUpdateConversionControls(); 4358 // Nothing switched: bind the row and the selector back to the flavour that is really carted. 4359 if (st !== 'ok' && scLastCart && scFindLine(scLastCart, fromVid, null, null) && !scFindLine(scLastCart, o.id, null, null)) revert(); 4360 if (scLastCart) applyRealCart(scLastCart); 4361 }, function () { magP.convertFrom = null; scUpdateConversionControls(); revert(); }); 4362 } 4363 if (sel) { 4364 MAG_OPTIONS.forEach(function(o, i) { 4365 var opt = document.createElement('option'); 4366 opt.value = o.id; 4367 opt.textContent = o.title + ' â ' + fmtMoney(o.price); 4368 if (i === 0) opt.selected = true; 4369 sel.appendChild(opt); 4370 }); 4371 if (row && MAG_OPTIONS.length > 1) row.style.display = 'flex'; 4372 sel.addEventListener('change', function() { 4373 for (var i = 0; i < MAG_OPTIONS.length; i++) { 4374 if (MAG_OPTIONS[i].id === sel.value) { applyOption(MAG_OPTIONS[i], true); break; } 4375 } 4376 }); 4377 } 4378 applyOption(MAG_OPTIONS[0], false); 4379 })(); 4380 4381 function updateShippingBar() { 4382 var pct = Math.min((cartTotal / FREE_SHIP_THRESHOLD) * 100, 100); 4383 barFill.style.width = pct + '%'; 4384 if (cartTotal >= FREE_SHIP_THRESHOLD) { 4385 barFill.classList.add('sc-full'); barFill.classList.add('sc-bar-pulse'); 4386 shipWrap.classList.add('sc-shipping-unlocked'); 4387 shipText.innerHTML = '<span class="sc-truck">ð</span> <span style="color:#16a34a;font-weight:800;">FREE shipping unlocked!</span>'; 4388 } else { 4389 var remaining = FREE_SHIP_THRESHOLD - cartTotal; 4390 barFill.classList.remove('sc-full'); barFill.classList.remove('sc-bar-pulse'); 4391 shipWrap.classList.remove('sc-shipping-unlocked'); 4392 shipText.innerHTML = '<span class="sc-truck">ð</span> <span>You\'re <span class="sc-amount">' + fmtMoney(remaining) + '</span> away from <strong>FREE shipping!</strong></span>'; 4393 } 4394 if (scRenderedTotal !== null) subtotalEl.textContent = scRenderedTotal; 4395 updateDuoNote(); 4396 } 4397 4398 var scOpenerEl = null; 4399 function scTrapFocus(e) { 4400 if (e.key !== 'Tab') return; 4401 // Recomputed per keypress: the drawer's focusable set changes as cards collapse. 4402 var els = Array.prototype.slice.call( 4403 drawer.querySelectorAll("button, [href], input, select, textarea, [tabindex]:not
4403([tabindex='-1'])") 4404 ).filter(function(el) { return !el.disabled && el.offsetParent !== null; }); 4405 if (!els.length) return; 4406 var first = els[0], last = els[els.length - 1]; 4407 if (e.shiftKey && document.activeElement === first) { last.focus(); e.preventDefault(); } 4408 else if (!e.shiftKey && document.activeElement === last) { first.focus(); e.preventDefault(); } 4409 } 4410 // The $50 duo saving is an automatic Buy X Get Y applied at checkout, so the 4411 // drawer's line-item maths can't see it. Say so, or the drawer looks like it 4412 // is charging full price for the bundle. 4413 // Automatic Buy X Get Y: 2 Averas -> 2 Cleaners free, once per order. 4414 var DUO_SAVING = 50; 4415 4416 function updateDuoNote() { 4417 var badge = document.getElementById('scSaveBadge'), was = document.getElementById('scSubtotalWas'); 4418 if (!badge || !was) return; 4419 var discounted = !!(scLastCart && scLastCart.total_discount > 0 && scRenderedDiscount); 4420 badge.classList.toggle('sc-show', discounted); was.classList.toggle('sc-show', discounted); 4421 if (discounted) { badge.textContent = 'Save ' + scRenderedDiscount; was.textContent = scRenderedOriginal || ''; } 4422 } 4423 4424 // The rail test's exposure IS the drawer open, so tag the cart here rather 4425 // than relying on a later sync â some pages write their own cart and only 4426 // re-hydrate, which would leave those buyers with no arm on their order. 4427 var scAbStamped = false; 4428 function stampScAb() { 4429 // Attribution is emitted by trackSideCart. Do not put experiment attributes on the commerce queue. 4430 scAbStamped = true; 4431 } 4432 4433 function openCart() { 4434 stampScAb(); 4435 scOpenerEl = document.activeElement; 4436 drawer.classList.add('sc-open'); 4437 overlay.classList.add('sc-open'); 4438 document.body.style.overflow = 'hidden'; 4439 if (fabEl) fabEl.classList.remove('sc-fab-show'); 4440 trackSideCart('side_cart_open'); 4441 document.addEventListener('keydown', scTrapFocus); 4442 if (closeBtn && closeBtn.focus) closeBtn.focus(); 4443 updateShippingBar(); 4444 } 4445 function closeCart() { 4446 scShowNote(''); 4447 drawer.classList.remove('sc-open'); 4448 overlay.classList.remove('sc-open'); 4449 document.body.style.overflow = ''; 4450 document.removeEventListener('keydown', scTrapFocus); 4451 if (scOpenerEl && scOpenerEl.focus) { try { scOpenerEl.focus(); } catch (err) {} } 4452 scOpenerEl = null; 4453 updateFab(); 4454 } 4455 4456 closeBtn.addEventListener('click', closeCart); 4457 overlay.addEventListener('click', closeCart); 4458 document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeCart(); }); 4459 4460 // One checkout attempt, one navigation permission. No failure-counter bypass. 4461 var scCheckoutLabel = checkoutBtn.innerHTML; 4462 var scCheckoutResetTimer = null, scCheckoutPromise = null, scCheckoutCancel = null; 4463 var scRecoveryKey = 'sc:recovery:v1', scPriorRecovery = null, scReviewNeeded = false; 4464 var scReviewedCart = null, scReviewCheckSeq = 0; // In-memory acknowledgment only; never restored from storage. 4465 try { scPriorRecovery = JSON.parse(sessionStorage.getItem(scRecoveryKey) || 'null'); } catch (ignored) {} 4466 function scRoot() { 4467 var root = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/'; 4468 return root.charAt(root.length - 1) === '/' ? root : root + '/'; 4469 } 4470 function scCommerce(op) { return op.kind !== 'read' && op.kind !== 'attributes' && op.kind !== 'resume'; } 4471 function scOutstanding() { return scOps.filter(function (op) { return scCommerce(op) && op.status !== 'ok' && !(op.terminal && op.id <= scInspected); }); } 4472 function scReviewFingerprint(cart) { 4473 // Full line properties/plan allocation stay in memory, never in diagnostics or sessionStorage. 4474 return JSON.stringify({ cart: scCartSignature(cart), details: cart.items.map(function (line) { 4475 return [line.key, line.properties || {}, line.selling_plan_allocation || null]; 4476 }) }); 4477 } 4478 function scReviewViewMatches(cart) { 4479 var holder = document.getElementById('scServerState'); 4480 return !!(cart && scLastCart && !scViewPending && !scViewError && 4481 drawer.classList.contains('sc-server-rendered') && !drawer.classList.contains('sc-view-unconfirmed') && 4482 holder && scSectionSignature(holder.querySelector('[data-sc-server-render]')) === scCartSignature(cart) && 4483 scReviewFingerprint(scLastCart) === scReviewFingerprint(cart)); 4484 } 4485 function scCanReviewCart(cart, boundary, duringCheckout) { 4486 if (!cart || boundary !== scOpSeq || (scFrozen && !duringCheckout)) return false;
4487 if (scPriorRecovery && scPriorRecovery.until && (!isFinite(Number(scPriorRecovery.until)) || Number(scPriorRecovery.until) > Date.now())) return false; 4488 if (Object.keys(scPending).some(function (key) { return !!scPending[key]; }) || 4489 Object.keys(scConvertBusy).some(function (key) { return !!scConvertBusy[key]; }) || 4490 scOps.some(function (op) { return op.id <= boundary && scCommerce(op) && (!op.terminal || !scTerminal(op)); })) return false; 4491 return scReviewViewMatches(cart); 4492 } 4493 function scWaitForReviewView(cart, boundary, checkSeq, deadline) { 4494 return new Promise(function (resolve) { 4495 function check() { 4496 if (checkSeq !== scReviewCheckSeq || boundary !== scOpSeq || scFrozen || Date.now() >= deadline) { resolve(false); return; } 4497 if (scViewPending) { setTimeout(check, Math.min(40, deadline - Date.now())); return; } 4498 resolve(scCanReviewCart(cart, boundary, false)); 4499 } 4500 check(); 4501 }); 4502 } 4503 function scArmReviewedCart(cart, boundary) { 4504 scReviewedCart = { signature: scReviewFingerprint(cart), boundary: boundary }; 4505 } 4506 var scReviewReadyMessage = 'Your cart is up to date. Review the items above, then select Secure checkout to continue.'; 4507 function scSaveRecovery() { 4508 var ops = scOutstanding(); 4509 if (!ops.length && !scPriorRecovery && !scReviewNeeded) { try { sessionStorage.removeItem(scRecoveryKey); } catch (ignored) {} return; } 4510 // No cart token, line properties, buyer details or complete cart is persisted. 4511 var pending = ops.some(function (op) { return !op.terminal; }); 4512 var context = { version: 1, count: ops.length, until: pending ? Date.now() + 65000 : 0, 4513 actions: ops.slice(-10).map(function (op) { return { kind: op.kind, status: op.status }; }) }; 4514 if (scPriorRecovery) context.until = Math.max(context.until, scPriorRecovery.until || 0); 4515 try { sessionStorage.setItem(scRecoveryKey, JSON.stringify(context)); } catch (ignored) {} 4516 } 4517 function scRecoveryNotice(message) { 4518 scReviewNeeded = true; 4519 scSaveRecovery(); 4520 scShowNote(message + ' <button type="button" class="sc-note-btn" data-sc-check>Check cart</button> <a class="sc-note-btn" href="' + scRoot() + 'cart?sc_review=1">
4520Review cart</a>', true); 4521 } 4522 function scResetCheckoutBtn() { 4523 checkoutBtn.style.pointerEvents = ''; 4524 checkoutBtn.disabled = false; 4525 checkoutBtn.removeAttribute('aria-busy'); 4526 if (checkoutBtn.classList.contains('sc-blocked')) { scApplySoldout(); return; } 4527 checkoutBtn.innerHTML = scCheckoutLabel; 4528 } 4529 function scUnfreeze() { 4530 scFrozen = false; scCheckoutBusy = false; 4531 drawer.classList.remove('sc-checking-out'); 4532 if (scCheckoutResetTimer) { clearTimeout(scCheckoutResetTimer); scCheckoutResetTimer = null; } 4533 } 4534 function scCheckCart(background) { 4535 scReviewedCart = null; 4536 var checkSeq = ++scReviewCheckSeq, deadline = Date.now() + 8000; 4537 var reading = scEnqueue({ kind: 'read' }), boundary = scOpSeq; 4538 return reading.then(function (status) { 4539 if (status !== 'ok') { scRecoveryNotice('We cannot read your cart. Please check your connection.'); return status; } 4540 scOps.forEach(function (op) { 4541 if (op.status !== 'uncertain' || !op.verify || !scLastCart) return; 4542 var verified = false; try { verified = op.verify(scLastCart); } catch (ignored) {} 4543 if (!verified) return; 4544 // Check cart is read-only. An existing conversion watcher, not this button, 4545 // owns any previously accepted replacement cleanup. 4546 if (!op.resume) op.settle('ok'); 4547 }); 4548 var cart = scLastCart; 4549 return scWaitForReviewView(cart, boundary, checkSeq, deadline).then(function (ready) { 4550 if (checkSeq !== scReviewCheckSeq || scFrozen) return status; 4551 if (scPriorRecovery || scOutstanding().length) { 4552 if (ready && !background) { scArmReviewedCart(cart, boundary); scRecoveryNotice(scReviewReadyMessage); } 4553 else if (ready) scRecoveryNotice('Your current cart is shown. Review it before continuing.'); 4554 else scRecoveryNotice('We cannot yet confirm your current items. Please check or review your cart.'); 4555 } else if (ready) { scReviewNeeded = false; scShowNote(''); scSaveRecovery(); } 4556 return status; 4557 }); 4558 }); 4559 } 4560 document.addEventListener('click', function (e) { 4561 var button = e.target.closest && e.target.closest('[data-sc-check]'); 4562 if (!button || button.disabled) return; 4563 button.disabled = true; 4564 scCheckCart().then(function () { button.disabled = false; }, function () { button.disabled = false; }); 4565 }); 4566 function scTrackCheckout(cart) { 4567 // Preserve the existing channels, once at the verified checkout handoff. 4568 // Use Shopify's complete cart, not catalog-only client totals or quantities. 4569 var value = cart.total_price / 100, currency = cart.currency, eid = 'ic_' + Date.now(); 4570 try { if (typeof genEventId === 'function') eid = genEventId('ic') || eid; } catch (ignored) {} 4571 try { if (typeof fbq === 'function') fbq('track', 'InitiateCheckout', { value: value, currency: currency, num_items: cart.item_count }, { eventID: eid }); } catch (ignored) {} 4572 var fbp = '', fbc = ''; 4573 try { if (typeof getFbCookie === 'function') fbp = getFbCookie('_fbp'); } catch (ignored) {} 4574 try { if (typeof getFbCookie === 'function') fbc = getFbCookie('_fbc'); } catch (ignored) {} 4575 try { 4576 window.dataLayer = window.dataLayer || []; 4577 window.dataLayer.push({ event: 'InitiateCheckout', eventID: eid, value: value, currency: currency, fbp: fbp, fbc: fbc }); 4578 } catch (ignored) {} 4579 try { if (typeof gtag === 'function') gtag('event', 'begin_checkout', { currency: currency, value: value }); } catch (ignored) {} 4580 try { if (window.posthog && typeof window.posthog.capture === 'function') window.posthog.capture('side_cart_checkout_click', { cart_main: mode }); } catch (ignored) {} 4581 try { 4582 if (typeof gtag === 'function') gtag('event', 'side_cart_checkout_click', { cart_main: mode }); 4583 else { 4584 window.dataLayer = window.dataLayer || []; 4585 window.dataLayer.push({ event: 'side_cart_checkout_click', cart_main: mode }); 4586 } 4587 } catch (ignored) {} 4588 } 4589 4590 // Diagnostics never participate in the cart/checkout boundary. Only aggregate state is 4591 // allowed here: no cart snapshot, token, product/line IDs, properties or error messages. 4592 var scCheckoutDiagnosticSeq = 0; 4593 function scCaptureCheckoutDiagnostic(event, attempt, outcome) { 4594 try { 4595 if (!attempt || !window.posthog || typeof window.posthog.capture !== 'function') return; 4596 var statuses = { queued: 0, inflight: 0, uncertain: 0, ok: 0, rejected: 0, partial: 0, unconfirmed: 0, other: 0 }; 4597 var commerce = 0, outstanding = 0, pending = 0; 4598 scOps.forEach(function (op) {
4599 // Do not copy dynamic keys or operation objects into analytics. 4600 var status = Object.prototype.hasOwnProperty.call(statuses, op.status) ? op.status : 'other'; 4601 statuses[status]++; 4602 if (scCommerce(op)) { commerce++; if (op.status !== 'ok' && !(op.terminal && op.id <= scInspected)) outstanding++; } 4603 if (!op.terminal) pending++; 4604 }); 4605 var payload = { 4606 diagnostic_version: 1, 4607 attempt_id: attempt.id, 4608 elapsed_ms: Math.max(0, Date.now() - attempt.started), 4609 operation_count: scOps.length, 4610 commerce_operation_count: commerce, 4611 outstanding_commerce_count: outstanding, 4612 pending_operation_count: pending, 4613 operation_status_counts: statuses, 4614 pending_stepper_count: Object.keys(scPending).filter(function (key) { return !!scPending[key]; }).length, 4615 prior_recovery: !!scPriorRecovery, 4616 review_needed: !!scReviewNeeded, 4617 review_armed: !!(scReviewedCart && scReviewedCart.boundary === scOpSeq), 4618 view_pending: !!scViewPending, 4619 view_error: !!scViewError, 4620 paint_failure_count: scPaintFailures, 4621 server_rendered: drawer.classList.contains('sc-server-rendered'), 4622 view_unconfirmed: drawer.classList.contains('sc-view-unconfirmed'), 4623 stock_pending: !!scStockPending, 4624 stock_unknown: !!scStockUnknown, 4625 soldout_item_count: Object.keys(scSoldoutIds).length 4626 }; 4627 if (outcome) payload.outcome = outcome; 4628 var captured = window.posthog.capture(event, payload); 4629 // Also tolerate a custom analytics adapter returning a rejected promise. 4630 if (captured && typeof captured.catch === 'function') captured.catch(function () {}); 4631 } catch (ignored) {} // Includes payload construction and analytics getters, not just capture(). 4632 } 4633 function scStartCheckoutDiagnostic() { 4634 try { 4635 var started = Date.now(); 4636 var attempt = { id: 'sc_' + started.toString(36) + '_' + (++scCheckoutDiagnosticSeq) + '_' + Math.random().toString(36).slice(2, 8), 4637 started: started, resultSent: false, navigationFailed: false }; 4638 scCaptureCheckoutDiagnostic('side_cart_checkout_attempt', attempt); 4639 return attempt; 4640 } catch (ignored) { return null; } 4641 } 4642 function scFinishCheckoutDiagnostic(attempt, outcome) { 4643 try { 4644 if (!attempt || attempt.resultSent) return; 4645 attempt.resultSent = true; 4646 scCaptureCheckoutDiagnostic('side_cart_checkout_result', attempt, outcome); 4647 } catch (ignored) {} 4648 } 4649 function scFailCheckoutNavigationDiagnostic(attempt, outcome) { 4650 try { 4651 if (!attempt || attempt.navigationFailed) return; 4652 attempt.navigationFailed = true; 4653 scCaptureCheckoutDiagnostic('side_cart_checkout_navigation_failed', attempt, outcome); 4654 } catch (ignored) {} 4655 } 4656 4657 function scCheckout() { 4658 if (scCheckoutBusy) return scCheckoutPromise || Promise.resolve('pending'); 4659 var diagnosticAttempt = scStartCheckoutDiagnostic(); 4660 if (checkoutBtn.classList.contains('sc-blocked')) { scApplySoldout(); scFinishCheckoutDiagnostic(diagnosticAttempt, 'unavailable'); return Promise.resolve('unavailable'); } 4661 scFlush(); 4662 var boundary = scOpSeq, seq = ++scCheckoutSeq, started = Date.now(), finish; 4663 scCheckoutPromise = new Promise(function (resolve) { finish = resolve; }); 4664 scCheckoutBusy = true; scFrozen = true; 4665 drawer.classList.add('sc-checking-out'); 4666 checkoutBtn.disabled = true; checkoutBtn.setAttribute('aria-busy', 'true'); 4667 checkoutBtn.textContent = 'Going to checkoutâ¦'; 4668 function active() { return seq === scCheckoutSeq && scCheckoutBusy; } 4669 function stay(status, message) { 4670 if (!active()) return; 4671 ++scCheckoutSeq; // revoke permission before releasing the controls 4672 scUnfreeze(); scResetCheckoutBtn(); 4673 if (message) scRecoveryNotice(message); 4674 scCheckoutCancel = null; 4675 scFinishCheckoutDiagnostic(diagnosticAttempt, status); 4676 finish(status); 4677 } 4678 scCheckoutCancel = function () { stay('cancelled'); }; 4679 scCheckoutResetTimer = setTimeout(function () { stay('timeout', 'Your cart is taking longer to confirm. Please check it before continuing.'); }, 8000); 4680 function judge() { 4681 if (!active()) return; 4682 var ops = scOps.filter(function (op) { return op.id <= boundary && scCommerce(op); }); 4683 if (ops.some(function (op) { return !op.terminal; })) { setTimeout(judge, 40); return; } 4684 var needsReview = !!scPriorRecovery || ops.some(function (op) { return op.status !== 'ok' && op.id > scInspected; }); 4685 var remaining = Math.max(1, 8000 - (Date.now() - started)); 4686 scReadCartCapped(remaining).then(function (cart) { 4687 if (!active()) return; 4688 if (!cart || !scValidCart(cart)) { stay('unreadable', 'We cannot confirm your cart. Please check your connection.'); return; } 4689 scApplyServer(cart); 4690 if (!cart.items.length) { stay('empty'); return; } 4691 function continueWhenPainted() { 4692 if (!active()) return; 4693 if (scViewPending) { setTimeout(continueWhenPainted, 40); return; } 4694 if (scLastCart && scCartSignature(scLastCart) !== scCartSignature(cart)) { judge(); return; } 4695 if (scViewError) { stay('display', 'Your cart updated, but its display could not refresh. Please review the current items.'); return; } 4696 // Section availability is immediate; legacy/missing metadata gets only 4697 // the remaining checkout deadline. Never outrun an unresolved stock check. 4698 if (scStockPending) { setTimeout(continueWhenPainted, 40); return; } 4699 if (scStockUnknown) { stay('availability', 'We cannot confirm item availability. Please check your cart before continuing.'); return; } 4700 if (Object.keys(scSoldoutIds).length || checkoutBtn.classList.contains('sc-blocked')) { stay('unavailable'); return; } 4701 if (needsReview) { 4702 if (!scCanReviewCart(cart, boundary, true)) { 4703 scReviewedCart = null; 4704 stay('review', 'We cannot yet confirm your current items. Please check or review your cart.'); return; 4705 } 4706 if (!scReviewedCart || scReviewedCart.boundary !== boun
4706dary || scReviewedCart.signature !== scReviewFingerprint(cart)) { 4707 scArmReviewedCart(cart, boundary); 4708 stay('review', scReviewReadyMessage); return; 4709 } 4710 // The shopper reviewed this exact rendered cart and explicitly pressed checkout again. 4711 // Retire only settled history; never retry writes or erase an unresolved conversion. 4712 scInspected = Math.max(scInspected, boundary); 4713 scPriorRecovery = null; scReviewedCart = null; 4714 } 4715 // Analytics is best effort and never part of the accepted commerce boundary. 4716 try { scTrackCheckout(cart); } catch (ignored) {} 4717 scReviewNeeded = false; scSaveRecovery(); 4718 ++scCheckoutSeq; 4719 clearTimeout(scCheckoutResetTimer); scCheckoutResetTimer = null; 4720 scCheckoutCancel = null; scFinishCheckoutDiagnostic(diagnosticAttempt, 'navigating'); finish('navigating'); 4721 var navigationSeq = scCheckoutSeq; 4722 scCheckoutResetTimer = setTimeout(function () { 4723 if (navigationSeq !== scCheckoutSeq) return; 4724 scFailCheckoutNavigationDiagnostic(diagnosticAttempt, 'watchdog'); 4725 ++scCheckoutSeq; scUnfreeze(); scResetCheckoutBtn(); 4726 scRecoveryNotice('Checkout did not open. Please review your cart.'); 4727 }, 8000); 4728 try { window.location.assign(scRoot() + 'checkout'); } 4729 catch (error) { scFailCheckoutNavigationDiagnostic(diagnosticAttempt, 'exception'); scUnfreeze(); scResetCheckoutBtn(); scRecoveryNotice('Checkout could not open. Please review your cart.'); } 4730 } 4731 continueWhenPainted(); 4732 }, function () { stay('unreadable', 'We cannot confirm your cart. Please check your connection.'); }); 4733 } 4734 judge(); 4735 return scCheckoutPromise; 4736 } 4737 checkoutBtn.addEventListener('click', scCheckout); 4738 window.addEventListener('pagehide', function () { 4739 scReviewedCart = null; ++scReviewCheckSeq; 4740 if (scCheckoutCancel) scCheckoutCancel(); 4741 ++scCheckoutSeq; scSaveRecovery(); 4742 }); 4743 window.addEventListener('pageshow', function (e) { 4744 if (!e.persisted) return; 4745 scReviewedCart = null; ++scReviewCheckSeq; 4746 if (scCheckoutCancel) scCheckoutCancel(); 4747 ++scCheckoutSeq; scUnfreeze(); scResetCheckoutBtn(); 4748 scCheckCart(true); 4749 }); 4750 var scRefreshTimer = null; 4751 function scRefreshOnReturn() { 4752 if (document.hidden || scFrozen || scRefreshTimer) return; 4753 scRefreshTimer = setTimeout(function () { scRefreshTimer = null; scEnqueue({ kind: 'read' }); }, 100); 4754 } 4755 window.addEventListener('focus', scRefreshOnReturn); 4756 document.addEventListener('visibilitychange', scRefreshOnReturn); 4757 window.addEventListener('storage', function (e) { if (e.key === 'sc:changed:v1') scRefreshOnReturn(); }); 4758 4759 // Compatibility purchase entry: explicit additive group, pending-only dedupe in the shared API. 4760 function scBuy(items, missing) { 4761 var purchase = items.map(function (item) { return { id: prod(item.key).variant, quantity: item.qty }; }); 4762 var pending = window.scCart.add(purchase); 4763 if (missing && missing.indexOf('cleaner') !== -1) scShowNote('Cleaners are unavailable right now, so only the devices were added.', true); 4764 return pending; 4765 } 4766 // Back-compat API: openSideCart() | openSideCart({cleaner:true}) | openSideCart({duo:true}) | openSideCart('gst'|'avera') | openSideCart({add:[{key,qty}]}) 4767 window.openSideCart = function(arg) { 4768 var opts = {}; 4769 var targetMode = mode; 4770 if (typeof arg === 'string') { targetMode = arg; } 4771 else if (arg && typeof arg === 'object') { opts = arg; } 4772 if (!MODES[targetMode]) targetMode = 'avera'; 4773 if (opts.optimistic) { setMode(targetMode, true); openCart(); refreshSideCart(); return; } 4774 var items = []; 4775 if (opts.add && opts.add.length) { 4776 opts.add.forEach(function (it) { items.push({ key: it.key, qty: it.qty || 1 }); }); 4777 } else { 4778 items.push({ key: targetMode, qty: opts.duo ? 2 : 1 }); 4779 if (opts.duo) items.push({ key: 'cleaner', qty: 2 }); 4780 else if (opts.cleaner) items.push({ key: 'cleaner', qty: 1 }); 4781 } 4782 setMode(targetMode, true); 4783 var missing = []; 4784 items = items.filter(function (it) { 4785 var p = prod(it.key); 4786 if (p && p.ok && p.available && p.variant) return true; 4787 missing.push(it.key); 4788 return false;
4789 }); 4790 if (!scFrozen) { 4791 if (items.length) scBuy(items, missing); 4792 else if (missing.length) scShowNote('Sorry, that item is unavailable right now.'); 4793 } 4794 openCart(); 4795 }; 4796 4797 // Page API v2: pages never write the cart themselves when this exists. 4798 window.scCart = { 4799 version: 2, 4800 add: function (items) { return scApiGroup(items, false); }, 4801 setQuantities: function (items) { return scApiGroup(items, true); }, 4802 buyNow: function (items) { return scApiGroup(items, true, true); }, 4803 open: function (targetMode) { 4804 scPaint(function () { if (targetMode && MODES[targetMode]) setMode(targetMode, true); openCart(); }); 4805 return scEnqueue({ kind: 'read' }); 4806 }, 4807 checkout: scCheckout, 4808 check: scCheckCart, 4809 converting: function (vid) { return !!scConvertBusy[String(vid)]; }, 4810 changeLine: function (key, quantity) { 4811 if (scFrozen) return Promise.reject(new Error('checkout_in_progress')); 4812 var ident = ''; 4813 ((scLastCart && scLastCart.items) || []).forEach(function (it) { if (it.key === key) ident = scLineIdent(it); }); 4814 return scEnqueue({ kind: 'line', key: key, ident: ident, target: Math.max(0, quantity | 0) }); 4815 }, 4816 convert: function (spec) { 4817 if (scFrozen) return Promise.reject(new Error('checkout_in_progress')); 4818 return scEnqueue({ kind: 'convert', 4819 src: { vid: String(spec.from.id), plan: spec.from.selling_plan || null, props: spec.from.properties || null, key: spec.from.key || null }, 4820 dst: { vid: String(spec.to.id), plan: spec.to.selling_plan || null, props: spec.to.properties || null }, 4821 direct: !!spec.direct, label: spec.label || 'convert' }); 4822 }, 4823 setAttributes: function (attrs) { 4824 if (scFrozen) return Promise.reject(new Error('checkout_in_progress')); 4825 return scEnqueue({ kind: 'attributes', attrs: attrs || {} }); 4826 }, 4827 read: function () { return scEnqueue({ kind: 'read' }); }, 4828 last: function () { return scLastCart; }, 4829 whenIdle: scWhenIdle, 4830 frozen: function () { return scFrozen; }, 4831 viewError: function () { return !!scViewError; } 4832 }; 4833 4834 // Cart view for header cart icons: show the real cart, never force the page's product in. 4835 window.viewSideCart = function () { return window.scCart.open(); }; 4836 4837 // Initial visual state only â no cart POST until the user opens the drawer. 4838 setMode(mode, true); 4839 4840 // ---- Real-cart hydration (27/07/2026) ---- 4841 // Read the actual Shopify cart on load so returning visitors see what is already in it 4842 // (floating badge + populated drawer) and cart syncs can never wipe pre-existing items. 4843 function knownVariantIds() { 4844 // Line KEYS currently represented by a PRODUCTS row (the property-less one-time line of its 4845 // variant). Every other line - a second flavour, a propertied duplicate, a subscription - is its own row. 4846 var keys = {}; 4847 PRODUCTS.forEach(function(p) { 4848 if (p.ok && p.variant && p.lineKey && p.inCart && p.role !== 'hidden') keys[p.lineKey] = true; 4849 if (p.convertFromKey) keys[p.convertFromKey] = true; // old flavour, mid-switch: still shown on the row 4850 }); 4851 return keys; 4852 } 4853 4854 // ---- Sold-out cart lines (28/08/2026) ---- 4855 // Confirmed Liquid rows carry stock availability. Only older/missing metadata needs 4856 // a product lookup; its response can never overwrite a newer rendered row verdict. 4857 var scAvailCache = {}, scAvailPending = {}; 4858 var scSectionStock = {}, scSectionStockSignature = null; 4859 var scStockPending = false, scStockUnknown = false; 4860 var scSoldoutIds = {}; 4861 function scStockFromSection(line) { 4862 if (!scLastCart || scSectionStockSignature !== scCartSignature(scLastCart)) return null; 4863 return typeof scSectionStock[line.key] === 'boolean' ? scSectionStock[line.key] : null; 4864 } 4865 function scStockValue(line) { 4866 var sectionValue = scStockFromSection(line); 4867 if (sectionValue !== null) return sectionValue; 4868 var product = line.handle && scAvailCache[line.handle]; 4869 if (product && product.__gone) return false; 4870 return product && typeof product[String(line.variant_id)] === 'boolean' ? product[String(line.variant_id)] : null; 4871 } 4872 function scRefreshStockState() { 4873 scSoldoutIds = {}; scStockPending = false; scStockUnknown = false;
4874 ((scLastCart && scLastCart.items) || []).forEach(function (line) { 4875 var available = scStockValue(line); 4876 if (available === false) scSoldoutIds[String(line.variant_id)] = true; 4877 if (available === null) { 4878 scStockUnknown = true; 4879 if (line.handle && scAvailPending[line.handle]) scStockPending = true; 4880 } 4881 }); 4882 scPaint(function () { scApplySoldout(); }); 4883 } 4884 function scLookupAvailability(items) { 4885 var handles = []; 4886 items.forEach(function (line) { 4887 if (scStockValue(line) === null && line.handle && !scAvailPending[line.handle] && handles.indexOf(line.handle) === -1) handles.push(line.handle); 4888 }); 4889 handles.forEach(function (handle) { 4890 scAvailPending[handle] = scFetchT('/products/' + handle + '.js', { cache: 'no-store', headers: { 'Accept': 'application/json' } }, 8000) 4891 .then(function (r) { if (r.status === 404) return { __gone: true }; return r.ok ? r.json() : null; }) 4892 .then(function (product) { 4893 if (!product) { scAvailCache[handle] = null; return; } 4894 var available = {}; 4895 if (product.__gone) available.__gone = true;
4896 if (Array.isArray(product.variants)) product.variants.forEach(function (variant) { 4897 if (variant && typeof variant.available === 'boolean') available[String(variant.id)] = variant.available; 4898 }); 4899 scAvailCache[handle] = available; 4900 }, function () { scAvailCache[handle] = null; }) 4901 .then(function () { 4902 delete scAvailPending[handle]; 4903 // Always use current cart/section state, never the captured pre-request items. 4904 scRefreshStockState(); 4905 }); 4906 }); 4907 scRefreshStockState(); 4908 } 4909 function scAcceptSectionStock(root, cart) { 4910 var stock = {}; 4911 Array.prototype.forEach.call(root.querySelectorAll('[data-sc-line-key]'), function (row) { 4912 var value = row.getAttribute('data-sc-available'); 4913 if (value === 'true' || value === 'false') stock[row.getAttribute('data-sc-line-key')] = value === 'true'; 4914 }); 4915 scSectionStock = stock; scSectionStockSignature = scCartSignature(cart); 4916 scLookupAvailability(cart.items); 4917 } 4918 function scSoldoutState(vid) { 4919 var holder = document.getElementById('scServerState'); 4920 var rendered = holder && holder.querySelector('[data-sc-variant="' + vid + '"]'); 4921 if (rendered) return rendered; 4922 if (drawer.classList.contains('sc-server-rendered')) return false; 4923 // -> row element to badge, or true (active, no row: mag), or false (line gone) 4924 var p = null; 4925 PRODUCTS.forEach(function (x) { if (String(x.variant) === vid) p = x; }); 4926 if (p) return (p.ok && p.inCart && p.role !== 'hidden') ? p.itemEl : false;
4927 var other = itemsWrap.querySelector('.sc-item-other[data-scvid="' + vid + '"]'); 4928 if (other) return other; 4929 var mag = document.getElementById('scItemMag'); 4930 return !!(mag && mag.style.display !== 'none'); 4931 } 4932 function scApplySoldout() { 4933 var marked = itemsWrap.querySelectorAll('.sc-item-soldout'); 4934 for (var i = 0; i < marked.length; i++) { 4935 var oldBadge = marked[i].querySelector('.sc-soldout-badge'); 4936 if (oldBadge) oldBadge.parentNode.removeChild(oldBadge); 4937 marked[i].classList.remove('sc-item-soldout'); 4938 } 4939 var any = false; 4940 for (var vid in scSoldoutIds) { 4941 if (!scSoldoutIds[vid]) continue; 4942 var state = scSoldoutState(vid); 4943 if (!state) continue; 4944 any = true; 4945 if (state !== true && state.classList) { 4946 state.classList.add('sc-item-soldout'); 4947 var nameEl = state.querySelector('.sc-item-name'); 4948 if (nameEl && !nameEl.querySelector('.sc-soldout-badge')) { 4949 var badge = document.createElement('span'); 4950 badge.className = 'sc-soldout-badge'; 4951 badge.textContent = 'Sold out'; 4952 nameEl.appendChild(badge); 4953 } 4954 } 4955 } 4956 if (any) { 4957 if (!checkoutBtn.__scHeldLabel) checkoutBtn.__scHeldLabel = scCheckoutBusy ? scCheckoutLabel : checkoutBtn.innerHTML; 4958 checkoutBtn.classList.add('sc-blocked'); 4959 checkoutBtn.setAttribute('aria-disabled', 'true'); 4960 checkoutBtn.innerHTML = 'Remove sold-out items to check out'; 4961 } else if (checkoutBtn.__scHeldLabel) { 4962 checkoutBtn.classList.remove('sc-blocked'); 4963 checkoutBtn.removeAttribute('aria-disabled'); 4964 checkoutBtn.innerHTML = checkoutBtn.__scHeldLabel; 4965 checkoutBtn.__scHeldLabel = null; 4966 } 4967 } 4968 4969 function scCartSignature(cart) { 4970 return JSON.stringify({ currency: cart.currency, total_price: cart.total_price, 4971 items: cart.items.map(function (it) { return [it.key, String(it.variant_id), it.quantity, 4972 it.selling_plan_allocation ? String(it.selling_plan_allocation.selling_plan.id) : '', it.final_line_price]; }) }); 4973 } 4974 function scSectionRoot(html) { 4975 if (typeof html !== 'string' || !html) return null; 4976 var host = document.createElement('div'); host.innerHTML = html; 4977 return host.querySelector('[data-sc-server-render]'); 4978 } 4979 function scSectionSignature(root) { 4980 var node = root && root.querySelector('[data-sc-render-signature]'); 4981 if (!node) return null; 4982 try { return JSON.stringify(JSON.parse(node.textContent)); } catch (error) { return null; } 4983 } 4984 function scPaintSection(root, cart) { 4985 var holder = document.getElementById('scServerState'); 4986 if (!holder || !root || scSectionSignature(root) !== scCartSignature(cart)) return false; 4987 var total = root.querySelector('[data-sc-total-text]'); 4988 if (!total) throw new Error('cart_section_missing_total'); 4989 var rows = root.querySelectorAll('[data-sc-line-key]'); 4990 if (rows.length !== cart.items.length || Array.prototype.some.call(rows, function (row) { return !scExactLine(cart, row.getAttribute('data-sc-line-key')); })) throw new Error('cart_section_missing_lines'); 4991 // Validate the incoming section completely before replacing the usable current view. 4992 if (root.parentNode !== holder) { holder.innerHTML = ''; holder.appendChild(root); } 4993 scRenderedTotal = total.textContent; 4994 var original = root.querySelector('[data-sc-original-total-text]'), discount = root.querySelector('[data-sc-discount-text]'); 4995 scRenderedOriginal = original ? original.textContent : null; scRenderedDiscount = discount ? discount.textContent : null; 4996 subtotalEl.textContent = scRenderedTotal; 4997 drawer.classList.add('sc-server-rendered'); 4998 scSectionPendingSignature = null; 4999 scAcceptSectionStock(root, cart); 5000 scPaintLineControls(); updateDuoNote(); 5001 scClearDisplayNotice('[data-sc-view-note], [data-sc-hydration-note]'); 5002 scSetViewStatus(true, false); 5003 ++scSectionRequest; // Only a completed paint supersedes older in-flight section replies. 5004 return true; 5005 } 5006 function scSetViewStatus(current, pending) { 5007 scViewPending = !current && !!pending; 5008 drawer.classList.toggle('sc-view-unconfirmed', !current); 5009 drawer.setAttribute('data-sc-view-pending', scViewPending ? 'true' : 'false'); 5010 var holder = document.getElementById('scServerState'); 5011 if (holder) holder.setAttribute('aria-busy', scViewPending ? 'true' : 'false'); 5012 if (!current) subtotalEl.textContent = pending ? 'Checkingâ¦' : 'Unavailable'; 5013 } 5014 function scClearDisplayNotice(selector) { 5015 var note = document.getElementById('scNote'); if (!note) return; 5016 Array.prototype.forEach.call(note.querySelectorAll(selector), function (node) { node.parentNode.removeChild(node); }); 5017 if (!note.textContent.trim() && !note.querySelector('button, a')) scShowNote(''); 5018 } 5019 function scViewNotice(message, controls) { 5020 scClearDisplayNotice('[data-sc-view-note]'); 5021 var note = document.getElementById('scNote'); if (!note) return; 5022 if (note.style.display === 'none') note.innerHTML = ''; 5023 var own = document.createElement('span'); own.setAttribute('data-sc-view-note', ''); 5024 own.style.display = 'block'; 5025 own.textContent = message;
5026 if (controls) own.insertAdjacentHTML('beforeend', ' <button type="button" class="sc-note-btn" data-sc-check>Check cart</button> <a class="sc-note-btn" href="' + scRoot() + 'cart?sc_review=1">Review cart</a>'); 5027 note.appendChild(own); note.style.display = 'block'; 5028 if (scNoteTimer) { clearTimeout(scNoteTimer); scNoteTimer = null; } 5029 } 5030 function scRenderConfirmedCart(cart) { 5031 var signature = scCartSignature(cart), holder = document.getElementById('scServerState'); 5032 var mounted = holder && holder.querySelector('[data-sc-server-render]'); 5033 var bundled = scSectionRoot(scSectionCandidate); scSectionCandidate = null; 5034 var paintSource = scSectionSignature(bundled) === signature ? bundled : (scSectionSignature(mounted) === signature ? mounted : null); 5035 if (paintSource) { 5036 var complete = false; 5037 scPaint(function () { complete = scPaintSection(paintSource, cart); }, false); 5038 if (complete) { scViewError = null; return; } 5039 ++scSectionRequest; scSectionPendingSignature = null; 5040 scViewError = new Error('cart_section_unavailable'); 5041 scPaint(function () { 5042 scSetViewStatus(false, false); 5043 scViewNotice('We could not refresh your current items. Please check or review your cart.', true); 5044 }); 5045 return; 5046 } 5047 scSetViewStatus(false, true); scViewError = new Error('cart_view_pending'); 5048 scPaintLineControls(); 5049 scViewNotice('Updating your cart displayâ¦', false); 5050 if (scSectionPendingSignature === signature) return; 5051 scSectionPendingSignature = signature; 5052 var request = ++scSectionRequest; 5053 var deadline = Date.now() + 8000; 5054 function current() { return request === scSectionRequest && scLastCart && scCartSignature(scLastCart) === signature; } 5055 function unavailable() { 5056 if (!current()) return; 5057 scSectionPendingSignature = null; scViewError = new Error('cart_section_unavailable'); 5058 scPaint(function () { 5059 scSetViewStatus(false, false); 5060 scViewNotice('We could not refresh your current items. Please check or review your cart.', true); 5061 }); 5062 } 5063 function readSection(attempt) { 5064 if (!current()) return; 5065 var remaining = deadline - Date.now(); 5066 if (remaining <= 0) { unavailable(); return; } 5067 // A stale/null section gets one fresh READ, never a repeated cart mutation. 5068 scFetchT(scLocaleRoot() + '?sections=side-cart-state', { cache: 'no-store', headers: { 'Accept': 'application/json' } }, remaining).then(function (r) { 5069 if (!current()) return; 5070 var root = r.ok && r.body ? scSectionRoot(r.body['side-cart-state']) : null; 5071 var success = false; 5072 var painted = scPaint(function () { success = scPaintSection(root, scLastCart); }); 5073 if (success) { scViewError = null; return; } 5074 // Do not mask a DOM exception with more requests. The single retry shares this deadline. 5075 if (painted && attempt === 0 && deadline - Date.now() > 150) { 5076 setTimeout(function () { readSection(1); }, 150); return; 5077 } 5078 unavailable(); 5079 }, unavailable); 5080 } 5081 readSection(0); 5082 } 5083 function scExactLine(cart, key) { 5084 var items = (cart && cart.items) || []; 5085 for (var i = 0; i < items.length; i++) if (items[i].key === key) return items[i]; 5086 return null; 5087 } 5088 function scTotalQty(cart, ident) { 5089 return ((cart && cart.items) || []).reduce(function (sum, line) { return sum + (scLineIdent(line) === ident ? line.quantity : 0); }, 0); 5090 } 5091 function scPaintLineControls() { 5092 var holder = document.getElementById('scServerState'); if (!holder) return; 5093 var currentView = !!scLastCart && scSectionSignature(holder.querySelector('[data-sc-server-render]')) === scCartSignature(scLastCart); 5094 Array.prototype.forEach.call(holder.querySelectorAll('[data-sc-line-key]'), function (row) { 5095 var key = row.getAttribute('data-sc-line-key'), line = scExactLine(scLastCart, key); 5096 if (!line) { 5097 row.setAttribute('aria-busy', 'true'); 5098 Array.prototype.forEach.call(row.querySelectorAll('[data-sc-action]'), function (control) { control.disabled = true; }); 5099 var unavailableLabel = row.querySelector('[data-sc-line-pending]'); 5100 if (unavailableLabel) { unavailableLabel.style.display = ''; unavailableLabel.textContent = scLastCart ? 'Please review cart' : 'Checking cartâ¦'; } 5101 return; 5102 } 5103 var pending = (scPending['line:' + key] || 0) + (scLineOverlay[key] || 0); 5104 var busy = !!scConvertBusy[String(line.variant_id)]; 5105 row.setAttribute('aria-busy', busy || pending !== 0 || !currentView ? 'true' : 'false'); 5106 var qty = row.querySelector('[data-sc-line-qty]'); if (qty) qty.textContent = Math.max(0, line.quantity + pending); 5107 var pendingLabel = row.querySelector('[data-sc-line-pending]'); 5108 if (pendingLabel) { pendingLabel.style.display = busy || pending !== 0 || !currentView ? '' : 'none'; pendingLabel.textContent = !currentView && !scViewPending ? 'Please review cart' : 'Updatingâ¦'; } 5109 Array.prototype.forEach.call(row.querySelectorAll('[data-sc-action]'), function (control) { control.disabled = busy || !currentView; }); 5110 }); 5111 } 5112 function scStepLine(line, delta) { 5113 var slot = 'line:' + line.key; 5114 if (!scPending[slot]) { 5115 scPendingOrder.push(slot); 5116 scPendingLines[slot] = { vid: String(line.variant_id), ident: scLineIdent(line), lineKey: line.key }; 5117 } 5118 scPending[slot] = (scPending[slot] || 0) + delta; 5119 if (!scPending[slot]) scPendingOrder = scPendingOrder.filter(function (key) { return key !== slot; }); 5120 scPaint(function () { scPaintLineControls(); }); syncCart(); 5121 } 5122 function scLineAction(event) { 5123 var control = event.target && event.target.closest && event.target.closest('[data-sc-action]'); 5124 if (!control || !itemsWrap.contains(control)) return; 5125 var action = control.getAttribute('data-sc-action'); 5126 if ((event.type === 'change') !== (action === 'flavour')) return; 5127 var row = control.closest('[data-sc-line-key]'), line = row && scExactLine(scLastCart, row.getAttribute('data-sc-line-key')); 5128 event.preventDefault(); 5129 var holder = document.getElementById('scServerState'); 5130 var currentView = !!scLastCart && holder && scSectionSignature(holder.querySelector('[data-sc-server-render]')) === scCartSignature(scLastCart); 5131 if (!line || !currentView || scFrozen || scConvertBusy[String(line.variant_id)]) {
5132 if (line && action === 'flavour') control.value = String(line.variant_id); 5133 return; 5134 } 5135 var plan = line.selling_plan_allocation ? line.selling_plan_allocation.selling_plan.id : null; 5136 if (action === 'plus' || action === 'minus') { 5137 var shown = line.quantity + (scPending['line:' + line.key] || 0) + (scLineOverlay[line.key] || 0); 5138 if (action === 'plus' || shown > 0) scStepLine(line, action === 'plus' ? 1 : -1); 5139 return; 5140 } 5141 scFlush(); 5142 if (action === 'remove') { 5143 scEnqueue({ kind: 'line', key: line.key, ident: scLineIdent(line), target: 0, strictKey: true }); return; 5144 } 5145 if (action === 'subscribe' || action === 'flavour') { 5146 var targetId = action === 'flavour' ? String(control.value) : String(line.variant_id); 5147 var targetPlan = action === 'subscribe' ? control.getAttribute('data-sc-plan') : plan; 5148 if (!targetId || (action === 'subscribe' && !targetPlan) || (action === 'flavour' && targetId === String(line.variant_id))) return; 5149 scEnqueue({ kind: 'convert', src: { vid: String(line.variant_id), plan: plan, props: line.properties || null, key: line.key }, 5150 dst: { vid: targetId, plan: targetPlan, props: line.properties || null }, direct: action === 'subscribe', label: action }) 5151 .then(function () { scPaint(function () { scPaintLineControls(); }); }); 5152 } 5153 } 5154 itemsWrap.addEventListener('click', scLineAction); 5155 itemsWrap.addEventListener('change', scLineAction); 5156 5157 5158 function updateFab() { 5159 if (!fabEl) return; 5160 var count = scLastCart ? scLastCart.item_count : 0; 5161 fabCountEl.textContent = count > 99 ? '99+' : String(count); 5162 fabEl.classList.toggle('sc-fab-show', count > 0 && !drawer.classList.contains('sc-open')); 5163 } 5164 5165 5166 function applyRealCart(cart, authoritative) { 5167 scValidateCart(cart); 5168 var failuresBefore = scPaintFailures; 5169 if (scPaint(function () { scPaintRealCart(cart, authoritative); }) && scPaintFailures === failuresBefore && !scViewPending && !drawer.classList.contains('sc-view-unconfirmed')) scViewError = null; 5170 } 5171 function scPaintRealCart(cart, authoritative) { 5172 // Server truth + the overlay of queued/in-flight ops. `authoritative` drops unflushed stepper taps 5173 // (checkout recovery); it never touches ops that are still queued or in flight. 5174 if (authoritative) { scPending = {}; scPendingOrder = []; scPendingLines = {}; } 5175 var items = cart.items || []; 5176 lastCartItems = items; 5177 var subVariants = {}; 5178 items.forEach(function(it) { if (it.selling_plan_allocation) subVariants[String(it.variant_id)] = true; }); 5179 window.__scSubVariants = subVariants; 5180 5181 // Line up the magnesium option with whichever flavour is actually carted (not mid-switch). 5182 var magP = prod('mag'); 5183 if (magP && magP.ok && !scConvertBusy[String(magP.variant)] && !magP.convertFrom && !scPending['mag']) { 5184 for (var i = 0; i < MAG_OPTIONS.length; i++) { 5185 if (scFindLine(cart, MAG_OPTIONS[i].id, null, null)) { 5186 magP.variant = MAG_OPTIONS[i].id; magP.price = MAG_OPTIONS[i].price; magP.name = MAG_OPTIONS[i].name; 5187 var sel = document.getElementById('scMagFlavour'); 5188 if (sel) sel.value = String(MAG_OPTIONS[i].id); 5189 var mn = document.getElementById('scMagItemName'); if (mn) mn.textContent = MAG_OPTIONS[i].name; 5190 var mf = document.getElementById('scMagItemFlavour'); if (mf) mf.innerHTML = MAG_OPTIONS[i].title + ' · Relaxation & Recovery'; 5191 break; 5192 } 5193 } 5194 } 5195 5196 PRODUCTS.forEach(function(p) { 5197 if (!p.ok || !p.variant) return; 5198 var line = scFindLine(cart, p.variant, null, null); 5199 p.lineKey = line ? line.key : null; 5200 var serverQty = line ? line.quantity : 0; 5201 p.convertFromKey = null; 5202 if (p.convertFrom) { 5203 // Mid flavour switch: one row, showing the old flavour's quantity until the new line exists. 5204 var from = scFindLine(cart, p.convertFrom, null, null); 5205 if (from) { p.convertFromKey = from.key; if (!serverQty) serverQty = from.quantity; } 5206 } 5207 var subbed = !!subVariants[String(p.variant)]; 5208 var qty = Math.max(0, serverQty + scOverlayFor(scIdent(p.variant, null, null), p.key)); 5209 p.qty = qty; 5210 p.inCart = qty > 0; 5211 if (p.inCart) { 5212 if (p.role === 'hidden') p.role = 'addon'; 5213 p.itemEl.style.display = 'flex'; 5214 p.upsellEl.style.display = 'none'; 5215 } else if (p.role === 'main') { 5216 // The page's product is not in the cart: no synthetic row. 5217 p.itemEl.style.display = 'none'; 5218 } else if (p.role === 'addon') { 5219 p.itemEl.style.display = 'none'; 5220 if (subbed) p.upsellEl.style.display = 'none'; else expandCard(p); 5221 } 5222 }); 5223 recalcCart(true); // merchandising only; actual rows and money come from Shopify's section 5224 scUpdateConversionControls(); 5225 scRenderConfirmedCart(cart); 5226 } 5227 5228 function refreshSideCart() { 5229 // A read op: applied only between mutations, never while one is in flight. 5230 return scEnqueue({ kind: 'read' })['catch'](function() {}); 5231 } 5232 window.refreshSideCart = refreshSideCart; 5233 scPaint(function () { scSetViewStatus(false, true); scPaintLineControls(); scViewNotice('Checking your cartâ¦', false); }); 5234 refreshSideCart().then(function() { hydrateResolve(); }); 5235 5236 if (fabEl) fabEl.addEventListener('click', function() { openCart(); }); 5237 5238 // Cart adds made by other scripts (old-theme ajax form, Appstle widget) never told the 5239 // drawer - remaining compatibility hooks request a refresh only; they never delete another line. 5240 (function () { 5241 function scExternalAdd(u) { 5242 if (typeof u === 'string' && u.indexOf('/cart/add') !== -1) { 5243 window.setTimeout(function () { refreshSideCart(); }, 500); 5244 } 5245 } 5246 var scOrigFetch = window.fetch; 5247 window.fetch = function (input, init) { 5248 var u = (typeof input === 'string') ? input : ((input && input.url) || ''); 5249 var p = scOrigFetch.apply(this, arguments); 5250 // The drawer's own writes carry __sc and already apply the returned cart; only third-party adds refresh. 5251 if (typeof u === 'string' && u.indexOf('/cart/add') !== -1 && !(init && init.__sc)) { p.then(function () { scExternalAdd(u); }, function () {}); } 5252 return p; 5253 }; 5254 var scOrigOpen = XMLHttpRequest.prototype.open; 5255 XMLHttpRequest.prototype.open = function (m, u) {
5256 try { 5257 if (typeof u === 'string' && u.indexOf('/cart/add') !== -1) { 5258 this.addEventListener('load', function () { scExternalAdd(u); }); 5259 } 5260 } catch (e) {} 5261 return scOrigOpen.apply(this, arguments); 5262 }; 5263 })(); 5264 5265 5266 // Plan switch as a direct-only convert op (fresh 1-based line). Button disabled until terminal; 5267 // a rejection never becomes a second purchase, and the event fires only on a verified switch. 5268 function scUpdateConversionControls() { 5269 scPaint(function () { 5270 PRODUCTS.forEach(function (p) { 5271 if (!p.ok) return; 5272 var busy = !!scConvertBusy[String(p.variant)] || !!p.convertFrom; 5273 p.minusEl.disabled = busy; p.plusEl.disabled = busy; 5274 p.itemEl.setAttribute('aria-busy', busy ? 'true' : 'false'); 5275 if (p.key === 'mag') { 5276 var select = document.getElementById('scMagFlavour'); 5277 if (select) select.disabled = busy; 5278 } 5279 }); 5280 scPaintLineControls(); 5281 var cleaner = prod('cleaner'), mag = prod('mag'); 5282 var cb = document.getElementById('scSubOfferBtn'), mb = document.getElementById('scMagSubOfferBtn'); 5283 if (cb) cb.disabled = !!(cleaner && scConvertBusy[String(cleaner.variant)]); 5284 if (mb) mb.disabled = !!(mag && (scConvertBusy[String(mag.variant)] || mag.convertFrom)); 5285 }); 5286 } 5287 function scSwitchButtonBusy(btn, busy) { 5288 scPaint(function () { 5289 if (!btn) return; 5290 var label = btn.querySelector('[data-sc-switch-label]'); 5291 var status = btn.querySelector('[data-sc-switch-status]'); 5292 if (label) label.style.display = busy ? 'none' : ''; 5293 if (status) status.style.display = busy ? '' : 'none'; 5294 btn.disabled = busy; 5295 btn.setAttribute('aria-busy', busy ? 'true' : 'false'); 5296 }); 5297 } 5298 function swapLineToPlan(vid, q, planId, btn, btnHtml, evt) { 5299 if (scFrozen || scConvertBusy[String(vid)]) return; 5300 scFlush(); 5301 scSwitchButtonBusy(btn, true); 5302 var finished = false, settled = false; 5303 var pendingMessage = 'Still switching your plan - we will confirm shortly.'; 5304 function finish() { 5305 if (finished) return; finished = true; 5306 scSwitchButtonBusy(btn, false); 5307 scUpdateConversionControls(); 5308 scPaint(function () { updateSubOffer(); updateMagSubOffer(); }); 5309 scPaint(function () { 5310 var note = document.getElementById('scNote'); 5311 if (note && note.textContent === pendingMessage) scShowNote(''); 5312 }, false); 5313 } 5314 // Unknown writes retain the lock until bounded reconciliation reaches a terminal outcome. 5315 var cap = setTimeout(function () { if (!settled) scShowNote(pendingMessage, true); }, 8000); 5316 scEnqueue({ kind: 'convert', src: { vid: String(vid), plan: null, props: null }, dst: { vid: String(vid), plan: String(planId), props: null }, direct: true, label: evt }) 5317 .then(function (st) { 5318 settled = true; clearTimeout(cap); finish(); 5319 if (st === 'ok') { try { if (typeof trackSideCart === 'function') trackSideCart(evt); } catch (trackingError) {} } 5320 }, function () { settled = true; clearTimeout(cap); finish(); }); 5321 } 5322 5323 // ---- Cleaner subscribe-and-save offer (renders only when the selling plan is cheaper) ---- 5324 var SC_CL_OFFER = { variant: '41124907712651', plan: '773587083' }; 5325 var subOfferEl = document.getElementById('scSubOffer'); 5326 var subOfferBtn = document.getElementById('scSubOfferBtn'); 5327 var subOfferBtnHtml = subOfferBtn ? subOfferBtn.innerHTML : ''; 5328 function updateSubOffer() { 5329 if (!subOfferEl) return; 5330 var c = prod('cleaner'); 5331 var locked = c && window.__scSubVariants && window.__scSubVariants[String(c.variant)]; 5332 subOfferEl.style.display = (c && c.ok && c.inCart && c.qty > 0 && !locked && SC_CL_OFFER.plan) ? 'block' : 'none'; 5333 } 5334 if (subOfferBtn) subOfferBtn.addEventListener('click', function () { 5335 var c = prod('cleaner'); 5336 if (!c || !c.inCart || !SC_CL_OFFER.plan) return; 5337 swapLineToPlan(String(SC_CL_OFFER.variant), c.qty, SC_CL_OFFER.plan, subOfferBtn, subOfferBtnHtml, 'side_cart_cleaner_sub_upgrade'); 5338 }); 5339 5340 // ---- Magnesium subscribe-and-save offer (per-variant, renders only when a plan is cheaper) ---- 5341 var MAG_SUB = {};MAG_SUB['47628215287947'] = { plan: '2655355019', price: 46.99, sub: 42.29 };MAG_SUB['47628215320715'] = { plan: '2655355019', price: 46.99, sub: 42.29 };MAG_SUB['47628215353483'] = { plan: '2655355019', price: 46.99, sub: 42.29 };var magSubOfferEl = document.getElementById('scMagSubOffer'); 5342 var magSubOfferBtn = document.getElementById('scMagSubOfferBtn'); 5343 var magSubOfferBtnHtml = magSubOfferBtn ? magSubOfferBtn.innerHTML : ''; 5344 function magOfferEntry() { 5345 var m = prod('mag'); 5346 if (!m || !m.ok || !m.inCart || m.qty <= 0) return null; 5347 var e = MAG_SUB[String(m.variant)]; 5348 if (!e) return null; 5349 if (window.__scSubVariants && window.__scSubVariants[String(m.variant)]) return null; 5350 return { m: m, e: e }; 5351 } 5352 function updateMagSubOffer() { 5353 if (!magSubOfferEl) return; 5354 var x = magOfferEntry(); 5355 if (!x) { magSubOfferEl.style.display = 'none'; return; } 5356 var pct = Math.round((1 - x.e.sub / x.e.price) * 100); 5357 document.getElementById('scMagOfferPct').textContent = pct; 5358 document.getElementById('scMagOfferPctBadge').textContent = pct; 5359 document.getElementById('scMagOfferPrice').textContent = fmtMoney(x.e.sub) + '/mo instead of ' + fmtMoney(x.e.price); 5360 var buttonPrice = document.getElementById('scMagOfferBtnPrice'); 5361 if (buttonPrice) buttonPrice.textContent = fmtMoney(x.e.sub) + '/mo'; 5362 magSubOfferEl.style.display = 'block'; 5363 } 5364 if (magSubOfferBtn) magSubOfferBtn.addEventListener('click', function () { 5365 var x = magOfferEntry(); 5366 if (!x) return; 5367 swapLineToPlan(String(x.m.variant), x.m.qty, x.e.plan, magSubOfferBtn, magSubOfferBtnHtml, 'side_cart_mag_sub_upgrade'); 5368 }); 5369 5370 5371})(); 5372</script>
5372 5373 5374 5375 5376 5377</div> 5378 5379<style> 5380 #gsc-intent-popup { position: fixed; inset: 0; z-index: 9996; display: none; background: #002156 url('https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Couple_Sleeping.jpg?v=1782981097') center/cover no-repeat; } 5381 #gsc-intent-popup.gscp-open { display: block; } 5382 #gsc-intent-popup::before { content: ''; position: absolute; inset: 0; background: linear-gradient(160deg, rgba(0,33,86,0.94) 0%, rgba(0,33,86,0.78) 55%, rgba(0,33,86,0.55) 100%); } 5383 .gscp-modal { position: absolute; inset: 0; overflow-y: auto; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 24px 40px; box-sizing: border-box; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; opacity: 0; transform: translateY(14px); transition: opacity .25s ease, transform .25s ease; } 5384 #gsc-intent-popup.gscp-in .gscp-modal { opacity: 1; transform: translateY(0); } 5385 .gscp-close { position: fixed; top: 16px; right: 16px; width: 38px; height: 38px; border: 0; background: rgba(244,239,233,0.15); border-radius: 50%; cursor: pointer; color: #F4EFE9; font-size: 22px; line-height: 38px; text-align: center; padding: 0; z-index: 2; -webkit-tap-highlight-color: transparent; } 5386 .gscp-step { display: none; width: 100%; max-width: 480px; margin: 0 auto; text-align: center; } 5387 .gscp-step.gscp-active { display: block; } 5388 .gscp-eyebrow { display: inline-block; background: #ECAFAC; color: #002156; font-size: 11px; font-weight: bold; letter-spacing: 1.4px; text-transform: uppercase; border-radius: 999px; padding: 6px 14px; margin: 0 0 20px; } 5389 .gscp-ten { color: #F4EFE9; font-size: 72px; line-height: 72px; font-weight: bold; letter-spacing: -2px; margin: 0; } 5390 .gscp-h { margin: 6px 0 10px; color: #F4EFE9; font-size: 25px; line-height: 32px; font-weight: bold; } 5391 .gscp-sub { margin: 0 0 26px; color: #99BCD2; font-size: 15px; line-height: 22px; } 5392 .gscp-opt { display: block; width: 100%; text-align: center; background: rgba(244,239,233,0.14); color: #F4EFE9; border: 1px solid rgba(153,188,210,0.7); border-radius: 999px; padding: 14px 18px; margin: 0 0 11px; font-size: 15px; line-height: 20px; font-family: inherit; cursor: pointer; transition: border-color .15s ease; -webkit-tap-highlight-color: transparent; backdrop-filter: blur(3px); } 5393 .gscp-opt:hover { border-color: #ECAFAC; } 5394 .gscp-opt.gscp-selected { background: #F4EFE9; color: #002156; border-color: #F4EFE9; } 5395 .gscp-input { display: block; width: 100%; box-sizing: border-box; background: #F4EFE9; border: 1.5px solid #F4EFE9; border-radius: 999px; padding: 14px 20px; font-size: 16px; color: #002156; font-family: inherit; margin: 0 0 12px; text-align: center; } 5396 .gscp-input:focus { outline: none; border-color: #ECAFAC; } 5397 .gscp-cta { display: block; width: 100%; background: #ECAFAC; color: #002156; border: 0; border-radius: 999px; padding: 15px 18px; font-size: 16px; font-weight: bold; font-family: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; } 5398 .gscp-cta:disabled { opacity: .6; cursor: default; } 5399 .gscp-fine { margin: 14px 0 0; color: rgba(244,239,233,0.55); font-size: 12px; line-height: 17px; } 5400 .gscp-err { display: none; margin: 0 0 10px; color: #FFB4AC; font-size: 13px; line-height: 18px; } 5401 .gscp-err.gscp-show { display: block; } 5402 .gscp-hp { position: absolute; left: -9999px; top: -9999px; height: 0; width: 0; opacity: 0; } 5403 .gscp-tick { width: 54px; height: 54px; border-radius: 50%; background: #F4EFE9; color: #002156; font-size: 26px; line-height: 54px; text-align: center; margin: 4px auto 16px; } 5404 .gscp-code { background: rgba(244,239,233,0.12); border: 1.5px dashed #ECAFAC; border-radius: 14px; padding: 13px 18px; margin: 0 0 14px; font-size: 30px; letter-spacing: 5px; font-weight: bold; color: #F4EFE9; } 5405 #gscp-teaser { position: fixed; left: 16px; bottom: 16px; z-index: 9995; display: none; background: #ECAFAC; color: #002156; border: 0; border-radius: 999px; padding: 12px 20px; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 14px; font-weight: bold; letter-spacing: .3px; cursor: pointer; box-shadow: 0 6px 20px rgba(0,33,86,0.28); transition: transform .2s ease, box-shadow .2s ease; -webkit-tap-highlight-color: transparent; }
5406 #gscp-teaser.gscp-teaser-show { display: block; animation: gscpTeaserIn .35s cubic-bezier(0.34, 1.56, 0.64, 1); } 5407 #gscp-teaser:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0,33,86,0.34); } 5408 @keyframes gscpTeaserIn { from { opacity: 0; transform: scale(0.7); } to { opacity: 1; transform: scale(1); } } 5409 @media (max-width: 860px) { #gscp-teaser { bottom: 90px; left: 12px; padding: 11px 16px; font-size: 13px; } } 5410 @media (max-width: 480px) { 5411 .gscp-ten { font-size: 54px; line-height: 54px; } 5412 .gscp-h { font-size: 20px; line-height: 26px; } 5413 .gscp-code { font-size: 24px; letter-spacing: 4px; } 5414 .gscp-modal { padding: 56px 20px 32px; } 5415 } 5416</style> 5417 5418<div id="gsc-intent-popup" role="dialog" aria-modal="true" aria-labelledby="gscp-title"> 5419 <div class="gscp-modal"> 5420 <button type="button" class="gscp-close" data-gscp-dismiss aria-label="Close">×</button> 5421 5422 <div class="gscp-step gscp-active" data-gscp-step="intent"> 5423 <span class="gscp-eyebrow">Our gift to you</span> 5424 <p class="gscp-ten">$10 off</p> 5425 <h3 class="gscp-h" id="gscp-title">your first order — and quieter nights ahead</h3> 5426 <p class="gscp-sub">Tell us what brings you here to unlock your $10 code.</p> 5427 <button type="button" class="gscp-opt" data-gscp-intent="snoring">I snore</button> 5428 <button type="button" class="gscp-opt" data-gscp-intent="test">I think I have sleep apnea</button> 5429 <button type="button" class="gscp-opt" data-gscp-intent="cpap_alt">Diagnosed, but CPAP isn’t working</button> 5430 <button type="button" class="gscp-opt" data-gscp-intent="research">Just researching better sleep</button> 5431 <p class="gscp-fine">Plus practical sleep tips. Unsubscribe anytime.</p> 5432 </div> 5433 5434 <div class="gscp-step" data-gscp-step="email"> 5435 <span class="gscp-eyebrow">Almost there</span> 5436 <h3 class="gscp-h">Last step — unlock your $10 code</h3> 5437 <p class="gscp-sub">Your code shows right here and applies automatically at checkout.</p> 5438 <form id="gscp-form" novalidate> 5439 <p class="gscp-err" data-gscp-error>Something went wrong — please check your email and try again.</p> 5440 <input type="email" class="gscp-input" data-gscp-email placeholder="Enter your email" autocomplete="email" required> 5441 <input type="text" class="gscp-hp" name="website" tabindex="-1" autocomplete="off" data-gscp-hp> 5442 <button type="submit" class="gscp-cta" data-gscp-submit>Show my $10 code</button> 5443 </form> 5444 <p class="gscp-fine">Plus practical sleep tips. Unsubscribe anytime.</p> 5445 </div> 5446 5447 <div class="gscp-step" data-gscp-step="success"> 5448 <div class="gscp-tick">✓</div> 5449 <h3 class="gscp-h">Here’s your $10 code</h3> 5450 <p class="gscp-code" data-gscp-code>SLEEP10</p> 5451 <p class="gscp-sub">It’s applied automatically at checkout — nothing to paste.</p> 5452 <button type="button" class="gscp-cta" data-gscp-dismiss>Keep browsing</button> 5453 <p class="gscp-fine" data-gscp-code-fine>Not showing at checkout? Just enter SLEEP10.</p> 5454 </div> 5455 </div> 5456</div> 5457<button type="button" id="gscp-teaser" aria-label="Get $10 off your first order">$10 Off</button>
5458<script> 5459(function () { 5460 'use strict'; 5461 var COMPANY_ID = 'WscBdf'; 5462 var LIST_ID = 'RsDuiB'; 5463 var CODE = 'SLEEP10'; 5464 var LS_SUBMITTED = 'gscp_submitted'; 5465 var LS_DISMISSED_AT = 'gscp_dismissed_at'; 5466 var SS_SHOWN = 'gscp_shown'; 5467 var DISMISS_DAYS = 7; 5468 var root = document.getElementById('gsc-intent-popup'); 5469 if (!root) return; 5470 5471 var state = { open: false, step: 'intent', intent: null, submitting: false, openRetries: 0, code: CODE }; 5472 5473 function lsGet(k) { try { return window.localStorage.getItem(k); } catch (e) { return null; } } 5474 function lsSet(k, v) { try { window.localStorage.setItem(k, v); } catch (e) {} } 5475 function ssGet(k) { try { return window.sessionStorage.getItem(k); } catch (e) { return null; } } 5476 function ssSet(k, v) { try { window.sessionStorage.setItem(k, v); } catch (e) {} } 5477 5478 // Urgency A/B concluded 28/08/2026: evergreen (control) won on purchases in 5479 // both markets. The 48h badge / unique-code / countdown machinery is gone; 5480 // the static SLEEP10 + auto-apply path below is the whole popup again. 5481 5482 function track(name, props) { 5483 var payload = props || {}; 5484 try { 5485 window.dataLayer = window.dataLayer || []; 5486 var dl = { event: name }; 5487 for (var k in payload) { if (payload.hasOwnProperty(k)) dl[k] = payload[k]; } 5488 window.dataLayer.push(dl); 5489 } catch (e) {} 5490 try { 5491 if (window.posthog && typeof window.posthog.capture === 'function') { 5492 window.posthog.capture(name, payload); 5493 } 5494 } catch (e) {} 5495 } 5496 5497 function eligible() { 5498 if (lsGet(LS_SUBMITTED)) return false; 5499 if (ssGet(SS_SHOWN)) return false; 5500 var d = parseInt(lsGet(LS_DISMISSED_AT) || '0', 10); 5501 if (d && (Date.now() - d) < DISMISS_DAYS * 86400000) return false; 5502 return true; 5503 } 5504 5505 function setStep(step) { 5506 state.step = step; 5507 var steps = root.querySelectorAll('[data-gscp-step]'); 5508 for (var i = 0; i < steps.length; i++) { 5509 steps[i].className = steps[i].className.replace(' gscp-active', ''); 5510 if (steps[i].getAttribute('data-gscp-step') === step) steps[i].className += ' gscp-active'; 5511 } 5512 } 5513 5514 function openPopup(source, force) { 5515 if (state.open) return; 5516 if (!force && !eligible()) return; 5517 var cartOpen = document.querySelector('.sc-overlay.sc-open'); 5518 if (cartOpen && state.openRetries < 4) { 5519 state.openRetries += 1; 5520 window.setTimeout(function () { openPopup(source); }, 15000); 5521 return; 5522 } 5523 state.open = true; 5524 ssSet(SS_SHOWN, '1'); 5525 root.className = 'gscp-open'; 5526 window.setTimeout(function () { root.className = 'gscp-open gscp-in'; }, 20); 5527 document.body.style.overflow = 'hidden'; 5528 updateTeaser(); 5529 track('popup_viewed', { trigger_source: source, popup: 'au_intent' }); 5530 } 5531 5532 function closePopup(reason) { 5533 if (!state.open) return; 5534 state.open = false; 5535 root.className = ''; 5536 document.body.style.overflow = ''; 5537 updateTeaser(); 5538 if (reason === 'dismiss' && !lsGet(LS_SUBMITTED)) { 5539 lsSet(LS_DISMISSED_AT, String(Date.now())); 5540 track('popup_dismissed', { step: state.step, intent: state.intent || 'none', popup: 'au_intent' }); 5541 } 5542 } 5543 5544 // --- triggers: first of 30s timer / >50% scroll / desktop exit-intent --- 5545 var fired = false; 5546 function fire(source) { 5547 if (fired) return; 5548 fired = true; 5549 window.removeEventListener('scroll', onScroll); 5550 document.removeEventListener('mouseleave', onLeave); 5551 openPopup(source); 5552 } 5553 function onScroll() { 5554 var doc = document.documentElement; 5555 var max = (doc.scrollHeight - doc.clientHeight); 5556 if (max > 0 && (window.pageYOffset / max) > 0.5) fire('scroll'); 5557 } 5558 function onLeave(e) { if (e.clientY <= 0) fire('exit_intent'); } 5559 5560 if (eligible()) { 5561 try { var pre = new Image(); pre.src = 'https://cdn.shopify.com/s/files/1/0598/2417/7291/files/Couple_Sleeping.jpg?v=1782981097'; } catch (e) {} 5562 window.setTimeout(function () { fire('timer'); }, 12000); 5563 window.addEventListener('scroll', onScroll, { passive: true }); 5564 if (window.matchMedia && window.matchMedia('(pointer: fine)').matches) { 5565 document.addEventListener('mouseleave', onLeave); 5566 } 5567 } 5568 5569 // --- dismiss handlers --- 5570 var dismissers = root.querySelectorAll('[data-gscp-dismiss]'); 5571 for (var i = 0; i < dismissers.length; i++) { 5572 dismissers[i].addEventListener('click', function () {
5573 closePopup(state.step === 'success' ? 'done' : 'dismiss'); 5574 }); 5575 } 5576 document.addEventListener('keydown', function (e) { 5577 if (e.key === 'Escape' && state.open) closePopup(state.step === 'success' ? 'done' : 'dismiss'); 5578 }); 5579 5580 // --- intent selection --- 5581 var opts = root.querySelectorAll('[data-gscp-intent]'); 5582 for (var j = 0; j < opts.length; j++) { 5583 opts[j].addEventListener('click', function () { 5584 state.intent = this.getAttribute('data-gscp-intent'); 5585 this.className += ' gscp-selected'; 5586 track('popup_intent_selected', { intent: state.intent, popup: 'au_intent' }); 5587 var self = this; 5588 window.setTimeout(function () { 5589 setStep('email'); 5590 var em = root.querySelector('[data-gscp-email]'); 5591 if (em) em.focus(); 5592 self.className = self.className.replace(' gscp-selected', ''); 5593 }, 180); 5594 }); 5595 } 5596 5597 function showSuccessCode() { 5598 var codeEl = root.querySelector('[data-gscp-code]'); 5599 if (codeEl) codeEl.textContent = state.code; 5600 var fineEl = root.querySelector('[data-gscp-code-fine]'); 5601 if (fineEl) fineEl.textContent = 'Not showing at checkout? Just enter ' + state.code + '.'; 5602 setStep('success'); 5603 } 5604 5605 // --- submit --- 5606 var form = document.getElementById('gscp-form'); 5607 form.addEventListener('submit', function (e) { 5608 e.preventDefault(); 5609 if (state.submitting) return; 5610 var emailEl = root.querySelector('[data-gscp-email]'); 5611 var errEl = root.querySelector('[data-gscp-error]'); 5612 var btn = root.querySelector('[data-gscp-submit]'); 5613 var hp = root.querySelector('[data-gscp-hp]'); 5614 var email = (emailEl.value || '').trim(); 5615 errEl.className = errEl.className.replace(' gscp-show', ''); 5616 5617 if (hp && hp.value) { setStep('success'); return; } // honeypot: silently succeed 5618 if (!/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email)) { 5619 errEl.textContent = 'Please enter a valid email address.'; 5620 errEl.className += ' gscp-show'; 5621 return; 5622 } 5623 5624 state.submitting = true; 5625 btn.disabled = true; 5626 var prevLabel = btn.textContent; 5627 btn.textContent = 'Sendingâ¦'; 5628 5629 Promise.resolve().then(function () { 5630 state.code = CODE; 5631 5632 var props = { intent: state.intent || 'research' }; 5633 var body = { 5634 data: { 5635 type: 'subscription', 5636 attributes: { 5637 custom_source: 'AU Intent Popup', 5638 profile: { data: { type: 'profile', attributes: { 5639 email: email, 5640 properties: props 5641 } } } 5642 }, 5643 relationships: { list: { data: { type: 'list', id: LIST_ID } } } 5644 } 5645 }; 5646 5647 function subscribe() { 5648 return fetch('https://a.klaviyo.com/client/subscriptions/?company_id=' + COMPANY_ID, { 5649 method: 'POST', 5650 headers: { 'Content-Type': 'application/vnd.api+json', 'revision': '2025-07-15' }, 5651 body: JSON.stringify(body) 5652 }); 5653 } 5654 return subscribe().then(function (res) { 5655 if (res.status !== 202 && !res.ok) throw new Error('klaviyo_' + res.status); 5656 return res; 5657 }).catch(function () { 5658 return new Promise(function (resolve) { window.setTimeout(resolve, 1200); }).then(subscribe); 5659 }).then(function (res) { 5660 if (res.status !== 202 && !res.ok) throw new Error('klaviyo_' + res.status); 5661 lsSet(LS_SUBMITTED, '1'); 5662 try { fetch('/discount/' + state.code, { credentials: 'same-origin' }); } catch (err) {} 5663 showSuccessCode(); 5664 track('popup_submitted', { intent: state.intent || 'research', popup: 'au_intent' }); 5665 }); 5666 }).catch(function () { 5667 errEl.textContent = 'Something went wrong â please try again in a moment.'; 5668 errEl.className += ' gscp-show'; 5669 }).then(function () { 5670 state.submitting = false; 5671 btn.disabled = false; 5672 btn.textContent = prevLabel; 5673 }); 5674 }); 5675 5676 // --- teaser tab: stays in the corner while the offer is unclaimed; reopens the form --- 5677 var teaser = document.getElementById('gscp-teaser'); 5678 var teaserTracked = false; 5679 function updateTeaser() { 5680 if (!teaser) return; 5681 var show = !lsGet(LS_SUBMITTED) && !state.open;
5682 teaser.className = show ? 'gscp-teaser-show' : ''; 5683 if (show && !teaserTracked) { 5684 teaserTracked = true; 5685 track('popup_teaser_shown', { popup: 'au_intent' }); 5686 } 5687 } 5688 if (teaser) teaser.addEventListener('click', function () { 5689 track('popup_teaser_clicked', { popup: 'au_intent' }); 5690 openPopup('teaser', true); 5691 }); 5692 updateTeaser(); 5693})();</script>
5693 5694 5695 5696<style> 5697 .gs-sd-backdrop { position: fixed; inset: 0; z-index: 9998; background: rgba(0,21,54,.45); opacity: 0; pointer-events: none; transition: opacity .25s ease; } 5698 .gs-sd-backdrop.gs-sd-open { opacity: 1; pointer-events: auto; } 5699 #gs-shop-drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: 9999; width: 440px; max-width: 100%; background: #fff; display: flex; flex-direction: column; 5700 transform: translateX(102%); transition: transform .3s cubic-bezier(.22,.7,.3,1); box-shadow: -12px 0 40px rgba(0,21,54,.18); } 5701 #gs-shop-drawer.gs-sd-open { transform: translateX(0); } 5702 #gs-shop-drawer *, #gs-shop-drawer *:before, #gs-shop-drawer *:after { box-sizing: border-box; } 5703 .gs-sd-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid #E5E7EB; flex: 0 0 auto; } 5704 .gs-sd-head img { height: 26px; width: auto; display: block; } 5705 .gs-sd-close, .gs-sd-cart { background: none; border: none; cursor: pointer; padding: 8px; -webkit-tap-highlight-color: transparent; line-height: 0; } 5706 .gs-sd-close svg, .gs-sd-cart svg { width: 22px; height: 22px; fill: none; stroke: #002156; stroke-width: 2.2; } 5707 .gs-sd-body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 14px 14px 40px; flex: 1 1 auto; } 5708 .gs-sd-col { display: flex; flex-direction: column; gap: 12px; } 5709 .gs-sd-tile { display: grid; grid-template-columns: 1.15fr 1fr; border-radius: 14px; overflow: hidden; min-height: 150px; position: relative; border: 1px solid #E5E7EB; 5710 text-decoration: none; transition: box-shadow .18s ease, transform .18s ease; -webkit-tap-highlight-color: transparent; } 5711 .gs-sd-tile:hover { box-shadow: 0 8px 26px rgba(0,21,54,.12); transform: translateY(-1px); text-decoration: none; } 5712 .gs-sd-txt { padding: 20px 6px 20px 20px; display: flex; flex-direction: column; justify-content: center; } 5713 .gs-sd-tag { font-size: 11px; font-weight: 800; letter-spacing: 1.2px; text-transform: uppercase; color: #43567A; } 5714 .gs-sd-tile h3 { font-size: 20px; font-weight: 800; color: #002156; margin: 6px 0 0; line-height: 1.15; } 5715 .gs-sd-sub { margin: 8px 0 0; font-size: 13.5px; line-height: 1.45; font-weight: 300; color: #43567A; } 5716 .gs-sd-img { display: flex; align-items: center; justify-content: center; overflow: hidden; } 5717 .gs-sd-img img { width: 100%; height: 100%; object-fit: contain; padding: 14px; } 5718 .gs-sd-img.gs-sd-cover img { object-fit: cover; padding: 0; } 5719 .gs-sd-tile.gs-sd-hero { background: #002156; border-color: #002156; } 5720 .gs-sd-tile.gs-sd-hero .gs-sd-tag { color: #ECAFAC; } 5721 .gs-sd-tile.gs-sd-hero h3 { color: #fff; } 5722 .gs-sd-tile.gs-sd-hero .gs-sd-sub { color: #C9D6E6; } 5723 .gs-sd-tile.gs-sd-blush { background: #F8ECEB; } 5724 .gs-sd-tile.gs-sd-blue { background: #E8F0F6; } 5725 .gs-sd-tile.gs-sd-grey { background: #F7F8FA; } 5726 .gs-sd-soldout { position: absolute; top: 12px; right: 12px; background: #43567A; color: #fff; font-size: 11px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; padding: 6px 12px; border-radius: 999px; } 5727 .gs-sd-tile.gs-sd-is-sold .gs-sd-img img { filter: grayscale(55%); opacity: .72; } 5728 .gs-sd-tile.gs-sd-quiz { background: #ECAFAC; border-color: #ECAFAC; min-height: 110px; grid-template-columns: 1fr; } 5729 .gs-sd-tile.gs-sd-quiz h3 { color: #001536; } 5730 .gs-sd-tile.gs-sd-quiz .gs-sd-tag, .gs-sd-tile.gs-sd-quiz .gs-sd-sub { color: #7A4A46; } 5731 .gs-sd-links { display: none; margin-top: 18px; border-top: 1px solid #E5E7EB; padding-top: 6px; } 5732 .gs-sd-links a { display: block; padding: 13px 6px; color: #002156; font-size: 15px; font-weight: 400; text-decoration: none; border-bottom: 1px solid #F7F8FA; } 5733 @media (max-width: 860px) { .gs-sd-links { display: block; } } 5734</style> 5735 5736<div class="gs-sd-backdrop" id="gs-sd-backdrop"></div> 5737<div id="gs-shop-drawer" role="dialog" aria-modal="true" aria-label="Shop"> 5738 <div class="gs-sd-head"> 5739 <button class="gs-sd-close" id="gs-sd-close" aria-label="Close shop menu"><svg viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18"/></svg></button> 5740 <img src="//goodsleepco.health/cdn/shop/t/11/assets/good-sleep-co-logo-long.svg?v=74090565778415339771747357548" alt="Good Sleep Co"> 5741 <a class="gs-sd-cart" href="/cart" onclick="if (window.scCart && window.scCart.open) { event.preventDefault(); window.scCart.open(); }" aria-label="Cart"><svg viewBox="0 0 24 24">
5741<path d="M6 7h12l1.2 12.2a1.5 1.5 0 01-1.5 1.8H6.3a1.5 1.5 0 01-1.5-1.8L6 7z"/><path d="M9 10V6a3 3 0 016 0v4"/></svg></a> 5742 </div> 5743 <div class="gs-sd-body"> 5744 <div class="gs-sd-col"><a class="gs-sd-tile gs-sd-hero" href="/products/hushd-avera"> 5745 <div class="gs-sd-txt"><span class="gs-sd-tag">Snoring</span><h3>Stop the snoring</h3> 5746 <p class="gs-sd-sub">Hushd Avera. The custom-fit mouthpiece you mould at home. $139</p></div> 5747 <div class="gs-sd-img"><img src="//goodsleepco.health/cdn/shop/files/Avera_Packaging.webp?v=1771996349&width=400" alt="Hushd Avera" loading="lazy"></div></a><a class="gs-sd-tile gs-sd-blue" href="/products/good-sleep-test"> 5748 <div class="gs-sd-txt"><span class="gs-sd-tag">Sleep Apnea</span><h3>Test your sleep at home</h3> 5749 <p class="gs-sd-sub">Good Sleep Test. One night in your own bed, specialist report and a free consult. $200</p></div> 5750 <div class="gs-sd-img"><img src="//goodsleepco.health/cdn/shop/files/Web_Product_Images_1080x1080_GoodSleepTest2.jpg?v=1728010687&width=400" alt="Good Sleep Test" loading="lazy"></div></a><a class="gs-sd-tile gs-sd-blush" href="/pages/treatment"> 5751 <div class="gs-sd-txt"><span class="gs-sd-tag">Sleep Apnea</span><h3>Explore treatment options</h3> 5752 <p class="gs-sd-sub">Clinically-backed treatment pathways, guided by our team.</p></div> 5753 <div class="gs-sd-img gs-sd-cover"><img src="https://cdn.shopify.com/s/files/1/0598/2417/7291/files/homepage-oral-device-hand.webp?v=1773366326" alt="Oral device" loading="lazy"></div> 5754 </a><a class="gs-sd-tile gs-sd-grey gs-sd-is-sold" href="/products/hushd-guard"> 5755 <div class="gs-sd-txt"><span class="gs-sd-tag">Teeth Grinding</span><h3>Protect your teeth</h3> 5756 <p class="gs-sd-sub">Hushd Guard. Custom-fit night guard for grinding and jaw tension. $59.95</p></div> 5757 <div class="gs-sd-img"><img src="//goodsleepco.health/cdn/shop/files/Web_Product_Images_1080x1080_HushdGuardTemp2.jpg?v=1700607833&width=400" alt="Hushd Guard" loading="lazy"></div><span class="gs-sd-soldout">Sold Out</span></a><a class="gs-sd-tile gs-sd-blue gs-sd-is-sold" href="/products/hushd-nasal"> 5758 <div class="gs-sd-txt"><span class="gs-sd-tag">Blocked Nose</span><h3>Breathe easier tonight</h3> 5759 <p class="gs-sd-sub">Hushd Nasal dilators. Drug-free, two per pack. $24.95</p></div> 5760 <div class="gs-sd-img"><img src="//goodsleepco.health/cdn/shop/files/Hushd_Nasal.jpg?v=1757568127&width=400" alt="Hushd Nasal" loading="lazy"></div><span class="gs-sd-soldout">Sold Out</span></a><a class="gs-sd-tile gs-sd-grey" href="/products/cleaner"> 5761 <div class="gs-sd-txt"><span class="gs-sd-tag">Device Care</span><h3>Keep it fresh</h3> 5762 <p class="gs-sd-sub">The Cleaner. Deep-cleaning solution for your mouthpiece. $25</p></div> 5763 <div class="gs-sd-img"><img src="//goodsleepco.health/cdn/shop/files/GoodSleepCo-Product-Photos-39_Clipped.jpg?v=1752707389&width=400" alt="Cleaner" loading="lazy"></div></a><a class="gs-sd-tile gs-sd-quiz" href="/pages/sleep-quiz"> 5764 <div class="gs-sd-txt"><span class="gs-sd-tag">Not sure where to start?</span><h3>Take the 2-minute sleep quiz</h3> 5765 <p class="gs-sd-sub">Get a personalised recommendation.</p></div> 5766 </a> 5767 5768 </div> 5769 <nav class="gs-sd-links"> 5770 <a href="/pages/location">Location</a> 5771 <a href="/pages/faqs">FAQs</a> 5772 <a href="/pages/contact">Contact Us</a> 5773 </nav> 5774 </div> 5775</div> 5776
5777<script> 5778(function () { 5779 var drawer = document.getElementById('gs-shop-drawer'); 5780 var backdrop = document.getElementById('gs-sd-backdrop'); 5781 if (!drawer || !backdrop) return; 5782 var pushed = false; 5783 var prevOverflow = ''; 5784 5785 function openDrawer() { 5786 drawer.classList.add('gs-sd-open'); 5787 backdrop.classList.add('gs-sd-open'); 5788 prevOverflow = document.body.style.overflow; 5789 document.body.style.overflow = 'hidden'; 5790 if (window.location.pathname !== '/collections/shop') { 5791 try { 5792 history.pushState({ gsShopDrawer: 1 }, '', '/collections/shop'); 5793 pushed = true; 5794 } catch (e) { pushed = false; } 5795 } 5796 window.dataLayer = window.dataLayer || []; 5797 window.dataLayer.push({ event: 'virtual_page_view', page_path: '/collections/shop', page_title: 'Shop' }); 5798 if (window.posthog && typeof window.posthog.capture === 'function') { 5799 try { window.posthog.capture('$pageview'); } catch (e) {} 5800 } 5801 } 5802 5803 function closeDrawer(skipHistory) { 5804 drawer.classList.remove('gs-sd-open'); 5805 backdrop.classList.remove('gs-sd-open'); 5806 document.body.style.overflow = prevOverflow; 5807 if (pushed && !skipHistory) { try { history.back(); } catch (e) {} } 5808 pushed = false; 5809 } 5810 5811 document.getElementById('gs-sd-close').addEventListener('click', function () { closeDrawer(false); }); 5812 backdrop.addEventListener('click', function () { closeDrawer(false); }); 5813 document.addEventListener('keydown', function (e) { 5814 if (e.key === 'Escape' && drawer.classList.contains('gs-sd-open')) closeDrawer(false); 5815 }); 5816 window.addEventListener('popstate', function () { 5817 if (drawer.classList.contains('gs-sd-open')) closeDrawer(true); 5818 }); 5819 5820 // Capture-phase interception: burger (mobile nav) + Shop nav links. 5821 document.addEventListener('click', function (e) { 5822 var burger = e.target.closest ? e.target.closest('.js-drawer-open-nav, #menuBtn, #menuToggle, button[aria-label="Menu"]') : null; 5823 if (burger) { 5824 e.preventDefault(); 5825 e.stopImmediatePropagation ? e.stopImmediatePropagation() : e.stopPropagation(); 5826 openDrawer(); 5827 return; 5828 } 5829 var link = e.target.closest ? e.target.closest('a[href*="/collections/shop"]') : null; 5830 if (link && !drawer.contains(link)) { 5831 e.preventDefault(); 5832 e.stopImmediatePropagation ? e.stopImmediatePropagation() : e.stopPropagation(); 5833 openDrawer(); 5834 } 5835 }, true); 5836})(); 5837</script>
5837 5838 5839<div id="shopify-block-AUitnVGUzYUpqd3NYV__3498691031678343252" class="shopify-block shopify-app-block">
5839<script> 5840 var translations = {"store.load_more":"Load More-","store.leave_a_review":"Leave a review","store.verified_buyer":"Verified Buyer","store.view_product":"View Product","store.reply_from_owner":"Reply from owner","store.sticky_bar_discount":"CLAIM UP TO {discount} OFF* IN DISCOUNT CODES","store.sticky_bar_info":"Review products from your previous orders to claim your discount codes.","store.sticky_bar_click":"Click each order below to get started.","store.sticky_bar_order":"Order","store.sticky_bar_order_discount_one":"Discount code worth {discount} off","store.sticky_bar_order_discount_every":"Discount codes worth {discount} off","store.sticky_bar_term_created":"*A discount code is created for each product reviewed.","store.sticky_bar_term_only_one":"*Only one discount code can be used per order.","store.review_graph_total":"From {count} Reviews"}; 5841 window.kooee = { 5842 strings: translations 5843 }; 5844</script>
5844 5845 5846<!-- BEGIN app snippet: kooee-rich-snippet --> 5847<!-- END app snippet --> 5848 5849<div 5850 id="kooee-global-style" 5851 data-local-dev="false" 5852 data-fill-color="#F0F083" 5853 data-star-size="24" 5854 data-text-color="#000000" 5855 data-text-size="16" 5856 data-hide-no-results="false" 5857 data-rating-template="${review_rating} stars from ${review_count} reviews" 5858 data-padding="20" 5859 data-gap="10" 5860 data-flex-direction="column" 5861 data-align-items="center" 5862 data-script-url="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee-reviews-rating.js" 5863 data-leave-review-script-url="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee-leave-review.js" 5864 data-so-load-more="Load More" 5865 data-so-leave-review="Leave a Review" 5866 data-so-verified-buyer="Verified Buyer" 5867 data-so-view-product="View Product" 5868 data-so-owner-reply="Reply from owner" 5869></div> 5870 5871 5872 5873
5874<script 5875 src="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee-reviews-rewards.js" 5876 data-rewards-enabled="true" 5877 data-sticky-enabled="true" 5878 data-user="" 5879 data-bar-bg-colour="#F8AFB1" 5880 data-bar-text-size="20" 5881 data-bar-text-weight="800" 5882 data-bar-text-colour="#021f4a" 5883 data-bar-location="footer" 5884 data-bar-reward-for="one" 5885 data-modal-left-bg-colour="#F8AFB1" 5886 data-modal-left-text-colour="#fff" 5887 data-modal-right-bg-colour="#fff" 5888 data-modal-right-text-colour="#021f4a" 5889 data-bar-app-url="https://app.kooee.reviews" 5890 5891 async></script>
5891 5892 5893
5893<script 5894 src="https://cdn.shopify.com/extensions/019cfe03-08f6-782b-9714-4c1ba92113b7/theme-app-extension-25/assets/kooee-embed.js" 5895 async></script>
5895 5896 5897</div><div id="shopify-block-AM05QbkZpaG5MWU93V__18228966181090706294" class="shopify-block shopify-app-block"> 5898 5899 5900
5900<script type="module" src="https://cdn.shopify.com/extensions/01a0ec21-7369-78a6-b9c0-c07227d664ec/lb-upsell-451/assets/lb-upsell.js" defer="defer"></script>
5900 5901
5901<script type="module" src="https://cdn.shopify.com/extensions/01a0ec21-7369-78a6-b9c0-c07227d664ec/lb-upsell-451/assets/lb-upsell-components.esm.js" defer="defer"></script>
5901 5902 5903 5904
5905<script> 5906 5907 5908 5909</script>
5909 5910
5911<script> 5912 5913 window.lbInitMode = "immediate"; 5914 5915 window.lbComponentSrc = "https://cdn.shopify.com/extensions/01a0ec21-7369-78a6-b9c0-c07227d664ec/lb-upsell-451/assets/lb-upsell-components.esm.js";</script>
5915 5916
5917<script type="text/javascript" src="https://cdn.shopify.com/extensions/01a0ec21-7369-78a6-b9c0-c07227d664ec/lb-upsell-451/assets/lb-utils.js" defer="defer"></script>
5917 5918 5919</div><div id="shopify-block-ARExFU25Wa0dyOGZGU__6251270934270006384" class="shopify-block shopify-app-block">
5919<script> 5920 console.log("Stape gtm: 1.0.4"); 5921 window.lsData = {}; 5922 window.dataLayer = window.dataLayer || []; 5923 window.addEventListener("message", (event) => { 5924 if (event.data?.event) { 5925 window.dataLayer.push(event.data); 5926 } 5927 }); 5928 window.dataShopStape = { 5929 shop: "goodsleepco.health", 5930 shopId: "59824177291", 5931 } 5932</script>
5932 5933 5934 5935 5936 5937 5938 5939
5939<script> 5940 console.log("â ï¸ User not logged in"); 5941 window.localStorage.removeItem('customerShopStape'); 5942 </script>
5942 5943 5944 5945 5946
5947<script> 5948 window.currentShopifyMarketStapeId = null; 5949 window.currentShopifyMarketStapeCode = null; 5950 try { 5951 window.currentShopifyMarketStapeId = "28434563211"; 5952 window.currentShopifyMarketStapeCode = "AU"; 5953 // Checkout doesn't render theme app extension blocks, so this is the 5954 // only place the market/country code is ever set. Persisting it here 5955 // lets checkout-side field mapping (country_market_code) fall back to 5956 // the last known value instead of coming up empty. 5957 localStorage.setItem('marketShopStape', JSON.stringify({ 5958 id: window.currentShopifyMarketStapeId, 5959 code: window.currentShopifyMarketStapeCode 5960 })); 5961 } catch (error) { 5962 console.error("â Stape Error:", error); 5963 } 5964</script>
5964 5965 5966 5967 5968 5969 5970</div><div id="shopify-block-AY3pVa3ZJR0E3aHF6e__10436698916776057164" class="shopify-block shopify-app-block">
5970<script id="subscription-helper"> 5971 5972 if (!window.AppstleIncluded) { 5973 window.AppstleIncluded = true; 5974 window.RS = Window.RS || {}; 5975 5976 RS.Config = { 5977 "selectors": { 5978 "payment_button_selectors": "form[action$='/cart/add'] .shopify-payment-button", 5979 "subscriptionLinkSelector": "", 5980 "atcButtonPlacement": "BEFORE", 5981 "subscriptionLinkPlacement": "BEFORE", 5982 "cartRowSelector": "", 5983 "cartLineItemSelector": "", 5984 "cartLineItemPerQuantityPriceSelector": "", 5985 "cartLineItemTotalPriceSelector": "", 5986 "cartLineItemSellingPlanNameSelector": "", 5987 "cartSubTotalSelector" : "", 5988 "cartLineItemPriceSelector": "", 5989 "cartLineItemPlacement": "BEFORE", 5990 "cartHiddenAttributesSelector": "", 5991 "buildABoxDiscountSelector": "", 5992 }, 5993 "baseUrl": "https://subscription-admin.appstle.com", 5994 "usedTranslation": "true", 5995 "enableCartWidgetFeature": "false", 5996 "storefrontAnalyticsForwardingEnabled": false, 5997 "appstleStorefrontAnalyticsPath": "https://subscription-admin.appstle.com/assets/js/appstle-storefront-analytics.min.js?shop=good-sleep-co-gc.myshopify.com&v=1785489929499", 5998 "useUrlWithCustomerId": "true", 5999 "atcButtonSelector": "", 6000 "moneyFormat": "${{amount}}", 6001 "oneTimePurchaseText": "One Time Purchase", 6002 "minimumQuantityMessage": "", 6003 "tapToSelectText": "", 6004 "bundleDiscountTextV2": "bundle discount extra: {{bundleDiscount}} off", 6005 "productPageUnitPriceSelectorV2": "", 6006 "monthsFrequencyTextV2": "Months", 6007 "monthlyLabelTextV2": "Monthly", 6008 "monthFrequencyTextV2": "Month", 6009 "weeksFrequencyTextV2": "Weeks", 6010 "weeklyLabelTextV2": "Weekly", 6011 "weekFrequencyTextV2": "Week", 6012 "daysFrequencyTextV2": "Days", 6013 "dayFrequencyTextV2": "day", 6014 "yearsFrequencyTextV2": "Years", 6015 "yearlyLabelTextV2": "Yearly", 6016 "yearFrequencyTextV2": "Year", 6017 "offFrequencyTextV2": "Off", 6018 "prepayLabelTextV2": "Prepay", 6019 "prepaidLabelTextV2": "Prepaid", 6020 "prepaidSaveBadgeTextV2": "SAVE {{selectedDiscountPercentage}}", 6021 "onetimeDescriptionTextV2": "", 6022 "atcButtonTextV2": "", 6023 "oneTimeFrequencyTextV2": "One Time", 6024 "cancelAnytimeLabelTextV2": "Cancel Anytime", 6025 "noSubscriptionLabelTextV2": "No Subscription", 6026 "addToShipmentButtonTextV2": "Add to Shipment", 6027 "addToShipmentProcessingV2": "Processing...", 6028 "addToShipmentSuccessTextV2": "Success", 6029 "addToShipmentErrorTextV2": "Error", 6030 "addToShipmentTooltipTextV2": "Please avoid double delivery charges! Login to add this product to an upcoming delivery.", 6031 "frequencyCombinedWidgetTextV2": "Frequency", 6032 "selectDeliverOptionV2": "select deliver option", 6033 "subscribeAndSaveSuccessV2": "Subscribe success", 6034 "unsubscribeFrequencyTextV2": "unsubscribe", 6035 "deliveryEveryFrequencyTextV2": "Delivery Every", 6036 "sellingPlanTitleTextNonPrepaid": "{{sellingPlanName}}", 6037 "subscribeAndSaveInitalV2": "Subscribe & save", 6038 "subscriptionDescriptionTextV2": "", 6039 "atcButtonTextSelector": "", 6040 "disableCartWidgetOnVariants": "", 6041 "shop": "good-sleep-co-gc.myshopify.com", 6042 "deliveryText": "delivery", 6043 "purchaseOptionsText": "Purchase Options", 6044 "manageSubscriptionButtonText": "Manage Subscription", 6045 "subscriptionOptionText": "Subscribe", 6046 "sellingPlanSelectTitle": "DELIVERY FREQUENCY", 6047 "subscriptionPriceDisplayText": "", 6048 "tooltipTitle": "Subscription detail", 6049 "showTooltipOnClick": "false", 6050 "tooltipDesctiption": `<strong>Have complete control of your subscriptions<\/strong><br\/><br\/>Skip, reschedule, edit, or cancel deliveries anytime, based on your needs.`, 6051 "tooltipDescriptionOnPrepaidPlan": "<b>Prepaid Plan Details<\/b><\/br> Total price: {{totalPrice}} ( Price for every delivery: {{pricePerDelivery}})", 6052 "tooltipDescriptionOnMultipleDiscount": "<b>Discount Details<\/b><\/br> Initial discount is {{discountOne}} and then {{discountTwo}}", 6053 "manualTranslation": "false", 6054 "tooltipDescriptionCustomization": "{{{defaultTooltipDescription}}} <\/br> {{{prepaidDetails}}} <\/br> {{{discountDetails}}}", 6055 "orderStatusManageSubscriptionTitle": "Subscription", 6056 "orderStatusManageSubscriptionDescription": "Continue to your account to view and manage your subscriptions. Please use the same email address that you used to buy the subscription.", 6057 "orderStatusManageSubscriptionButtonText": "Manage your subscription", 6058 "subscriptionOptionSelectedByDefault" : true, 6059 "totalPricePerDeliveryText" : "{{prepaidPerDeliveryPrice}}\/delivery", 6060 "memberOnlySellingPlansJson": {}, 6061 "nonMemberOnlySellingPlansJson": {}, 6062 "sellingPlansJson": [{"frequencyCount":1,"frequencyInterval":"MONTH","billingFrequencyCount":1,"billingFrequencyInterval":"MONTH","frequencyName":"Monthly","frequencyDescription":"A monthly delivery of our Cleaner solution.","discountOffer":20.0,"afterCycle1":0,"discountType":"PERCENTAGE","discountEnabled":true,"discountEnabledMasked":true,"id":"gid://shopify/SellingPlan/773587083","frequencyType":"ON_PURCHASE_DAY","specificDayEnabled":false,"cutOff":0,"prepaidFlag":"false","idNew":"gid://shopify/SellingPlan/773587083","planType":"PAY_AS_YOU_GO","deliveryPolicyPreAnchorBehavior":"ASAP","freeTrialEnabled":false,"memberOnly":false,"nonMemberOnly":false,"formFieldJson":"null","frequencySequence":0,"groupName":"Monthly Cleaner","groupId":219283595,"repeatingCycle":false,"defaultSelectedPlan":false,"inventoryPolicyReserve":"ON_SALE","appstleCycles":[]},{"frequencyCount":1,"frequencyInterval":"MONTH","billingFrequencyCount":1,"billingFrequencyInterval":"MONTH","frequencyName":"Monthly Subscription","frequencyDescription":"","afterCycle1":0,"afterCycle2":0,"discountEnabled":false,"discountEnabled2":false,"discountEnabledMasked":false,"discountEnabled2Masked":false,"id":"gid://shopify/SellingPlan/2068152459","frequencyType":"ON_PURCHASE_DAY","specificDayEnabled":false,"cutOff":0,"prepaidFlag":"false","idNew":"gid://shopify/SellingPlan/2068152459","planType":"PAY_AS_YOU_GO","deliveryPolicyPreAnchorBehavior":"ASAP","freeTrialEnabled":false,"memberOnly":false,"nonMemberOnly":false,"formFieldJson":"null","frequencySequence":0,"groupName":"Hushd Avera Subscription ","groupId":1153433739,"repeatingCycle":false,"defaultSelectedPlan":false,"frequencyNameTranslations":{},"inventoryPolicyReserve":"ON_SALE","appstleCycles":[]},{"frequencyCount":3,"frequencyInterval":"MONTH","billingFrequencyCount":3,"billingFrequencyInterval":"MONTH","frequencyName":"Quarterly Subscription","frequencyDescription":"","afterCycle1":0,"afterCycle2":0,"discountEnabled":false,"discountEnabled2":false,"discountEnabledMasked":false,"discountEnabled2Masked":false,"id":"gid://shopify/SellingPlan/2068185227","frequencyType":"ON_PURCHASE_DAY","specificDayEnabled":false,"cutOff":0,"prepaidFlag":"false","idNew":"gid://shopify/SellingPlan/2068185227","planType":"PAY_AS_YOU_GO","deliveryPolicyPreAnchorBehavior":"ASAP","freeTrialEnabled":false,"memberOnly":false,"nonMemberOnly":false,"formFieldJson":"[]","frequencySequence":1,"groupName":"Hushd Avera Subscription ","groupId":1153433739,"repeatingCycle":false,"defaultSelectedPlan":false,"frequencyNameTranslations":{},"inventoryPolicyReserve":"ON_SALE","appstleCycles":[]},{"frequencyCount":1,"frequencyInterval":"MONTH","billingFrequencyCount":1,"billingFrequencyInterval":"MONTH","frequencyName":"Monthly Subscription","frequencyDescription":"","discountOffer":10.0,"afterCycle1":0,"discountType":"PERCENTAGE","discountEnabled":true,"discountEnabledMasked":true,"id":"gid://shopify/SellingPlan/2655355019","frequencyType":"ON_PURCHASE_DAY","specificDayEnabled":false,"cutOff":0,"prepaidFlag":"false","idNew":"gid://shopify/SellingPlan/2655355019","planType":"PAY_AS_YOU_GO","deliveryPolicyPreAnchorBehavior":"ASAP","freeTrialEnabled":false,"memberOnly":false,"nonMemberOnly":false,"formFieldJson":"[]","frequencySequence":0,"groupName":"Magnesium Subscription ","groupId":1711603851,"repeatingCycle":false,"defaultSelectedPlan":false,"frequencyNameTranslations":{},"inventoryPolicyReserve":"ON_SALE","appstleCycles":[]}], 6063 "widgetEnabled": true, 6064 "showFreeGiftPrice" : true, 6065 "showFreeGiftComparePrice" : true, 6066 "enableFreeGiftLayout" : false, 6067 "freeGiftLabelText": "+ Free {{productName}}", 6068 "freeGiftBadgeText": "", 6069 "showTooltip" : true, 6070 "showCartWidgetOnBundleItems" : false, 6071 "prepaidOptionSelectedByDefault" : false, 6072 "disablePassingSellingPlanAsLineProperties" : false, 6073 "updateThemePrice" : false, 6074 "sortByDefaultSequence": false, 6075 "showSubOptionBeforeOneTime": false, 6076 "detectVariantFromURLParams": false, 6077 "disableQueryParamsUpdate": false, 6078 "showStaticTooltip": false, 6079 "showAppstleLink": true, 6080 "sellingPlanTitleText" : "{{sellingPlanName}} ({{sellingPlanPrice}}\/delivery)", 6081 "oneTimePriceText" : "{{price}}", 6082 "selectedPayAsYouGoSellingPlanPriceText" : "{{price}}", 6083 "selectedPrepaidSellingPlanPriceText" : " {{totalPrice}}", 6084 "selectedDiscountFormat" : "SAVE {{selectedDiscountPercentage}}", 6085 "manageSubscriptionBtnFormat" : "<a href='apps\/subscriptions' class='appstle_manageSubBtn' ><button class='btn' style='padding: 2px 20px'>Manage Subscription<\/button>
6085<a><br><br>", 6086 "manageSubscriptionUrl" : "https:\/\/goodsleepco.health\/apps\/subscriptions", 6087 "appstlePlanId": 161, 6088 "showCheckoutSubscriptionBtn": true, 6089 "priceSelector": "", 6090 "reloadPriceSelector": "", 6091 "landingPagePriceSelector": "", 6092 "quickViewClickSelector": "", 6093 "badgeTop": "", 6094 "pricePlacement": "BEFORE", 6095 "disableLoadingJquery": false, 6096 "widgetEnabledOnSoldVariant": "false", 6097 "switchRadioButtonWidget": true, 6098 "appstlePlanName": "FREE", 6099 "appstlePlanFeatures": {"analytics": true, "webhookAccess": false, "accessBundling": false, "enableAutoSync": false, "enableBundling": false, "enableSmsAlert": false, "accessBuildABox": false, "enableCampaigns": false, "enablePriceSync": false, "enableAutomation": false, "enableCartWidget": false, "accessAppstleMenu": false, "accessResendEmail": false, "enableAddressSync": false, "enableExternalApi": false, "enablePhasedRetry": false, "enableIntegrations": true, "enableQuickActions": false, "accessQuickCheckout": false, "accessSplitContract": false, "enableSummaryReports": false, "enableCustomEmailHtml": false, "enableWidgetPlacement": false, "enableCancellationFlow": false, "enableShippingProfiles": true, "accessZapierIntegration": true, "enableCustomEmailDomain": false, "enableDunningManagement": true, "enableExportActivityLog": true, "subscriptionOrderAmount": 500, "accessGorgiasIntegration": true, "accessKlaviyoContactSync": false, "enableOrderConsolidation": false, "accessMechanicIntegration": true, "accessWidgetDesignOptions": false, "enableImmediatePlaceOrder": false, "enableInventoryManagement": true, "accessMechanicsIntegration": true, "enableAdvancedSellingPlans": false, "accessOneTimeProductUpsells": false, "enableBillingIntervalChange": true, "enableProductSwapAutomation": false, "accessShopifyFlowIntegration": true, "enableCancellationManagement": false, "enableCustomerPortalSettings": true, "enableSubscriptionManagement": true, "accessKlaviyoEmailIntegration": true, "enableAdminNotificationAccess": true, "accessSubscriptionActivityLogs": true, "enableBackupPaymentMethodRetry": false, "accessSubscriberLoyaltyFeatures": false, "enableAddToExistingSubscription": false, "enableContractPriceModification": true, "enableTrackInventoryInSingleBAB": true, "accessManualSubscriptionCreation": false, "enableNextBillingDateModification": true, "accessCustomerPortalProductUpsells": false, "enableServerSideConversionTracking": false, "accessDiscountOnCancellationAttempt": false, "enableStorefrontAnalyticsForwarding": false, "accessAdvanceSubscriptionPlanOptions": false, "accessAdvancedCustomerPortalSettings": true}, 6100 "formMappingAttributeName": "", 6101 "formMappingAttributeSelector": "", 6102 "quickViewModalPollingSelector": "", 6103 "scriptLoadDelay": "0", 6104 "formatMoneyOverride": "false", 6105 "enableAddToExistingSubscriptionFeature": "false", 6106 "displayAddToExistingSubscriptionButtonForNotLoggedInV2": "", 6107 "showAddToSubscriptionButtonOnlyOnSubscriptionProducts": "false", 6108 "appstle_app_proxy_path_prefix": "apps\/subscriptions", 6109 "updatePriceOnQuantityChange": "", 6110 "widgetParentSelector": "", 6111 "quantitySelector": "", 6112 "enableAddJSInterceptor": "false", 6113 "isDevEnabled": false, 6114 "forceReloadWidgetSelector": "", 6115 "forceReloadOnFreqChange": false, 6116 "showPrepaidPlanSeparately": false, 6117 "debugLogsEnabled": false, 6118 "isUseStorefrontAPI": false, 6119 "reBuyEnabled": "false", 6120 "loyaltyDetailsLabelText": "", 6121 "loyaltyPerkDescriptionTextV2": "{{#isDiscountTypeFreeProduct}}<div style='display: flex;'><div style='height: 60px; width: 60px; flex-shrink: 0; margin-right: 10px;'><img style='width: 100%' src={{{featured_image}}}><\/img><\/div><div>After {{{billingCycleBlock}}} orders,<span style='color: #ffc000;font-weight: 700;';> get a FREE {{freeProductName}} <\/span><\/div><div>{{\/isDiscountTypeFreeProduct}}{{#isDiscountTypePercentage}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>
6121get <span style='color: #ffc000;font-weight: 700;';>{{{discount}}}% OFF your entire order<\/span><\/span>.{{\/isDiscountTypePercentage}}{{#isDiscountTypeShipping}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>get <span style='color: #ffc000;font-weight: 700;';>shipping at {{{formatDiscountedPrice}}}<\/span><\/span>.{{\/isDiscountTypeShipping}}{{#isDiscountTypeFixed}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>get <span style='color: #ffc000;font-weight: 700;';>{{{formatDiscountedPrice}}} OFF your entire order<\/span><\/span>.{{\/isDiscountTypeFixed}}", 6122 "widgetType": "WIDGET_TYPE_1", 6123 "collectionWidgetType": "LEGACY", 6124 "enableCompactProductPageWidget": false, 6125 "enableCartDrawerWidget": false, 6126 "cartDrawerWidgetStyle": false, 6127 "cartDrawerWidgetInlineStyle": "", 6128 "cartDrawerWidgetPanelStyle": "", 6129 "cartDrawerWidgetSegmentedStyle": "", 6130 "showOneTimeComparePrice": false, 6131 "showCombinedSellingPlanCartWidget": false, 6132 "combinedCartWidgetSelector": "", 6133 "removeUnsubscribeOption": false, 6134 "widgetTemplateHtml": `{% raw %}{% endraw %}`, 6135 6136 "allWidgetTemplateHtml": "{\"WIDGET_TYPE_1\":\"{% raw %}{% endraw %}\",\"WIDGET_TYPE_6\":\"{% raw %}<div id=\\\"appstle-widget-template\\\">\\n <div class=\\\"appstle_sub_widget\\\" id=\\\"appstle_subscription_widget{{widgetId}}\\\">\\n<div class=\\\"appstle_widget_title\\\">{{{purchaseOptionsText}}}</div>\\n <div class=\\\"widgetSellingPlanWrapper\\\">\\n{{^requires_selling_plan}}\\n{{^showSubOptionBeforeOneTime}}\\n <div class=\\\"appstle_input_wrapper appstle_onetime_block\\\">\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n<div class=\\\"appstle-selling-plan-name-wrapper\\\">\\n {{oneTimePuchaseText}}\\n<div class=\\\"appstle-cancel-text\\\">{{{noSubscriptionLabelTextV2}}}</div>\\n</div>\\n <div class=\\\"appstle-selling-plan-detail-wrapper\\\">\\n<div class=\\\"appstle_span_wrapper\\\">\\n{{#showOneTimeComparePrice}}\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount_compare\\\">\\n {{{oneTimePuchaseComparePriceAmount}}}\\n</span>\\n{{/showOneTimeComparePrice}}\\n\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount\\\">{{{oneTimePuchaseAmount}}}</span></div>\\n</div>\\n </label>\\n \\n </div>\\n{{/showSubOptionBeforeOneTime}}\\n{{/requires_selling_plan}}\\n {{#sellingPlanVariants}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n \\n <input type=\\\"radio\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" id=\\\"{{sellingPlanId}}\\\" value=\\\"{{sellingPlanId}}\\\" name=\\\"selling_plan\\\" {{#isChecked}}checked{{/isChecked}}>\\n{{^prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\">\\n<div class=\\\"appstle-selling-plan-name-wrapper appstle-selling-plan-label-name\\\">\\n {{{name}}}\\n<div class=\\\"appstle-cancel-text\\\">{{{cancelAnytimeLabelTextV2}}}</div>\\n</div>\\n<div class=\\\"appstle-selling-plan-detail-wrapper\\\">\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_formattedCompareAtPrice appstle_price_block\\\">{{{formattedCompareAtPrice}}}</span>\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{formattedPrice}}}</span>
6136\\n\\n\\n</div> \\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_formattext_block\\\"></span>\\n{{#showPricePerDay}}<div class=\\\"appstle-perday-price\\\">{{{pricePerDay}}}</div>{{/showPricePerDay}}\\n<div class=\\\"appstle-frequency-description\\\">\\n{{{frequencyDescription}}} \\n</div>\\n </div>\\n </label>\\n{{#showFormattedDiscountText}}\\n <span class=\\\"appstle_sellingPlan_discountText\\\">{{{formattedDiscountText}}}</span>\\n{{/showFormattedDiscountText}}\\n<div class=\\\"appstle-sm-hide appstle-frequency-description\\\">{{{frequencyDescription}}} </div> \\n{{/prepaidFlag}}\\n{{#prepaidFlag}}\\n<label for=\\\"{{sellingPlanId}}\\\">\\n<div class=\\\"appstle-selling-plan-name-wrapper appstle-selling-plan-label-name\\\">\\n {{{name}}}\\n<div class=\\\"appstle-cancel-text\\\">{{{cancelAnytimeLabelTextV2}}}</div>\\n</div>\\n<div class=\\\"appstle-selling-plan-detail-wrapper\\\">\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_formattedCompareAtPrice appstle_price_block\\\">{{{formattedCompareAtPrice}}}</span>\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{totalPrice}}}</span>\\n\\n</div> \\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block appstle_formattedPrepaidPerDeliveryPriceText\\\">{{{formattedPrepaidPerDeliveryPriceText}}}</span>\\n {{#showPricePerDay}}<div class=\\\"appstle-perday-price\\\">{{{pricePerDay}}}</div>{{/showPricePerDay}}\\n<div class=\\\"\\\">\\n<div class=\\\"appstle-frequency-description\\\">\\n{{{frequencyDescription}}} \\n</div>\\n</div>\\n</div>\\n</label>\\n{{#showFormattedDiscountText}}\\n <span class=\\\"appstle_sellingPlan_discountText\\\">{{{formattedDiscountText}}}</span>\\n{{/showFormattedDiscountText}}\\n<div class=\\\"appstle-sm-hide appstle-frequency-description\\\">{{{frequencyDescription}}} </div> \\n\\n{{/prepaidFlag}}\\n \\n </div>\\n {{/sellingPlanVariants}}\\n{{^requires_selling_plan}}\\n{{#showSubOptionBeforeOneTime}}\\n <div class=\\\"appstle_input_wrapper appstle_onetime_block\\\">\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n<div class=\\\"appstle-selling-plan-name-wrapper\\\">\\n {{oneTimePuchaseText}}\\n<div class=\\\"appstle-cancel-text\\\">{{{noSubscriptionLabelTextV2}}}</div>\\n</div>\\n<div class=\\\"appstle-selling-plan-detail-wrapper\\\">\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount_compare\\\">{{{oneTimePuchaseComparePriceAmount}}}</span>\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount\\\">{{{oneTimePuchaseAmount}}}</span>\\n\\n</div>\\n </label>\\n \\n </div>\\n{{/showSubOptionBeforeOneTime}}\\n{{/requires_selling_plan}}\\n </div>\\n{{#showStaticTooltip}}\\n<div class=\\\"appstle_tooltip_wrapper_static\\\"> {{{toolTipDescription}}}</div>\\n{{/showStaticTooltip}}\\n{{#showTooltip}}\\n<div class=\\\"appstle-tootltip-parent\\\">\\n <div data-appstle-icon=\\\"\\\" class=\\\"appstle_tooltip_wrapper\\\">\\n <svg width=\\\"90\\\" height=\\\"90\\\" viewBox=\\\"0 0 90 90\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"tooltip_subscription_svg\\\">\\n <path\\n d=\\\"M45 0C20.1827 0 0 20.1827 0 45C0 69.8173 20.1827 90 45 90C69.8173 90 90 69.8174 90 45C90.0056 44.6025 89.9322 44.2078 89.7839 43.8389C89.6357 43.47 89.4156 43.1342 89.1365 42.8511C88.8573 42.568 88.5247 42.3432 88.158 42.1897C87.7912 42.0363 87.3976 41.9573 87 41.9573C86.6024 41.9573 86.2088 42.0363 85.842 42.1897C85.4753 42.3432 85.1427 42.568 84.8635 42.8511C84.5844 43.1342 84.3643 43.47 84.2161 43.8389C84.0678 44.2078 83.9944 44.6025 84 45C84 66.5748 66.5747 84 45 84C23.4253 84 6 66.5747 6 45C6 23.4254 23.4253 6 45 6C56.1538 6 66.3012 10.5882 73.4375 18H65.4062C65.0087 17.9944 64.614 18.0678 64.2451 18.2161C63.8762 18.3643 63.5405 18.5844 63.2573 18.8635C62.9742 19.1427 62.7494 19.4753 62.596 19.842C62.4425 20.2088 62.3635 20.6024 62.3635 21C62.3635 21.3976 62.4425 21.7912 62.596 22.158C62.7494 22.5247 62.9742 22.8573 63.2573 23.1365C63.5405 23.4156 63.8762 23.6357 64.2451 23.7839C64.614 23.9322 65.0087 24.0056 65.4062 24H79.8125C80.6081 23.9999 81.3711 23.6838 81.9337 23.1212C82.4963 22.5586 82.8124 21.7956 82.8125 21V6.59375C82.821 6.18925 82.7476 5.78722 82.5966 5.41183C82.4457 5.03644 82.2205 4.69545 81.9344 4.40936C81.6483 4.12327 81.3073 3.898 80.9319 3.7471C80.5565 3.5962 80.1545 3.52277 79.75 3.53125C79.356 3.53941 78.9675 3.62511 78.6067 3.78344C78.2458 3.94177 77.9197 4.16963 77.6469 4.45402C77.3741 4.73841 77.16 5.07375 77.0168 5.44089C76.8737 5.80803 76.8042 6.19977 76.8125 6.59375V12.875C68.6156 4.86282 57.3081 0 45 0ZM43.75 20.75C43.356 20.7582 42.9675 20.8439 42.6067 21.0022C42.2458 21.1605 41.9197 21.3884 41.6469 21.6728C41.3741 21.9572 41.16 22.2925 41.0168 22.6596C40.8737 23.0268 40.8042 23.4185 40.8125 23.8125V47.375C40.8116 47.7693 40.8883 48.16 41.0385 48.5246C41.1886 48.8892 41.4092 49.2207 41.6875 49.5L54.0938 61.9375C54.6573 62.5011 55.4217 62.8177 56.2188 62.8177C57.0158 62.8177 57.7802 62.5011 58.3438 61.9375C58.9073 61.3739 59.224 60.6095 59.224 59.8125C59.224 59.0155 58.9073 58.2511 58.3438 57.6875L46.8125 46.1875V23.8125C46.821 23.408 46.7476 23.006 46.5966 22.6306C46.4457 22.2552 46.2205 21.9142 45.9344 21.6281C45.6483 21.342 45.3073 21.1168 44.9319 20.9658C44.5565 20.8149 44.1545 20.7415 43.75 20.75Z\\\"\\n ></path>\\n </svg>\\n <span class=\\\"appstle_tooltip_title\\\">{{{tooltipTitle}}}</span>\\n </div>\\n<div class=\\\"appstle_tooltip\\\">\\n <div class=\\\"appstle_tooltip_content\\\">\\n {{{toolTipDescription}}}\\n </div>\\n {{#showAppstleLink}}\\n <div class=\\\"appstle_tooltip_appstle\\\">\\n <a href=\\\"https://appstle.com\\\" class=\\\"appstle_link\\\" target=\\\"_blank\\\">\\n POWERED BY APPSTLE </a>\\n </div>\\n {{/showAppstleLink}}\\n </div>\\n</div>\\n{{/showTooltip}}\\n<style>\\n.widgetSellingPlanWrapper {\\n display: grid;\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n gap: 1.5rem;\\n grid-auto-rows: 1fr;\\n margin-bottom: 6px;\\nmargin-top: 10px;\\n}\\n\\n.widgetSellingPlanWrapper input {\\n display: none;\\n}\\n\\n.widgetSellingPlanWrapper label {\\n border-radius: 10px;\\n border: 1px solid rgba(var(--color-foreground));\\n padding: 0.5rem;\\n display: flex;\\n justify-content: center;
6136\\n align-items: center;\\n display: block;\\n height: 100%;\\n width: 100%;\\n text-align: center;\\ncursor: pointer;\\n}\\n\\n.widgetSellingPlanWrapper input:checked+label {\\n background-color: rgba(var(--color-foreground)) !important;\\ncolor: rgba(var(--color-background)) !important;\\n}\\n.appstle_lowercase {\\n text-transform: lowercase;\\n}\\n\\n\\n.appstle_input_wrapper {\\n position: relative;\\n}\\n\\nspan.appstle_sellingPlan_discountText {\\n position: absolute;\\n background: rgba(var(--color-foreground));\\n color: rgba(var(--color-background));\\n border-radius: 3px;\\n padding: 1px 18px;\\n left: 50%;\\n display: block;\\n transform: translate(-50%, -50%);\\n white-space: nowrap;\\n}\\n\\nspan.appstle_sellingPlan_discountText:empty {\\n display: none !important;\\n}\\ndiv.appstle_span_wrapper{\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n}\\n</style>\\n<style>\\n.widgetSellingPlanWrapper {\\n grid-template-columns: repeat(3, minmax(0, 1fr)) !important;\\n gap: 0.8rem !important;\\n}\\n\\n.appstle_sub_widget {\\n max-width: 100%!important;\\n} \\n\\n.widgetSellingPlanWrapper label {\\n height: auto !important;\\n border: none !important;\\n padding: 14px 5px !important;\\n display: flex !important;\\n justify-content: center !important;\\n align-items: center !important;\\n flex-direction: column;\\n max-width: 100% !important;\\n width: unset !important;\\nline-height: 20px;\\n}\\n\\n.appstle_how_does_it_work {\\n line-height: 16px !important;\\n margin: 6px 0px;\\n color: rgba(var(--color-background));\\n}\\n@media screen and (max-width: 800px) {\\n .appstle_how_does_it_work {\\n text-align: right;\\n }\\n}\\n\\nspan.appstle_lowercase.appstle_sellingPlan_price.appstle_formattext_block {\\ntext-align: right !important;\\n display: block;\\n}\\n\\n.appstle_span_wrapper {\\n align-items: baseline;\\n}\\n\\nspan.appstle_lowercase.appstle_sellingPlan_price.appstle_discount_block.appstle_formattedPrepaidPerDeliveryPriceText {\\n display: block;\\n text-align: right;\\n}\\n\\n.appstle_input_wrapper {\\n display: flex;\\n height: 100% !important;\\nflex-direction: column;\\n}\\n\\n.appstle_sub_widget input[type=radio]+label:before {\\n content: \\\"\\\";\\n position: absolute;\\n inset: 0;\\n border-radius: 12px;\\n padding: 2px;\\n background: #121212;\\n -webkit-mask: linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);\\n -webkit-mask-composite: xor;\\n mask-composite: exclude;\\n pointer-events: none;\\n z-index: 0;\\n transition: all 0.2s;\\n}\\n\\n.appstle_sub_widget input[type=radio]:checked+label:before {\\n content: \\\"\\\";\\n position: absolute;\\n inset: 0;\\n border-radius: 12px;\\n // padding: 4px;\\n// background: linear-gradient(to right,#Fef58f,#7A3900);\\n//background: #E53D29;\\n border: 2px transparent;\\n -webkit-mask: linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);\\n -webkit-mask-composite: xor;\\n mask-composite: exclude;\\n pointer-events: none;\\n z-index: 0;\\n}\\n\\nspan.appstle_sellingPlan_discountText {\\n background: rgba(var(--color-foreground));\\n border-radius: 100px !important;\\n padding: 0px 8px !important;\\n height: 20px;\\n display: flex !important;\\n justify-content: center;\\n align-items: center;\\n letter-spacing: 1px;\\nz-index: 2;\\n}\\nspan.appstle_lowercase.appstle_sellingPlan_price.appstle_onetime_amount_compare {\\ntext-decoration: line-through;\\n}\\n\\n\\nspan.appstle-popular {\\n position: absolute;\\n top: -40px;\\n background: black;\\n color: rgba(var(--color-background));\\n z-index: -3;\\n border-radius: 10px;\\n padding: 0px 10px 29px 10px;\\nleft: 0;\\n}\\n\\n.widgetSellingPlanWrapper label {\\n border-radius: 14px;\\n}\\n\\n.widgetSellingPlanWrapper input:checked+label {\\n overflow: hidden;\\n}\\n\\n\\n.appstle-perday-price {\\ndisplay: none;\\n}\\n\\n .widgetSellingPlanWrapper {\\n grid-template-columns: repeat(1, minmax(0, 1fr)) !important;\\n}\\n\\n.widgetSellingPlanWrapper label {\\n flex-direction: row;\\n justify-content: space-between !important;
6136\\n align-items: flex-start !important;\\nwidth: 100% !important;\\n}\\n\\n.widgetSellingPlanWrapper label {\\n text-align: left;\\n padding: 16px !important;\\nflex-basis: unset;\\n}\\n\\n.appstle_span_wrapper {\\n justify-content: flex-end !important;\\n}\\n\\n.appstle-perday-price {\\n text-align: right;\\n}\\n\\n.widgetSellingPlanWrapper {\\n gap: 15px !important;\\n}\\n\\nspan.appstle-popular {\\n width: calc(100% - 20px);\\n text-align: center;\\n letter-spacing: 2px;\\n top: -30px;\\nleft: 0;\\n}\\n\\nspan.appstle_sellingPlan_discountText { \\nleft: unset !important;\\n right: 15px;\\n transform: translate(0, -50%) !important;\\n}\\n.appstle-cancel-text {\\n text-align: left;\\n}\\n\\n.appstle_input_wrapper label {\\n text-align: left !important;\\n}\\n\\n.widgetSellingPlanWrapper input:checked+label {\\n width: 100% !important;\\n margin: 0 !important;\\n}\\n.appstle_input_wrapper {\\n width: 100% !important;\\nflex-direction: row;\\n}\\n.widgetSellingPlanWrapper input:checked+label+span {\\n background: rgba(var(--color-background)) !important;\\n color:rgba(var(--color-foreground)) !important;\\n border: 2px solid rgba(var(--color-foreground));\\n}\\n.appstle_onetime_block .appstle_span_wrapper {\\n grid-column: 2;\\n}\\n.appstle-frequency-description {\\n text-align: right !important;\\n}\\n\\n\\n.appstle-sm-hide {\\n display: none;\\n}\\n\\n@media screen and (min-width: 800px) {\\n.appstle-lg-show {\\n display: block;\\n}\\n.appstle-lg-hide {\\n display: none;\\n}\\n\\n}\\n\\nspan.appstle_lowercase.appstle_sellingPlan_formattedCompareAtPrice.appstle_price_block {\\n text-decoration: line-through;\\n display: block;\\n margin-right: 3px;\\n color: rgba(var(--color-foreground));\\n}\\n.widgetSellingPlanWrapper input:checked+label .appstle_sellingPlan_formattedCompareAtPrice {\\ncolor:rgba(var(--color-background));\\n} \\n\\n.appstle_span_wrapper > * {\\nflex-shrink: 0\\n}\\n.appstle-selling-plan-detail-wrapper{\\ncolor: rgba(var(--color-foreground));\\n}\\n.widgetSellingPlanWrapper input:checked+label .appstle-selling-plan-detail-wrapper{\\ncolor: rgba(var(--color-background)) !important;\\n}\\n\\n</style>\\n</div>{% endraw %}\",\"WIDGET_TYPE_7\":\"{% raw %}{% endraw %}\",\"WIDGET_TYPE_8\":\"{% raw %}{% endraw %}\",\"WIDGET_TYPE_2\":\"{% raw %}{% endraw %}\",\"WIDGET_TYPE_3\":\"{% raw %}<div id=\\\"appstle-widget-template\\\">\\n <div class=\\\"appstle_sub_widget\\\" id=\\\"appstle_subscription_widget{{widgetId}}\\\">\\n<div class=\\\"appstle_widget_title\\\">{{{purchaseOptionsText}}}</div>\\n <div class=\\\"widgetSellingPlanWrapper appstle_subscription_wrapper\\\">\\n{{#showSubOptionBeforeOneTime}}\\n {{#sellingPlanVariants}}\\n <div class=\\\"appstle_input_wrapper appstle_subscription_option\\\">\\n <input type=\\\"radio\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" id=\\\"{{sellingPlanId}}\\\" value=\\\"{{sellingPlanId}}\\\" name=\\\"selling_plan\\\" {{#isChecked}}checked{{/isChecked}}>\\n {{^prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\" class=\\\"appstle_widget_three\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{formattedPrice}}}</span>\\n{{#showSecondFormattedDiscountText}}{{^isFixedPrice}}<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block\\\"> ({{{secondFormattedDiscountText}}})</span> {{/isFixedPrice}}{{/showSecondFormattedDiscountText}}\\n</div>\\n \\n </label>\\n {{/prepaidFlag}}\\n {{#prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\" class=\\\"appstle_widget_three\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{totalPrice}}}</span>\\n {{#showSecondFormattedDiscountText}}{{^isFixedPrice}}<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block\\\"> ({{{secondFormattedDiscountText}}})</span>{{/isFixedPrice}}{{/showSecondFormattedDiscountText}}\\n {{#formattedPrepaidPerDeliveryPriceText}}<span class=\\\"appstle_formattedPrepaidPerDeliveryPriceText\\\"> ({{{formattedPrepaidPerDeliveryPriceText}}})</span>{{/formattedPrepaidPerDeliveryPriceText}}\\n </div>\\n \\n </label>\\n {{/prepaidFlag}}\\n \\n </div>\\n {{/sellingPlanVariants}}\\n{{/showSubOptionBeforeOneTime}}\\n {{^requires_selling_plan}}\\n <div class=\\\"appstle_input_wrapper appstle_onetime\\\">
6136\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"{{sellingPlanId}}\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" class=\\\"appstle_widget_three\\\">\\n {{oneTimePuchaseText}}\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount\\\">\\n{{#showOneTimeComparePrice}}\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount_compare\\\">\\n {{{oneTimePuchaseComparePriceAmount}}}\\n</span>\\n{{/showOneTimeComparePrice}}\\n{{{oneTimePuchaseAmount}}}</span>\\n </label>\\n \\n </div>\\n {{/requires_selling_plan}}\\n{{^showSubOptionBeforeOneTime}}\\n {{#sellingPlanVariants}}\\n <div class=\\\"appstle_input_wrapper appstle_subscription_option\\\">\\n <input type=\\\"radio\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" id=\\\"{{sellingPlanId}}\\\" value=\\\"{{sellingPlanId}}\\\" name=\\\"selling_plan\\\" {{#isChecked}}checked{{/isChecked}}>\\n {{^prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\" class=\\\"appstle_widget_three\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{formattedPrice}}}</span>\\n{{#showSecondFormattedDiscountText}}{{^isFixedPrice}}<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block\\\"> ({{{secondFormattedDiscountText}}})</span> {{/isFixedPrice}}{{/showSecondFormattedDiscountText}}\\n</div>\\n \\n </label>\\n {{/prepaidFlag}}\\n {{#prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\" class=\\\"appstle_widget_three\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{totalPrice}}}</span>\\n {{#showSecondFormattedDiscountText}}{{^isFixedPrice}}<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block\\\"> ({{{secondFormattedDiscountText}}})</span>{{/isFixedPrice}}{{/showSecondFormattedDiscountText}}\\n {{#formattedPrepaidPerDeliveryPriceText}}<span class=\\\"appstle_formattedPrepaidPerDeliveryPriceText\\\"> ({{{formattedPrepaidPerDeliveryPriceText}}})</span>{{/formattedPrepaidPerDeliveryPriceText}}\\n </div>\\n \\n </label>\\n {{/prepaidFlag}}\\n \\n </div>\\n {{/sellingPlanVariants}}\\n{{/showSubOptionBeforeOneTime}}\\n </div>\\n{{#showStaticTooltip}}\\n<div class=\\\"appstle_tooltip_wrapper_static\\\">{{{toolTipDescription}}}</div>\\n{{/showStaticTooltip}}\\n{{#showTooltip}}\\n <div data-appstle-icon=\\\"\\\" class=\\\"appstle_tooltip_wrapper\\\">\\n <svg width=\\\"90\\\" height=\\\"90\\\" viewBox=\\\"0 0 90 90\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"tooltip_subscription_svg\\\">\\n <path\\n d=\\\"M45 0C20.1827 0 0 20.1827 0 45C0 69.8173 20.1827 90 45 90C69.8173 90 90 69.8174 90 45C90.0056 44.6025 89.9322 44.2078 89.7839 43.8389C89.6357 43.47 89.4156 43.1342 89.1365 42.8511C88.8573 42.568 88.5247 42.3432 88.158 42.1897C87.7912 42.0363 87.3976 41.9573 87 41.9573C86.6024 41.9573 86.2088 42.0363 85.842 42.1897C85.4753 42.3432 85.1427 42.568 84.8635 42.8511C84.5844 43.1342 84.3643 43.47 84.2161 43.8389C84.0678 44.2078 83.9944 44.6025 84 45C84 66.5748 66.5747 84 45 84C23.4253 84 6 66.5747 6 45C6 23.4254 23.4253 6 45 6C56.1538 6 66.3012 10.5882 73.4375 18H65.4062C65.0087 17.9944 64.614 18.0678 64.2451 18.2161C63.8762 18.3643 63.5405 18.5844 63.2573 18.8635C62.9742 19.1427 62.7494 19.4753 62.596 19.842C62.4425 20.2088 62.3635 20.6024 62.3635 21C62.3635 21.3976 62.4425 21.7912 62.596 22.158C62.7494 22.5247 62.9742 22.8573 63.2573 23.1365C63.5405 23.4156 63.8762 23.6357 64.2451 23.7839C64.614 23.9322 65.0087 24.0056 65.4062 24H79.8125C80.6081 23.9999 81.3711 23.6838 81.9337 23.1212C82.4963 22.5586 82.8124 21.7956 82.8125 21V6.59375C82.821 6.18925 82.7476 5.78722 82.5966 5.41183C82.4457 5.03644 82.2205 4.69545 81.9344 4.40936C81.6483 4.12327 81.3073 3.898 80.9319 3.7471C80.5565 3.5962 80.1545 3.52277 79.75 3.53125C79.356 3.53941 78.9675 3.62511 78.6067 3.78344C78.2458 3.94177 77.9197 4.16963 77.6469 4.45402C77.3741 4.73841 77.16 5.07375 77.0168 5.44089C76.8737 5.80803 76.8042 6.19977 76.8125 6.59375V12.875C68.6156 4.86282 57.3081 0 45 0ZM43.75 20.75C43.356 20.7582 42.9675 20.8439 42.6067 21.0022C42.2458 21.1605 41.9197 21.3884 41.6469 21.6728C41.3741 21.9572 41.16 22.2925 41.0168 22.6596C40.8737 23.0268 40.8042 23.4185 40.8125 23.8125V47.375C40.8116 47.7693 40.8883 48.16 41.0385 48.5246C41.1886 48.8892 41.4092 49.2207 41.6875 49.5L54.0938 61.9375C54.6573 62.5011 55.4217 62.8177 56.2188 62.8177C57.0158 62.8177 57.7802 62.5011 58.3438 61.9375C58.9073 61.3739 59.224 60.6095 59.224 59.8125C59.224 59.0155 58.9073 58.2511 58.3438 57.6875L46.8125 46.1875V23.8125C46.821 23.408 46.7476 23.006 46.5966 22.6306C46.4457 22.2552 46.2205 21.9142 45.9344 21.6281C45.6483 21.342 45.3073 21.1168 44.9319 20.9658C44.5565 20.8149 44.1545 20.7415 43.75 20.75Z\\\"\\n ></path>\\n </svg>\\n <span class=\\\"appstle_tooltip_title\\\">{{{tooltipTitle}}}</span>\\n </div>\\n<div class=\\\"appstle_tooltip appstle_tooltip_hover\\\">\\n <div class=\\\"appstle_tooltip_content\\\">\\n {{{toolTipDescription}}}\\n </div>\\n {{#showAppstleLink}}\\n <div class=\\\"appstle_tooltip_appstle\\\">\\n <a href=\\\"https://appstle.com\\\" class=\\\"appstle_link\\\" target=\\\"_blank\\\">\\n POWERED BY APPSTLE\\n </a>\\n </div>\\n{{/showAppstleLink}}\\n </div>\\n{{/showTooltip}}\\n<style>.widgetSellingPlanWrapper {\\n display: grid;\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n gap: 0.5rem;\\n grid-auto-rows: 1fr;\\n margin-bottom: 6px;\\n}\\n.widgetSellingPlanWrapper input {\\n display: none;\\n}\\n.widgetSellingPlanWrapper label {\\n border-radius: 8px;\\n border: 1px solid rgba(var(--color-foreground));\\n padding: 0.5rem;\\n display: flex;\\n justify-content: center;
6136\\n align-items: center;\\n display: block;\\n height: 100%;\\n width: 100%;\\n text-align: center;\\ncursor: pointer;\\ncolor: rgba(var(--color-foreground));\\n}\\n.widgetSellingPlanWrapper input:checked+label {\\n background-color: rgba(var(--color-foreground));\\n color: rgba(var(--color-background));\\n border: 1px solid rgba(var(--color-background)) !important;\\n}\\n.appstle_lowercase {\\n text-transform: lowercase;\\n}\\n.appstle_input_wrapper {\\n position: relative;\\n}\\nspan.appstle_sellingPlan_discountText {\\n position: absolute;\\n background-color: color: rgba(var(--color-foreground));\\n color: rgba(var(--color-background));\\n border-radius: 3px;\\n padding: 1px 18px;\\n left: 50%;\\n display: block;\\n transform: translate(-50%, -50%);\\n white-space: nowrap;\\n}\\nspan.appstle_sellingPlan_discountText:empty {\\n display: none !important;\\n}\\nspan.appstle_lowercase.appstle_sellingPlan_price {\\n color: rgba(var(--color-foreground));\\n}\\nspan.appstle_lowercase.appstle_sellingPlan_price.appstle_onetime_amount_compare {\\n color: rgba(var(--color-foreground));\\n text-decoration: line-through;\\n padding: 0 3px;\\n}\\n#appstle_subscription_widget0 .appstle_tooltip_wrapper {\\n margin-top: 8px;\\n margin-bottom: 16px;\\n}\\n.appstle_subscription_wrapper {\\n border: none !important;\\n}\\nlabel.appstle_widget_three {\\n display: flex;\\n flex-direction: column;\\n}\\n.widgetSellingPlanWrapper input:checked+label span {\\n color: rgba(var(--color-background)) !important;\\n}\\n.appstle_sub_widget .appstle_subscription_wrapper{\\n border-radius:unset !important;\\n}\\nspan.appstle_second_price_block:empty {\\n display: none !important;\\n}\\n</style>\\n</div>{% endraw %}\",\"WIDGET_TYPE_4\":\"{% raw %}<div id=\\\"appstle-widget-template\\\">\\n <div class=\\\"appstle_sub_widget\\\" id=\\\"appstle_subscription_widget{{widgetId}}\\\">\\n<div class=\\\"appstle_widget_title\\\">{{{purchaseOptionsText}}}</div>\\n <div class=\\\"widgetSellingPlanWrapper\\\">\\n{{^requires_selling_plan}}\\n{{^showSubOptionBeforeOneTime}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n {{oneTimePuchaseText}}\\n{{#showOneTimeComparePrice}}\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount_compare\\\">\\n {{{oneTimePuchaseComparePriceAmount}}}\\n</span>\\n{{/showOneTimeComparePrice}}\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount\\\">{{{oneTimePuchaseAmount}}}/{{{oneTimeFrequencyText}}}</span>\\n </label>\\n </div>\\n{{/showSubOptionBeforeOneTime}}\\n{{/requires_selling_plan}}\\n {{#sellingPlanVariants}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n <span class=\\\"appstle_sellingPlan_discountText\\\">{{{formattedDiscountText}}}</span>\\n <input type=\\\"radio\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" id=\\\"{{sellingPlanId}}\\\" value=\\\"{{sellingPlanId}}\\\" name=\\\"selling_plan\\\" {{#isChecked}}checked{{/isChecked}}>\\n{{^prepaidFlag}}\\n <label for=\\\"{{sellingPlanId}}\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{formattedPrice}}}<span>\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_formattext_block\\\">/{{{sellingPlanFrequencyText}}}{{#isFrequencySubsequent}}{{/isFrequencySubsequent}}</span>\\n</div>\\n </label>\\n{{/prepaidFlag}}\\n{{#prepaidFlag}}\\n<label for=\\\"{{sellingPlanId}}\\\">\\n {{{name}}}\\n<div class=\\\"appstle_span_wrapper\\\">\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_price_block\\\">{{{totalPrice}}}</span>\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_discount_block appstle_formattedPrepaidPerDeliveryPriceText\\\"> {{{formattedPrepaidPerDeliveryPriceText}}}</span>\\n</div>\\n</label>\\n{{/prepaidFlag}}\\n </div>\\n {{/sellingPlanVariants}}\\n{{^requires_selling_plan}}\\n{{#showSubOptionBeforeOneTime}}\\n <div class=\\\"appstle_input_wrapper\\\">
6136\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n {{oneTimePuchaseText}}\\n{{#showOneTimeComparePrice}}\\n<span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount_compare\\\">\\n {{{oneTimePuchaseComparePriceAmount}}}\\n</span>\\n{{/showOneTimeComparePrice}}\\n <span class=\\\"appstle_lowercase appstle_sellingPlan_price appstle_onetime_amount\\\">{{{oneTimePuchaseAmount}}}/{{{oneTimeFrequencyText}}}</span>\\n </label>\\n </div>\\n{{/showSubOptionBeforeOneTime}}\\n{{/requires_selling_plan}}\\n </div>\\n{{#showStaticTooltip}}\\n<div class=\\\"appstle_tooltip_wrapper_static\\\"> {{{toolTipDescription}}}</div>\\n{{/showStaticTooltip}}\\n{{#showTooltip}}\\n <div data-appstle-icon=\\\"\\\" class=\\\"appstle_tooltip_wrapper\\\">\\n <svg width=\\\"90\\\" height=\\\"90\\\" viewBox=\\\"0 0 90 90\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"tooltip_subscription_svg\\\">\\n <path\\n d=\\\"M45 0C20.1827 0 0 20.1827 0 45C0 69.8173 20.1827 90 45 90C69.8173 90 90 69.8174 90 45C90.0056 44.6025 89.9322 44.2078 89.7839 43.8389C89.6357 43.47 89.4156 43.1342 89.1365 42.8511C88.8573 42.568 88.5247 42.3432 88.158 42.1897C87.7912 42.0363 87.3976 41.9573 87 41.9573C86.6024 41.9573 86.2088 42.0363 85.842 42.1897C85.4753 42.3432 85.1427 42.568 84.8635 42.8511C84.5844 43.1342 84.3643 43.47 84.2161 43.8389C84.0678 44.2078 83.9944 44.6025 84 45C84 66.5748 66.5747 84 45 84C23.4253 84 6 66.5747 6 45C6 23.4254 23.4253 6 45 6C56.1538 6 66.3012 10.5882 73.4375 18H65.4062C65.0087 17.9944 64.614 18.0678 64.2451 18.2161C63.8762 18.3643 63.5405 18.5844 63.2573 18.8635C62.9742 19.1427 62.7494 19.4753 62.596 19.842C62.4425 20.2088 62.3635 20.6024 62.3635 21C62.3635 21.3976 62.4425 21.7912 62.596 22.158C62.7494 22.5247 62.9742 22.8573 63.2573 23.1365C63.5405 23.4156 63.8762 23.6357 64.2451 23.7839C64.614 23.9322 65.0087 24.0056 65.4062 24H79.8125C80.6081 23.9999 81.3711 23.6838 81.9337 23.1212C82.4963 22.5586 82.8124 21.7956 82.8125 21V6.59375C82.821 6.18925 82.7476 5.78722 82.5966 5.41183C82.4457 5.03644 82.2205 4.69545 81.9344 4.40936C81.6483 4.12327 81.3073 3.898 80.9319 3.7471C80.5565 3.5962 80.1545 3.52277 79.75 3.53125C79.356 3.53941 78.9675 3.62511 78.6067 3.78344C78.2458 3.94177 77.9197 4.16963 77.6469 4.45402C77.3741 4.73841 77.16 5.07375 77.0168 5.44089C76.8737 5.80803 76.8042 6.19977 76.8125 6.59375V12.875C68.6156 4.86282 57.3081 0 45 0ZM43.75 20.75C43.356 20.7582 42.9675 20.8439 42.6067 21.0022C42.2458 21.1605 41.9197 21.3884 41.6469 21.6728C41.3741 21.9572 41.16 22.2925 41.0168 22.6596C40.8737 23.0268 40.8042 23.4185 40.8125 23.8125V47.375C40.8116 47.7693 40.8883 48.16 41.0385 48.5246C41.1886 48.8892 41.4092 49.2207 41.6875 49.5L54.0938 61.9375C54.6573 62.5011 55.4217 62.8177 56.2188 62.8177C57.0158 62.8177 57.7802 62.5011 58.3438 61.9375C58.9073 61.3739 59.224 60.6095 59.224 59.8125C59.224 59.0155 58.9073 58.2511 58.3438 57.6875L46.8125 46.1875V23.8125C46.821 23.408 46.7476 23.006 46.5966 22.6306C46.4457 22.2552 46.2205 21.9142 45.9344 21.6281C45.6483 21.342 45.3073 21.1168 44.9319 20.9658C44.5565 20.8149 44.1545 20.7415 43.75 20.75Z\\\"\\n ></path>\\n </svg>\\n <span class=\\\"appstle_tooltip_title\\\">{{{tooltipTitle}}}</span>\\n </div>\\n <div class=\\\"appstle_tooltip\\\">\\n <div class=\\\"appstle_tooltip_content\\\">\\n {{{toolTipDescription}}}\\n </div>\\n{{#showAppstleLink}}\\n <div class=\\\"appstle_tooltip_appstle\\\">\\n <a href=\\\"https://appstle.com\\\" class=\\\"appstle_link\\\" target=\\\"_blank\\\">\\n POWERED BY APPSTLE\\n </a>\\n </div>\\n{{/showAppstleLink}}\\n </div>\\n{{/showTooltip}}\\n<style>\\n.widgetSellingPlanWrapper {\\n display: grid;\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n gap: 16px;\\n grid-auto-rows: 1fr;\\n margin-bottom: 6px;\\nmargin-top: 10px\\n}\\n.widgetSellingPlanWrapper input {\\n display: none;\\n}\\n.widgetSellingPlanWrapper label {\\n border-radius: 10px;\\n border: 1px solid rgba(var(--color-foreground, 0, 0, 0));\\n padding: 0.5rem;\\n display: flex !important;\\n flex-direction: column;\\n justify-content: center;
6136\\n align-items: center;\\n display: block;\\n height: 100%;\\n width: 100%;\\n text-align: center;\\ncursor: pointer;\\n}\\n.widgetSellingPlanWrapper input:checked+label {\\n background-color: rgba(var(--color-foreground, 0, 0, 0));\\n}\\n.appstle_lowercase {\\n text-transform: lowercase;\\n}\\n.appstle_input_wrapper {\\n position: relative;\\n}\\nspan.appstle_sellingPlan_discountText {\\n position: absolute;\\n font-size: 1.2rem;\\n background-color: rgba(var(--color-foreground, 0, 0, 0));\\n color: rgba(var(--color-background, 255, 255, 255));\\n border-radius: 3px;\\n border: 2px solid rgba(var(--color-background, 255, 255, 255));\\n padding: 1px 18px;\\n left: 50%;\\n display: block;\\n transform: translate(-50%, -50%);\\n white-space: nowrap;\\n}\\nspan.appstle_sellingPlan_discountText:empty {\\n display: none !important;\\n}\\nspan.appstle_lowercase.appstle_sellingPlan_price.appstle_onetime_amount_compare {\\ntext-decoration: line-through;\\n}\\n.appstle_tooltip_wrapper {\\n margin-bottom:10px;\\n}\\n.widgetSellingPlanWrapper input:checked+label {\\n background-color: rgba(var(--color-foreground, 0, 0, 0));\\n color: rgba(var(--color-background, 255, 255, 255));\\n border: 2px solid rgba(var(--color-background, 255, 255, 255)) !important;\\n}\\n</style>\\n</div>{% endraw %}\",\"WIDGET_TYPE_5\":\"{% raw %}<div id=\\\"appstle-widget-template\\\">\\n <div class=\\\"appstle_sub_widget\\\" id=\\\"appstle_subscription_widget{{widgetId}}\\\">\\n<div class=\\\"appstle_widget_title\\\">{{{purchaseOptionsText}}}</div>\\n <div class=\\\"widgetSellingPlanWrapper\\\">\\n{{^showSubOptionBeforeOneTime}}\\n{{^requires_selling_plan}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}/>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n {{{oneTimePuchaseText}}}\\n </label>\\n \\n </div>\\n{{/requires_selling_plan}}\\n{{/showSubOptionBeforeOneTime}}\\n {{#sellingPlanVariants}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n <input type=\\\"radio\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" id=\\\"{{sellingPlanId}}\\\" value=\\\"{{sellingPlanId}}\\\" name=\\\"selling_plan\\\" {{#isChecked}}checked{{/isChecked}} />\\n <label for=\\\"{{sellingPlanId}}\\\">\\n {{{name}}}\\n </label>\\n \\n </div>\\n {{/sellingPlanVariants}}\\n{{#showSubOptionBeforeOneTime}}\\n{{^requires_selling_plan}}\\n <div class=\\\"appstle_input_wrapper\\\">\\n <input type=\\\"radio\\\" id=\\\"appstle_selling_plan_label_1{{widgetId}}\\\" name=\\\"selling_plan\\\" value=\\\"\\\" class=\\\"appstleSellingPlan{{widgetId}}\\\" {{^subscriptionOptionSelectedDefault}}checked{{/subscriptionOptionSelectedDefault}}/>\\n <label for=\\\"appstle_selling_plan_label_1{{widgetId}}\\\">\\n {{{oneTimePuchaseText}}}\\n </label>\\n \\n </div>\\n{{/requires_selling_plan}}\\n{{/showSubOptionBeforeOneTime}}\\n </div>\\n{{#showStaticTooltip}}\\n<div class=\\\"appstle_tooltip_wrapper_static\\\">{{{toolTipDescription}}}</div>\\n{{/showStaticTooltip}}\\n{{#showTooltip}}\\n <div data-appstle-icon=\\\"\\\" class=\\\"appstle_tooltip_wrapper\\\">\\n <svg width=\\\"90\\\" height=\\\"90\\\" viewBox=\\\"0 0 90 90\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"tooltip_subscription_svg\\\">\\n <path\\n d=\\\"M45 0C20.1827 0 0 20.1827 0 45C0 69.8173 20.1827 90 45 90C69.8173 90 90 69.8174 90 45C90.0056 44.6025 89.9322 44.2078 89.7839 43.8389C89.6357 43.47 89.4156 43.1342 89.1365 42.8511C88.8573 42.568 88.5247 42.3432 88.158 42.1897C87.7912 42.0363 87.3976 41.9573 87 41.9573C86.6024 41.9573 86.2088 42.0363 85.842 42.1897C85.4753 42.3432 85.1427 42.568 84.8
6136635 42.8511C84.5844 43.1342 84.3643 43.47 84.2161 43.8389C84.0678 44.2078 83.9944 44.6025 84 45C84 66.5748 66.5747 84 45 84C23.4253 84 6 66.5747 6 45C6 23.4254 23.4253 6 45 6C56.1538 6 66.3012 10.5882 73.4375 18H65.4062C65.0087 17.9944 64.614 18.0678 64.2451 18.2161C63.8762 18.3643 63.5405 18.5844 63.2573 18.8635C62.9742 19.1427 62.7494 19.4753 62.596 19.842C62.4425 20.2088 62.3635 20.6024 62.3635 21C62.3635 21.3976 62.4425 21.7912 62.596 22.158C62.7494 22.5247 62.9742 22.8573 63.2573 23.1365C63.5405 23.4156 63.8762 23.6357 64.2451 23.7839C64.614 23.9322 65.0087 24.0056 65.4062 24H79.8125C80.6081 23.9999 81.3711 23.6838 81.9337 23.1212C82.4963 22.5586 82.8124 21.7956 82.8125 21V6.59375C82.821 6.18925 82.7476 5.78722 82.5966 5.41183C82.4457 5.03644 82.2205 4.69545 81.9344 4.40936C81.6483 4.12327 81.3073 3.898 80.9319 3.7471C80.5565 3.5962 80.1545 3.52277 79.75 3.53125C79.356 3.53941 78.9675 3.62511 78.6067 3.78344C78.2458 3.94177 77.9197 4.16963 77.6469 4.45402C77.3741 4.73841 77.16 5.07375 77.0168 5.44089C76.8737 5.80803 76.8042 6.19977 76.8125 6.59375V12.875C68.6156 4.86282 57.3081 0 45 0ZM43.75 20.75C43.356 20.7582 42.9675 20.8439 42.6067 21.0022C42.2458 21.1605 41.9197 21.3884 41.6469 21.6728C41.3741 21.9572 41.16 22.2925 41.0168 22.6596C40.8737 23.0268 40.8042 23.4185 40.8125 23.8125V47.375C40.8116 47.7693 40.8883 48.16 41.0385 48.5246C41.1886 48.8892 41.4092 49.2207 41.6875 49.5L54.0938 61.9375C54.6573 62.5011 55.4217 62.8177 56.2188 62.8177C57.0158 62.8177 57.7802 62.5011 58.3438 61.9375C58.9073 61.3739 59.224 60.6095 59.224 59.8125C59.224 59.0155 58.9073 58.2511 58.3438 57.6875L46.8125 46.1875V23.8125C46.821 23.408 46.7476 23.006 46.5966 22.6306C46.4457 22.2552 46.2205 21.9142 45.9344 21.6281C45.6483 21.342 45.3073 21.1168 44.9319 20.9658C44.5565 20.8149 44.1545 20.7415 43.75 20.75Z\\\"\\n ></path>\\n </svg>\\n <span class=\\\"appstle_tooltip_title\\\">{{{tooltipTitle}}}</span>\\n </div>\\n<div class=\\\"appstle_tooltip appstle_tooltip_hover\\\">\\n <div class=\\\"appstle_tooltip_content\\\">\\n {{{toolTipDescription}}}\\n </div>\\n {{#showAppstleLink}}\\n <div class=\\\"appstle_tooltip_appstle\\\">\\n <a href=\\\"https://appstle.com\\\" class=\\\"appstle_link\\\" target=\\\"_blank\\\">\\n POWERED BY APPSTLE\\n </a>\\n </div>\\n {{/showAppstleLink}}\\n </div>\\n{{/showTooltip}}\\n <style>\\n .widgetSellingPlanWrapper {\\n display: grid;\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n gap: 8px;\\n grid-auto-rows: 1fr;\\n margin-bottom: 6px;\\n margin-top: 10px;\\n }\\n \\n .widgetSellingPlanWrapper input {\\n display: none;\\n }\\n \\n .widgetSellingPlanWrapper label {\\n border-radius: 4px;\\n border: 1px solid rgba(var(--color-foreground));\\n padding: 0.5rem;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n display: block;\\n height: 100%;\\n width: 100%;\\n text-align: center;\\n \\t color: rgba(var(--color-foreground));\\ncursor: pointer;\\n }\\n \\n .widgetSellingPlanWrapper input:checked+label {\\n background-color: rgba(var(--color-foreground));\\n \\t color: rgba(var(--color-background));\\n }\\n .appstle_lowercase {\\n text-transform: lowercase;\\n }\\n \\n \\n .appstle_input_wrapper {\\n position: relative;\\n }\\n \\n span.appstle_sellingPlan_discountText {\\n position: absolute;\\n background-color: rgba(var(--color-foreground));\\n color: rgba(var(--color-background));\\n border-radius: 3px;\\n padding: 1px 18px;\\n left: 50%;\\n display: block;\\n transform: translate(-50%, -50%);\\n white-space: nowrap;\\n }\\n span.appstle_sellingPlan_discountText:empty {\\n display: none !important;\\n }\\n </style>\\n </div>{% endraw %}\"}", 6137 6138 6139 "bundle": {}, 6140 6141 6142 "labels": `{\"appstle.subscription.wg.addToShipmentErrorTextV2\":\"Error\",\"appstle.subscription.wg.weeksFrequencyTextV2\":\"Weeks\",\"appstle.subscription.wg.weeklyLabelTextV2\":\"Weekly\",\"appstle.subscription.wg.displayAddToExistingSubscriptionButtonForNotLoggedInV2\":\"false\",\"appstle.subscription.wg.addToShipmentProcessingV2\":\"Processing...\",\"appstle.subscription.wg.deliveryEveryFrequencyTextV2\":\"Delivery Every\",\"appstle.subscription.wg.subscribeAndSaveInitalV2\":\"Subscribe & save\",\"appstle.subscription.wg.allowRefreshOnCartPageV2\":\"false\",\"appstle.subscription.wg.prepaidLabelTextV2\":\"Prepaid\",\"appstle.subscription.wg.daysFrequencyTextV2\":\"Days\",\"appstle.subscription.wg.monthlyLabelTextV2\":\"Monthly\",\"appstle.subscription.wg.subscribeAndSaveSuccessV2\":\"Subscribe success\",\"appstle.subscription.wg.addToShipmentSuccessTextV2\":\"Success\",\"appstle.subscription.wg.monthFrequencyTextV2\":\"Month\",\"appstle.subscription.wg.addToShipmentButtonTextV2\":\"Add to Shipment\",\"appstle.subscription.wg.displayAddToExistingSubscriptionButtonToSubscribersOnlyV2\":\"false\",\"appstle.subscription.wg.yearsFrequencyTextV2\":\"Years\",\"appstle.subscription.wg.addToShipmentTooltipTextV2\":\"Please avoid double delivery charges! Login to add this product to an upcoming delivery.\",\"appstle.subscription.wg.weekFrequencyTextV2\":\"Week\",\"appstle.subscription.wg.oneTimePurchaseTextV2\":\"One Time Purchase\",\"appstle.subscription.wg.loyaltyPerkDescriptionTextV2\":\"{{#isDiscountTypeFreeProduct}}<div style='display: flex;'><div style='height: 60px; width: 60px; flex-shrink: 0; margin-right: 10px;'><img style='width: 100%' src={{{featured_image}}}><\/img><\/div><div>After {{{billingCycleBlock}}} orders,<span style='color: #ffc000;font-weight: 700;';> get a FREE {{freeProductName}} <\/span><\/div><div>{{\/isDiscountTypeFreeProduct}}{{#isDiscountTypePercentage}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>
6142get <span style='color: #ffc000;font-weight: 700;';>{{{discount}}}% OFF your entire order<\/span><\/span>.{{\/isDiscountTypePercentage}}{{#isDiscountTypeShipping}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>get <span style='color: #ffc000;font-weight: 700;';>shipping at {{{formatDiscountedPrice}}}<\/span><\/span>.{{\/isDiscountTypeShipping}}{{#isDiscountTypeFixed}}After <span class='appstle-loyalty-billing-cycle'><span class='appstle-loyalty-billing-cycle-count'>{{{billingCycleBlock}}}<\/span> order<\/span>, <span class='appstle-loyalty-discount'>get <span style='color: #ffc000;font-weight: 700;';>{{{formatDiscountedPrice}}} OFF your entire order<\/span><\/span>.{{\/isDiscountTypeFixed}}\",\"appstle.subscription.wg.unsubscribeFrequencyTextV2\":\"unsubscribe\",\"appstle.subscription.wg.oneTimeFrequencyTextV2\":\"One Time\",\"appstle.subscription.wg.dayFrequencyTextV2\":\"day\",\"appstle.subscription.wg.allowFulfilmentCountViaPropertiesV2\":\"false\",\"appstle.subscription.wg.monthsFrequencyTextV2\":\"Months\",\"appstle.subscription.wg.prepaidSaveBadgeTextV2\":\"SAVE {{selectedDiscountPercentage}}\",\"appstle.subscription.wg.showPrepidPerDeliveryProductPriceV2\":\"false\",\"appstle.subscription.wg.manageSubscriptionButtonTextV2\":\"Manage Subscription\",\"appstle.subscription.wg.offFrequencyTextV2\":\"Off\",\"appstle.subscription.wg.yearFrequencyTextV2\":\"Year\",\"appstle.subscription.wg.prepayLabelTextV2\":\"Prepay\",\"appstle.subscription.wg.frequencyCombinedWidgetTextV2\":\"Frequency\",\"appstle.subscription.wg.showNewLoyaltyUI\":\"false\",\"appstle.subscription.wg.sellingPlanTitleTextNonPrepaid\":\"{{sellingPlanName}}\",\"appstle.subscription.wg.selectDeliverOptionV2\":\"select deliver option\",\"appstle.subscription.wg.yearlyLabelTextV2\":\"Yearly\"}`, 6143 6144 "css": { 6145 "appstle_subscription_widget": { 6146 "margin-top": "" , 6147 "margin-bottom": "", 6148 }, 6149 6150 "appstle_subscription_wrapper": { 6151 "border-width": "", 6152 "border-color": "", 6153 }, 6154 6155 "appstle_circle": { 6156 "border-color": "", 6157 }, 6158 6159 "appstle_dot": { 6160 "background-color": "", 6161 }, 6162 6163 "appstle_select": { 6164 "padding-top": "", 6165 "padding-bottom": "", 6166 "padding-left": "", 6167 "padding-right": "", 6168 "border-width": "", 6169 "border-style": "", 6170 "border-color": "", 6171 "border-radius": "", 6172 }, 6173 6174 "tooltip_subscription_svg": { 6175 "fill": "", 6176 }, 6177 6178 "appstle_tooltip": { 6179 "color": "", 6180 "background-color": "", 6181 }, 6182 6183 "appstle_tooltip_border_top_color": { 6184 "border-top-color": "", 6185 }, 6186 6187 "appstle_subscription_final_price": { 6188 "color": "", 6189 }, 6190 "appstle_widget_text_color": { 6191 "color": "", 6192 }, 6193 "appstle_selected_background": { 6194 "background": "transparent", 6195 }, 6196 "elementCSS": "[]", 6197 "customCSS": "", 6198 "customerPortalCss": "", 6199 "externalStyleTag": "", 6200 "themeCss": "", 6201 } 6202 }; 6203 6204 6205 window.AppstleSubscription = window.AppstleSubscription || JSON.parse(JSON.stringify(RS)); 6206 6207 sessionStorage['appstleSubscriptionConfig'] = JSON.stringify(RS.Config); 6208 6209 6210 try { 6211 6212 window.appstle_build_a_box_labels = {"perDeliveryLabelTextV2":"\\/delivery","variantNotAvailable":"Not Available","saveDiscountText":"{{discount}}","bundleSummaryTextV2":"Your bundle is empty. Please add products to your bundles to see bundle summary here.","freeProductLabelTextV2":"Free","bundleDescriptionTextV2":"Our bundle of all bundles, The Ultimate Superfood Bundle delivers exactly what it promises - a complete superfood solution. With 7 superfood blends each created to empower every aspect of your health and wellbeing - from immunity and gut health to energy & better focus.","productDetails":"Product Details","failedToAddMsgText":"Your cart can't have more than {{maxProduct}}
6212 products","cart":"Cart","reviewBundleTextV2":"Review Bundle","addButtonText":"Add","minimumQuantityToCheckoutV2":"Minimum {{quantity}} quantity to checkout","buildBoxErrormsgV2":"Build a Box token is Invalid, Please reach out to support.","continueShopping":"Continue Shopping","failedToAddTitleText":"Failed to add","spendAmountGetDiscount":"Spend {{amount}} get {{percent}}% discount","maxiumQuantityToCheckoutV2":"Maxium {{quantity}} quantity to checkout","contentsOnModalTextV2":"Contents","nextStepButtonTextV2":"Next Step","choosePlanLifeStyleTextV2":"Choose a plan to match your lifestyle","selectMinimumProductButtonText":"Please select {{minProduct}} minimum product","subtotal":"Subtotal","buyQuantityGetDiscount":"Buy {{quantity}} get {{percent}}% discount","loyaltyTablePercentageTextV2":"After <span class='appstle-loyalty-billing-cycle'><span class=''>{{billingCycle}}<\\/span> order<\\/span>, <span class='appstle-loyalty-discount'>get <span class='appstle-loyalty-discount-amount'>{{discount}}% off<\\/span><\\/span>.","loyaltyTablePriceTextV2":"After <span class='appstle-loyalty-billing-cycle'><span class=''>{{billingCycle}}<\\/span> order<\\/span>, <span class='appstle-loyalty-discount'>get at <span class='appstle-loyalty-discount-amount'>{{price}}<\\/span><\\/span>.","myDeliveryText":"My {{selectedSellingPlanDisplayName}} delivery","removeItem":"Remove","productsToProceedText":"Please select products to proceed","previousStepButtonTextV2":"Previous step","loadMoreTextV2":"Load more","selectedFrequencyLabelText":"Selected Frequency","addToCartButtonTextV2":"Add To Cart ","basePriceFormatFieldV2":"{{unitPrice}}\\/{{quantityUnit}}","title":"Build a Box","productPriceFormatField":"{{price}}","reviewOrdeDescriptionTextV2":"Check your items and select your required frequency plan","quantityLabelV2":"Quantity","subscriptionNotAvailableButtonV2":"Subscription not available","shoppingCart":"Shopping Cart","checkoutMessage":"Shipping and taxes calculated at checkout.","discountPopupCheckoutMessageV2":"Discount","selectedButtonTextV2":"Selected","congratsMessageText":null,"okBtnText":"Ok","tieredDiscount":"Tiered Discount","choosePlanLifeStyleDescriptionTextV2":"Cutoff each week to amend your meals is midnight on Thursday's. (Delivery Schedule is as follows: Gold Coast - Mondays | Brisbane & Sunshine Coast - Wednesdays)","orderNoteLabelTextV2":"Order Note","minimumToCheckoutV2":"Minimum {{quantity}} to checkout","loyaltyTableFixedTextV2":"After <span class='appstle-loyalty-billing-cycle'><span class=''>{{billingCycle}}<\\/span> order<\\/span>, <span class='appstle-loyalty-discount'>get <span class='appstle-loyalty-discount-amount'>{{price}} off<\\/span><\\/span>.","editQuantity":"Edit Quantity","itemsText":null,"chooseProductsTextV2":"Choose Products","loyaltyTableFreeProductTextV2":"After <span class='appstle-loyalty-billing-cycle'><span class=''>{{billingCycle}}<\\/span> order<\\/span>, <span class='appstle-loyalty-discount'>get <span class='appstle-loyalty-discount-amount'>FREE PRODUCT ({{productName}})<\\/span><\\/span>.","loyaltyTableShippingTextV2":"After <span class='appstle-loyalty-billing-cycle'><span class=''>{{billingCycle}}<\\/span> order<\\/span>, <span class='appstle-loyalty-discount'>get <span class='appstle-loyalty-discount-amount'>shipping at {{price}}<\\/span><\\/span>.","spentText":null,"quantityLabel":null,"addButtonV2":"Add","loyaltyTableFreeTrailTextV2":"Get <span class='appstle-loyalty-free-trial-discount'>{{discount}} <span class='appstle-loyalty-free-trial-discount-count' style='text-transform: lowercase;'>{{discountType}} <\\/span><\\/span> <span class='appstle-loyalty-free-trial-text'>free trial.<\\/span>","bundleCheckoutTextV2":"Checkout","reviewOrderTextV2":"Review Order","goBackButtonText":"Go Back","selectPlanTextV2":"Select Plan","viewProduct":"View Product","oneTimePurchaseTextV2":"One Time Purchase","bundleOnModalTextV2":"Bundle","proceedToCheckoutButtonText":"Proceed to checkout","pleaseWaitLabelTextV2":"Please wait...","typeToSearchPlaceholderTextV2":"Type to search","selectedProgressLabelTextV2":"Selected","outOfStockTextV2":"Out of stock"}; 6213 6214 } catch (e) { 6215 console.error("Error parsing build a box labels:", e); 6216 } 6217 6218 6219 var _RSConfig = _RSConfig || {}; 6220 6221 _RSConfig.shop = 'good-sleep-co-gc.myshopify.com'; 6222 6223 6224 6225 6226 6227 6228 _RSConfig.shopMoneyFormat = '${{amount}}'; 6229 _RSConfig.shopMoneyFormatWithCurrencyFormat = '${{amount}} AUD'; 6230 6231 6232 6233 6234 } 6235 6236 6237 6238 _RSConfig.assetRev = "f692e2ab9771bd0c6c55e797118551a1"; 6239 6240 6241</script>
6241 6242 6243<style id="appstle-payment-button-override"> 6244 .shopify-payment-button {display: none;} 6245</style>
6246<script> 6247 let appstleCount = 0 6248 function isAppstleJSInitiated() { 6249 appstleCount++; 6250 if (window?.["RSConfig"] || appstleCount > 20) { 6251 let appstleStyleElement = document.querySelector('#appstle-payment-button-override'); 6252 if (appstleStyleElement) { 6253 appstleStyleElement.remove(); 6254 } 6255 } else { 6256 setTimeout(isAppstleJSInitiated, 500) 6257 } 6258 } 6259 isAppstleJSInitiated(); 6260</script>
6260 6261 6262<style> 6263 6264</style>
6265<script> 6266 function pollAppstleInit() { 6267 if (window?.appstleInit) { 6268 window?.appstleInit() 6269 } else { 6270 setTimeout(pollAppstleInit, 30); 6271 } 6272 } 6273</script>
6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291
6291<script src="https://subscription-admin.appstle.com/assets/js/appstle-subscription.min.js?shop=good-sleep-co-gc.myshopify.com&v=1785489929499" defer ></script>
6291 6292 6293 6294 6295 6296 6297 6298 6299 6300</div><div id="shopify-block-ANExPbHMzYjJyMXg2Z__17646240911419608881" class="shopify-block shopify-app-block ngr-embed-block">
6301<script src="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/countries-data.js"></script>
6301<!-- BEGIN app snippet: autoredirects -->
6302<script> 6303 function ngrSetCookie(name, value, days) { 6304 var expires = ""; 6305 if (days) { 6306 var date = new Date(); 6307 date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 6308 expires = "; expires=" + date.toUTCString(); 6309 } 6310 document.cookie = name + "=" + (encodeURIComponent(value) || "") + expires + "; path=/"; 6311 } 6312 function ngrGetCookie(name) { 6313 var nameEQ = name + "="; 6314 var cookies = document.cookie.split(';'); 6315 for (var i = 0; i < cookies.length; i++) { 6316 var cookie = cookies[i].trim(); 6317 if (cookie.indexOf(nameEQ) === 0) { 6318 return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length)); 6319 } 6320 } 6321 return null; 6322 } 6323 function ngrDeleteCookie(name) { 6324 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 6325 } 6326 function ngrAutoRun(){ 6327 const STORE_PLAN = "Pro plan"; 6328 const NGR_REDIRECTED = "ngr-redirected" 6329 const LOGGER_NAME = "[NGRP APP]:"; 6330 const NGR_SESSION_NAME = "ngr-session"; 6331 const NGR_AUTORD_NAME = "ngr-auto"; 6332 const ENABLE_DEV_MODE_PARAM = "xgeo-off"; 6333 const DISABLE_DEV_MODE_PARAM = "xgeo-reset"; 6334 const NGR_TEST_PARAM = "ngr-test"; 6335 const NGR_TEST_HASH = "#" + NGR_TEST_PARAM; 6336 const HOST = "https://xapps-geo-ca956fdeab0c.herokuapp.com"; 6337 const AUTO_ONCE_TYPE = "session"; 6338 const AUTO_ONCE = false; 6339 const ROOT_URL = "/"; 6340 const userAgents = { 6341 mobile: 'Mozilla/5.0 (Linux; Android 11; moto g power (2022)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36', 6342 desktop: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', 6343 }; 6344 let isBot = false; 6345 if(window.location.search.includes(ENABLE_DEV_MODE_PARAM)){ 6346 ngrSetCookie(ENABLE_DEV_MODE_PARAM, 1, 7); 6347 } 6348 if(window.location.search.includes(DISABLE_DEV_MODE_PARAM)){ 6349 ngrDeleteCookie(ENABLE_DEV_MODE_PARAM); 6350 } 6351 6352 const isPreviewMode = ngrGetCookie(ENABLE_DEV_MODE_PARAM); 6353 if(navigator && navigator.userAgent){ 6354 isBot = /bot|adsbot|googlebot|crawler|spider|robot|crawling|slurp/i.test(navigator.userAgent); 6355 if(navigator.userAgent === userAgents.mobile || navigator.userAgent === userAgents.desktop){ 6356 isBot = true; 6357 } 6358 } 6359 6360 if(!isPreviewMode && !window.location?.host?.includes(".shopifypreview.com") && !isBot && !window.Shopify.designMode && !(window.location.search.includes(NGR_TEST_PARAM) || window.location.hash === NGR_TEST_HASH)){ 6361 6362 try{ 6363 ngrInitialize() 6364 }catch(e){ 6365 console.error(`${LOGGER_NAME} GEO location issue. `, e) 6366 } 6367 async function ngrInitialize(){ 6368 const ngrCurrentGeo = await ngrGeoRequest(); 6369 const ngrAutoRedirects = [{"id":"gid:\/\/shopify\/Metafield\/26630627917963","location":["US"],"except_r":false,"block":false,"url":"https:\/\/provider.goodsleepco.health\/usa-landing-page\/","domain_redirection":false,"status":false,"order_r":1}]; 6370 if(!ngrAutoRedirects || !ngrAutoRedirects?.length) return; 6371 if(window.Shopify.designMode || window.location.search.includes(NGR_TEST_PARAM) || window.location.hash === NGR_TEST_HASH){ 6372 return; 6373 } 6374 const suitableRedirects = ngrAutoRedirects.filter(item => item.status).sort((a, b) => a.order_r - b.order_r); 6375 for (let index = 0; index < suitableRedirects.length; index++) { 6376 const item = suitableRedirects[index]; 6377 let itemStringUrl = item.url ? item.url.replace(/\/$/, '') : ''; 6378 let itemUrl = null; 6379 6380 if (!item.block && (!itemStringUrl || typeof itemStringUrl !== 'string')) continue; 6381 6382 if (!item.block) { 6383 try { 6384 itemUrl = new URL(item.url.replace(/\/$/, '')); 6385 } catch (e) { 6386 console.warn(`${LOGGER_NAME} Invalid URL encountered: "${item.url}". Error:`, e); 6387 continue; 6388 } 6389 } 6390 6391 let domainRedirectUrl = ''; 6392 const currentParams = new URLSearchParams(removePreviewThemeId(window.location.search)); 6393 if(itemUrl) { 6394 const existingParams = new URLSearchParams(itemUrl.search);
6395 for (const [key, value] of currentParams.entries()) { 6396 existingParams.set(key, value); 6397 } 6398 itemUrl.search = existingParams.toString(); 6399 const basePath = (itemUrl.pathname && itemUrl.pathname !== '/') 6400 ? itemUrl.pathname.replace(/\/$/, '') 6401 : ''; 6402 const currentPath = window.location.pathname.replace(/^\/+/, ''); 6403 let combinedPath = joinPathsAvoidDuplicate(basePath, currentPath); 6404 if (!combinedPath.startsWith('/')) { 6405 combinedPath = '/' + combinedPath; 6406 } 6407 domainRedirectUrl = itemUrl.origin + combinedPath + (itemUrl.search ? itemUrl.search : '') + window.location.hash; 6408 } 6409 const locationIncludes = item.location.includes(ngrCurrentGeo.country) || item.location.includes("C:" + ngrCurrentGeo.continent) 6410 const customCodeString = ` 6411function pattern(redirectUrl, currentUrl, geolocation, forceRedirect) { 6412 let newUrl = ; 6413 // your logic 6414 // force redirection logic: 6415 // if(gelocation.country === CA){ 6416 // return forceRedirect(https://your-url.com) 6417 // } 6418 return newUrl; 6419} 6420`; 6421 6422 if(item.block && (!item.except_r && locationIncludes || item.except_r && !locationIncludes)){ 6423 blockUser(); 6424 return 6425 } 6426 if(!item.block && item.domain_redirection && (!item.except_r && locationIncludes || item.except_r && !locationIncludes)){ 6427 redirectUser(domainRedirectUrl, itemStringUrl) 6428 return 6429 } 6430 if(!item.block && !item.domain_redirection && (!item.except_r && locationIncludes || item.except_r && !locationIncludes)){ 6431 redirectUser(itemStringUrl) 6432 return 6433 } 6434 } 6435 } 6436 function redirectUser(redirectUrl, orignalUrl){ 6437 if (window.location.hostname === 'thejunkdesign.com') { 6438 if (!window.ngrRedirectCountTheJunkDesign) { 6439 window.ngrRedirectCountTheJunkDesign = 0; 6440 } 6441 window.ngrRedirectCountTheJunkDesign++; 6442 if (window.ngrRedirectCountTheJunkDesign > 3) { 6443 return; 6444 } 6445 const currentUrl = window.location.href.split('?')[0]; 6446 const targetUrl = redirectUrl.split('?')[0]; 6447 if (currentUrl === targetUrl) { 6448 return; 6449 } 6450 try { 6451 const redirectUrlObj = new URL(redirectUrl); 6452 if (redirectUrlObj.hostname === window.location.hostname && 6453 redirectUrlObj.pathname === window.location.pathname) { 6454 return; 6455 } 6456 } catch (e) {} 6457 } 6458 if(checkRedirectOnce() || window.location.search.includes(NGR_REDIRECTED)){ 6459 return; 6460 } 6461 let generatedUrl; 6462 try { 6463 generatedUrl = orignalUrl && new URL(orignalUrl); 6464 } catch (e) { 6465 console.warn(`${LOGGER_NAME} Invalid original URL encountered: "${orignalUrl}". Error:`, e); 6466 generatedUrl = null; 6467 } 6468 if(!generatedUrl){ 6469 const redirectUrlObj = new URL(redirectUrl, window.location.origin); 6470 if (window.location.search) { 6471 const currentSearchParams = new URLSearchParams(window.location.search); 6472 currentSearchParams.forEach((value, key) => { 6473 if (!redirectUrlObj.searchParams.has(key)) { 6474 redirectUrlObj.searchParams.append(key, value); 6475 } 6476 }); 6477 } 6478 redirectUrl = redirectUrlObj.toString(); 6479 } 6480 const equalHost = window.location.host === generatedUrl?.host; 6481 const checkCondition = equalHost ? !window.location.href.includes(orignalUrl) : true; 6482 const locationHref = window.location.href.replace(/\/$/, ''); 6483 6484 if(locationHref !== redirectUrl && checkCondition){ 6485 track();setRedirectOnce(); 6486 6487 if (window.location.hostname === 'thejunkdesign.com') { 6488 const referrer = document.referrer; 6489 const hasInstagramReferrer = referrer.includes('instagram.com'); 6490 const hasFacebookReferrer = referrer.includes('facebook.com') || referrer.includes('fb.com'); 6491 const hasFbclid = window.location.search.includes('fbclid'); 6492 const hasIgshid = window.location.search.includes('igshid'); 6493 if (hasInstagramReferrer || hasFacebookReferrer || hasFbclid || hasIgshid) { 6494 setTimeout(() => { 6495 window.location.replace(footprint(redirectUrl)); 6496 }, 1000); 6497 return; 6498 } 6499 } 6500 6501 return window.location.replace(footprint(redirectUrl)); 6502 } 6503 }
6504 function footprint(urlString){ 6505 const url = new URL(urlString); 6506 url.searchParams.append(NGR_REDIRECTED, 1); 6507 return url.toString(); 6508 } 6509 function blockUser(){ 6510 track(); 6511 window.location.replace("about:blank"); 6512 } 6513 function track() { 6514 try{ 6515 const dataEndpoint = `${HOST}/api/analytics/auto?shop=${window?.Shopify?.shop}`; 6516 fetch(dataEndpoint) 6517 return; 6518 }catch(e){} 6519 } 6520 function removePreviewThemeId(search) { 6521 return search.replace( 6522 /([?&])preview_theme_id=\d+(&?)/, 6523 (match, p1, p2) => { 6524 return p1 === "?" && p2 ? "?" : p1; 6525 } 6526 ); 6527 } 6528 function setRedirectOnce(){ 6529 if(!AUTO_ONCE) return; 6530 if(AUTO_ONCE_TYPE === "session"){ 6531 sessionStorage.setItem(NGR_AUTORD_NAME, 1); 6532 return 6533 } 6534 if(AUTO_ONCE_TYPE === "cookies"){ 6535 ngrSetCookie(NGR_AUTORD_NAME, 1, 7) 6536 return 6537 } 6538 } 6539 function checkRedirectOnce(){ 6540 if(AUTO_ONCE){ 6541 if(AUTO_ONCE_TYPE === "session"){ 6542 return sessionStorage?.getItem(NGR_AUTORD_NAME) ? true : false 6543 } 6544 if(AUTO_ONCE_TYPE === "cookies"){ 6545 return ngrGetCookie(NGR_AUTORD_NAME) ? true : false 6546 } 6547 return false 6548 } 6549 return false 6550 } 6551 async function ngrGeoRequest(){ 6552 const savedUserData = ngrGetCookie(NGR_SESSION_NAME); 6553 if (savedUserData && isJsonParsable(savedUserData) && !window.location.search.includes(NGR_TEST_PARAM) && window.location.hash !== NGR_TEST_HASH) { 6554 return JSON.parse(savedUserData) 6555 } 6556 try{ 6557 const countries = window.ngr_countries_window 6558 const userGeo = await fetch("/browsing_context_suggestions.json").then( 6559 (resp) => resp.json() 6560 ); 6561 if (!countries || !userGeo) 6562 return console.error( 6563 `${LOGGER_NAME} User GEO location or countries list not detected. Contact app support please.` 6564 ); 6565 const userCountry = userGeo?.detected_values?.country?.handle; 6566 const userLocation = { 6567 country_name: userGeo?.detected_values?.country?.name || userGeo?.detected_values?.country_name || countries[userCountry]?.name, 6568 country: userCountry, 6569 continent: countries[userCountry]?.continent, 6570 }; 6571 ngrSetCookie(NGR_SESSION_NAME, JSON.stringify(userLocation), 7); 6572 window[NGR_SESSION_NAME] = userLocation 6573 return userLocation; 6574 }catch(e){ 6575 console.error(`${LOGGER_NAME} GEO location issue. `, e) 6576 } 6577 } 6578 function isJsonParsable(input){try{JSON.parse(input);return true}catch(e){return false}} 6579 function joinPathsAvoidDuplicate(basePath, currentPath) { 6580 basePath = basePath.replace(/\/$/, ''); 6581 currentPath = currentPath.replace(/^\/+/, ''); 6582 if (currentPath.toLowerCase().startsWith(basePath.replace(/^\/+/, '').toLowerCase() + '/')) { 6583 return '/' + currentPath; 6584 } 6585 if (currentPath.toLowerCase() === basePath.replace(/^\/+/, '').toLowerCase()) { 6586 return '/' + currentPath; 6587 } 6588 if (basePath && currentPath) { 6589 return basePath + '/' + currentPath; 6590 } else if (basePath) { 6591 return basePath; 6592 } else { 6593 return '/' + currentPath; 6594 } 6595 } 6596 6597 } 6598 } 6599 ngrAutoRun() 6600</script>
6600 6601 6602<!-- END app snippet --><!-- BEGIN app snippet: widget --><ngr-app 6603 style="display: none" 6604 data-markets="false" 6605 data-menu-icon="" 6606 data-lng="en" 6607 data-shopify-template="index" 6608 data-shopify-template-dir="" 6609 data-flag-src="//cdn.shopify.com/static/images/flags/au.svg?width=100" 6610 data-custom-opener-icon-src="" 6611 data-widget-icon="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/earth-americas-solid.svg" 6612 data-widget-sticky-icon="https://cdn.shopify.com/extensions/019fa68b-5014-74a6-b414-02bbdcfce20d/xapps-geo-345/assets/sticky-logo.png" 6613 data-test-mode="false" 6614 ><template id="NGR-Redirects-Template"> 6615 <div class="ngr-modal" data-ngr-modal> 6616 <div role="dialog" aria-label="" aria-modal="true" class="ngr-modal__content" tabindex="-1" data-ngr-modal-content> 6617 <button class="ngr-modal__close" type="button" aria-label="Close" data-ngr-close>â</button> 6618 <div data-ngr-redirects></div> 6619 </div> 6620 </div> 6621 </template> 6622 </ngr-app><!-- END app snippet --> 6623 6624</div>
6624<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
6624 6625</body> 6626</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.