{
  "version": 3,
  "sources": ["/cdn/shop/t/149/assets/cart_drawer.js?view=metafields"],
  "sourcesContent": ["(function () {\n  'use strict';\n\n  // \u2500\u2500 SHARED CART READ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // /cart.js is read 17 times across this file, and several of those callers run in\n  // the same moment: on one add-to-cart, four reads went out and at least one pair\n  // overlapped. This collapses only the OVERLAPPING ones into a single request.\n  //\n  // Deliberately NOT a cache. The in-flight promise is released on the next tick, so\n  // anything that asks after the current read settles gets a genuinely fresh fetch.\n  // That matters: nearly every read here follows a cart WRITE, and serving one of\n  // those from a cache would show the customer the cart as it was before their own\n  // change. An extra request is cheap; a wrong cart is not.\n  //\n  // Each caller gets a CLONE. A Response body can only be read once, so handing the\n  // same object to two callers would leave the second with an empty body. The stored\n  // response is never consumed itself -- only clones are handed out -- so clone() is\n  // always legal.\n  var cdCartInFlight = null;\n  function cdFetchCart() {\n    if (!cdCartInFlight) {\n      cdCartInFlight = fetch('/cart.js').then(function (r) {\n        setTimeout(function () { cdCartInFlight = null; }, 0);\n        return r;\n      }, function (e) {\n        cdCartInFlight = null;\n        throw e;\n      });\n    }\n    return cdCartInFlight.then(function (r) { return r.clone(); });\n  }\n\n  // Force-hide the Debutify page transition overlay (runs on ALL pages inc. /cart).\n  // 25 Sep 2026: the CornerCart (\"cowi\") half of this was removed. CornerCart is uninstalled\n  // and loads nothing, so we were running a permanent MutationObserver over the whole document\n  // hiding an app that is not there.\n  (function suppressOverlays() {\n    function forceHide(el) {\n      el.style.setProperty('display', 'none', 'important');\n      el.style.setProperty('pointer-events', 'none', 'important');\n      el.style.setProperty('visibility', 'hidden', 'important');\n      el.style.setProperty('opacity', '0', 'important');\n    }\n    function shouldHide(el) {\n      if (el.nodeType !== 1) return false;\n      var cls = (typeof el.className === 'string' ? el.className : '') || '';\n      return cls.indexOf('dbtfy-page-transition') !== -1;\n    }\n    function scanAndHide(root) {\n      if (shouldHide(root)) { forceHide(root); return; }\n      if (root.querySelectorAll) {\n        root.querySelectorAll('.dbtfy-page-transition').forEach(forceHide);\n      }\n    }\n    document.querySelectorAll('.dbtfy-page-transition').forEach(forceHide);\n    new MutationObserver(function (mutations) {\n      mutations.forEach(function (m) {\n        if (m.type === 'childList') {\n          m.addedNodes.forEach(scanAndHide);\n        } else if (m.type === 'attributes' && shouldHide(m.target)) {\n          forceHide(m.target);\n        }\n      });\n    }).observe(document.documentElement, {\n      childList: true,\n      subtree: true,\n      attributes: true,\n      attributeFilter: ['style', 'class']\n    });\n  })();\n\n  // \u2500\u2500\u2500 DISCOUNT LINK ROUTING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // Codes arriving via URL (?discount=CODE on Klaviyo/SMS/ad links, or the\n  // discount_code cookie set by /discount/CODE redirects) normally sit invisible\n  // until checkout \u2014 bypassing the drawer's gift maths, progress bar and\n  // gap-closer entirely. Route them through the cart instead: applying the code\n  // via /cart/update.js makes final_line_price reflect it, so the gift engine\n  // re-evaluates on the spend the customer will actually pay, and the drawer\n  // shows the code badge the moment it opens.\n  function cdReadCookie(name) {\n    var m = document.cookie.match(new RegExp('(?:^|;\\\\s*)' + name + '=([^;]*)'));\n    return m ? decodeURIComponent(m[1]) : '';\n  }\n\n  // The code waiting to be routed this page load, or '' when there is none.\n  // A code already routed this session never re-routes \u2014 re-applying a code\n  // the customer deliberately removed would fight them.\n  function cdPendingUrlDiscount() {\n    var code = '';\n    try { code = new URLSearchParams(window.location.search).get('discount') || ''; } catch (e) {}\n    if (!code) code = cdReadCookie('discount_code');\n    code = String(code).trim();\n    if (!code) return '';\n    try {\n      if (sessionStorage.getItem('cdRoutedDiscount') === code.toUpperCase()) return '';\n    } catch (e) {}\n    return code;\n  }\n\n  // Drop the ?discount param so a plain reload doesn't count as a fresh click.\n  // The discount_code cookie (Shopify's own) is left alone \u2014 it keeps checkout\n  // covered even if cart routing couldn't land the code.\n  function cdStripDiscountParam() {\n    if (!(window.history && history.replaceState)) return;\n    try {\n      var u = new URL(window.location.href);\n      if (u.searchParams.has('discount')) {\n        u.searchParams.delete('discount');\n        history.replaceState(null, '', u.toString());\n      }\n    } catch (e) {}\n  }\n\n  // Apply a pending URL/cookie code to the cart. Resolves with the fresh cart\n  // when a code was routed, null otherwise. Invalid codes fail silently \u2014 this\n  // runs on page load, not from user input, so there is nobody mid-action to\n  // show an error to.\n  function routeUrlDiscount() {\n    if (window.b2bCompanyName) return Promise.resolve(null);\n    var code = cdPendingUrlDiscount();\n    if (!code) return Promise.resolve(null);\n    cdStripDiscountParam();\n    return fetch('/cart/update.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ discount: code })\n    })\n      .then(function () {\n        // update.js responds before discount totals settle \u2014 refetch truth\n        return cdFetchCart().then(function (r) { return r.json(); });\n      })\n      .then(function (cart) {\n        // Mark routed once the code has landed (or was rejected against a real\n        // cart). Shopify won't hold a code on an EMPTY cart \u2014 stash it instead,\n        // and cdApplyDeferredDiscount re-applies it the moment the first item\n        // arrives (customers from ad/email links usually land cart-empty).\n        var landed = (cart.cart_level_discount_applications || []).length > 0;\n        if (landed || cart.item_count > 0) {\n          try { sessionStorage.setItem('cdRoutedDiscount', code.toUpperCase()); } catch (e) {}\n        } else {\n          try { sessionStorage.setItem('cdDeferredDiscount', code); } catch (e) {}\n        }\n        return cart;\n      })\n      .catch(function () { return null; });\n  }\n\n  // Apply a deferred code (one that arrived while the cart was still empty)\n  // now that the cart can hold it. Called on every fresh (non-optimistic)\n  // render and on /cart load. Resolves with the discounted cart, or the\n  // original cart when there's nothing to do. The deferred key is cleared\n  // BEFORE the write \u2014 one attempt only, never a retry loop.\n  function cdApplyDeferredDiscount(cart) {\n    var code = '';\n    try { code = sessionStorage.getItem('cdDeferredDiscount') || ''; } catch (e) {}\n    if (!code || !cart || cart.item_count === 0) return Promise.resolve(cart);\n    try { sessionStorage.removeItem('cdDeferredDiscount'); } catch (e) {}\n    if ((cart.cart_level_discount_applications || []).length > 0) return Promise.resolve(cart);\n    return fetch('/cart/update.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ discount: code })\n    })\n      .then(function () { return cdFetchCart(); })\n      .then(function (r) { return r.json(); })\n      .then(function (fresh) {\n        try { sessionStorage.setItem('cdRoutedDiscount', code.toUpperCase()); } catch (e) {}\n        return fresh;\n      })\n      .catch(function () { return cart; });\n  }\n\n  // On /cart: SSR already renders the correct cart content.\n  // Debutify hides #main while waiting for buildCartPage() AJAX \u2014 that fetch never fires,\n  // so we must force-reveal #main. MutationObserver re-reveals if Debutify re-hides.\n  // /cart runs the block below and then stops at \"/cart STOPS HERE\" further down: it shares the gift rules\n  // declared in between (giftTierPlan, pairGiftRemovals) and never runs the drawer itself.\n  var CD_CART_PAGE = window.location.pathname === '/cart';\n  if (CD_CART_PAGE) {\n    injectStyles();\n\n    function revealCartMain() {\n      var main = document.getElementById('main');\n      if (main && main.style.display === 'none') main.style.removeProperty('display');\n    }\n\n    // Remove orphaned engraving SKUs \u2014 items with '_Customised Product' property whose\n    // linked main item (matched via '_cust_id') is no longer in the cart.\n    function cleanupOrphanEngravings() {\n      return cdFetchCart()\n        .then(function (r) { return r.json(); })\n        .then(function (cart) {\n          var items = cart.items;\n          // Collect _cust_id values present on visible (non-engraving) items\n          var mainCustIds = {};\n          items.forEach(function (item) {\n            var props = item.properties || {};\n            var isEng = Object.prototype.hasOwnProperty.call(props, '_Customised Product');\n            if (!isEng && props['_cust_id']) {\n              mainCustIds[props['_cust_id']] = true;\n            }\n          });\n          // Find engraving items whose main item is gone\n          var updates = {};\n          var hasOrphans = false;\n          items.forEach(function (item) {\n            var props = item.properties || {};\n            var isEng = Object.prototype.hasOwnProperty.call(props, '_Customised Product');\n            if (isEng) {\n              var cid = props['_cust_id'] || '';\n              // Only remove if it has a _cust_id that doesn't match any main item.\n              // Items without _cust_id use the old DTC model \u2014 leave them alone.\n              if (cid && !mainCustIds[cid]) {\n                updates[item.key] = 0;\n                hasOrphans = true;\n              }\n            }\n          });\n          if (!hasOrphans) return;\n          return fetch('/cart/update.js', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ updates: updates })\n          }).then(function () { window.location.reload(); });\n        });\n    }\n\n    // Remove gift lines the checkout would charge (4 Oct 2026: no longer a mirror, the drawer's OWN rules).\n    // Only the shoppers who stay on this page reach it: B2B company accounts (and no-JS); everyone else's /cart\n    // bounces into the drawer (snippets/cart-page-to-drawer.liquid). Tier gifts: giftTierPlan, the drawer's sweep\n    // (a line must match an active tier on target AND product, and carry the current arm's `_ob`), below-threshold\n    // and qty-1 clamp. Pair gifts: pairGiftRemovals, the drawer's pair rule for the current arm (this page never\n    // touched them before, so an old arm's grips went from here to checkout at $12 each). Removals only.\n    function cleanupGiftLines() {\n      cdFetchCart()\n        .then(function (r) { return r.json(); })\n        .then(function (cart) {\n          var updates = cdGiftRemovals(cart), dirty = Object.keys(updates).length > 0;\n          // a write that does not take (a key Shopify re-split) must not reload forever\n          var n = 0;\n          try { n = parseInt(sessionStorage.getItem('cdCartCleanReloads'), 10) || 0; } catch (e) {}\n          if (!dirty || n >= 3) { try { sessionStorage.removeItem('cdCartCleanReloads'); } catch (e) {} return; }\n          try { sessionStorage.setItem('cdCartCleanReloads', String(n + 1)); } catch (e) {}\n          fetch('/cart/update.js', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ updates: updates })\n          }).then(function () { window.location.reload(); });\n        });\n    }\n\n    // Capture-phase click handler fires before jQuery/Debutify handlers.\n    // When user removes a customised item, atomically remove its linked engraving SKU too.\n    document.addEventListener('click', function (e) {\n      var btn = e.target.closest\n        ? e.target.closest('.js-cart-product-remove.cstm_removetrue')\n        : null;\n      if (!btn) return;\n      e.preventDefault();\n      e.stopImmediatePropagation();\n      var row = btn.closest('[data-line]');\n      var lineIndex = row ? parseInt(row.getAttribute('data-line'), 10) : 0;\n      if (!lineIndex) {\n        var m = (btn.getAttribute('href') || '').match(/line=(\\d+)/);\n        if (m) lineIndex = parseInt(m[1], 10);\n      }\n      if (!lineIndex) return;\n      cdFetchCart()\n        .then(function (r) { return r.json(); })\n        .then(function (cart) {\n          var target = cart.items[lineIndex - 1];\n          if (!target) return;\n          var props = target.properties || {};\n          var custId = props['_cust_id'] || '';\n          var updates = {};\n          updates[target.key] = 0;\n          if (custId) {\n            cart.items.forEach(function (item) {\n              var ip = item.properties || {};\n              if (ip['_Customised Product'] !== undefined && ip['_cust_id'] === custId) {\n                updates[item.key] = 0;\n              }\n            });\n          }\n          return fetch('/cart/update.js', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ updates: updates })\n          }).then(function () { window.location.reload(); });\n        });\n    }, true); // true = capture phase \u2014 fires before any jQuery bubbling handlers\n\n    document.addEventListener('DOMContentLoaded', function () {\n      revealCartMain();\n      var obs = new MutationObserver(revealCartMain);\n      var main = document.getElementById('main');\n      if (main) obs.observe(main, { attributes: true, attributeFilter: ['style'] });\n      setTimeout(function () { obs.disconnect(); }, 3000);\n      // Serial, never parallel \u2014 Shopify carts do not tolerate racing writes.\n      // Route any URL/cookie discount first (plus any code deferred from an\n      // empty-cart landing) so cleanupGiftLines validates gifts against the\n      // discounted totals the customer will actually pay.\n      routeUrlDiscount()\n        .then(function (c) {\n          if (c) return cdApplyDeferredDiscount(c);\n          return cdFetchCart()\n            .then(function (r) { return r.json(); })\n            .then(cdApplyDeferredDiscount);\n        })\n        .then(function () { return cleanupOrphanEngravings(); })\n        .then(cleanupGiftLines)\n        .catch(function () { cleanupGiftLines(); });\n    });\n  }\n\n  var DRAWER_ID = 'cd-cart-drawer';\n\n  function injectStyles() {\n    if (document.getElementById('cd-cart-styles')) return;\n    var s = document.createElement('style');\n    s.id = 'cd-cart-styles';\n    s.textContent = [\n      /* Force html overflow-y to auto. Debutify injects CSS rules that set html{overflow:hidden}\n         for mobile scroll-locking. !important overrides any such rule regardless of source. */\n      'html{overflow-y:auto!important}',\n      /* Drawer shell */\n      '#cd-cart-drawer{display:none;position:fixed;inset:0;z-index:99999}',\n      '#cd-cart-drawer.open{display:block}',\n      '#cd-cart-overlay{position:absolute;inset:0;background:rgba(0,0,0,.45);z-index:1}',\n      /* Panel */\n      '#cd-cart-panel{position:absolute;top:0;right:0;width:504px;max-width:100vw;height:100%;background:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s cubic-bezier(0.4,0,.2,1);z-index:2;box-shadow:-4px 0 24px rgba(0,0,0,.12);}',\n      '#cd-cart-drawer.open #cd-cart-panel{transform:translateX(0)}',\n      /* Header */\n      '#cd-cart-header{display:flex;justify-content:space-between;align-items:center;padding:14px 20px;flex-shrink:0}',\n      '#cd-cart-title{font-size:20px;font-weight:700;letter-spacing:.02em;color:var(--c-ui);display:inline-flex;align-items:center}',\n      '#cd-cart-count-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:26px;background:var(--c-ui);color:#fff;border-radius:13px;font-size:14px;font-weight:700;padding:0 8px;margin-left:10px;letter-spacing:0}',\n      '#cd-cart-close{background:none;border:none;cursor:pointer;color:var(--c-meta);font-size:22px;padding:4px;line-height:1;border-radius:6px;transition:color .15s,background .15s}',\n      '#cd-cart-close:hover{color:var(--c-ui);background:var(--c-surface)}',\n      /* Items scroll area */\n      /* The wrap scrolls, not the list, so the upsell strip inside it scrolls with\n         the items. The list previously owned height:100% + overflow-y:auto, which\n         made it a scroller in its own right and left no way for anything after it\n         to share that scroll. */\n      /* min-height so the cart can never be squeezed to a sliver by whatever sits\n         above and below it. 132px is about one full item row. Deliberately modest:\n         the footer holds the checkout button, and a large min-height here would push\n         it off-screen on a short window. Verified checkout stays reachable at 500px. */\n      '#cd-items-wrap{flex:1;position:relative;overflow-y:auto;-webkit-overflow-scrolling:touch;min-height:132px}',\n      '#cd-cart-items{padding:16px 20px 0;box-sizing:border-box}',\n      '#cd-cart-items::-webkit-scrollbar{width:4px}',\n      '#cd-cart-items::-webkit-scrollbar-track{background:var(--c-stage)}',\n      '#cd-cart-items::-webkit-scrollbar-thumb{background:#ddd;border-radius:2px}',\n      /* Items loading overlay */\n      '#cd-items-loading{display:none;position:absolute;inset:0;background:rgba(255,255,255,.65);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);align-items:center;justify-content:center;z-index:5}',\n      '#cd-items-loading.active{display:flex}',\n      '.cd-items-spinner{width:32px;height:32px;border:3px solid var(--c-divider);border-top-color:var(--c-ui);border-radius:50%;animation:cd-spin .65s linear infinite}',\n      /* Footer */\n      '#cd-cart-footer{padding:10px 20px 10px;border-top:none;box-shadow:0 -4px 12px rgba(0,0,0,.04);flex-shrink:0;background:var(--c-bg-section)}',\n      '#cd-cart-checkout{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:14px 16px;background:var(--c-navy);color:#fff;text-decoration:none;font-size:16px;font-weight:700;letter-spacing:.03em;border:none;border-radius:999px;cursor:pointer;box-sizing:border-box;transition:background .15s,box-shadow .15s}',\n      /* brand-2026 greys inside the drawer only (Kegan 28 Sep: \"update the colours used on the cart\"):\n         muted #6B7280, line #E4E9EC, sky tint #EAF7FC, the PDP tokens. Struck prices use muted #6B7280 (4.8:1), not the PDP's\n         #A3ACB2 strike grey (2.3:1): the colour check on 28 Sep failed it */\n      '#cd-cart-drawer{--c-mid:#6B7280;--c-sub:#6B7280;--c-meta:#6B7280;--c-muted:#6B7280;--c-ghost:#A3ACB2;--c-divider:#E4E9EC;--c-item-divider:#E4E9EC;--c-hover:#EAF7FC;--c-surface:#EAF7FC;color:#262626}',\n      /* Checkout follows the site button rule (Kegan 28 Sep): brand blue #00BBE3 with an ink label (9.2:1), ink with a\n         white label on hover and on tap (15.1:1). Blue at rest so phones, which have no hover, see it too */\n      '#cd-cart-checkout{background:#00BBE3;color:#262626;transition:background .15s ease,color .15s ease,transform .15s ease,box-shadow .15s ease}',\n      '#cd-cart-checkout *{color:inherit}',\n      '@media (hover:hover){#cd-cart-checkout:hover:not([disabled]){background:#262626;color:#FFFFFF;transform:translateY(-2px);box-shadow:0 10px 22px rgba(38,38,38,.28)}',\n      '.cd-upsell-add:hover{background:#00BBE3!important;color:#262626!important}}',\n      '#cd-cart-checkout:active:not([disabled]){background:#262626;color:#FFFFFF;transform:translateY(0) scale(0.98);box-shadow:0 4px 10px rgba(38,38,38,.24)}',\n      '.cd-moq-warning{margin:0 0 10px;padding:10px 14px;border-radius:8px;background:#fdecea;color:#c0392b;font-size:13px;font-weight:600;line-height:1.4;box-sizing:border-box}',\n      '.cd-moq-warning[hidden]{display:none}',\n      '#cd-cart-trust{display:flex;flex-direction:row;gap:6px;margin:12px 0 0}',\n      '.cd-trust-item{flex:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:10px 8px;font-size:10px;font-weight:600;color:#262626;letter-spacing:.05em;text-transform:uppercase;line-height:1.3}',\n      '.cd-trust-icon{width:32px;height:32px;flex-shrink:0;object-fit:contain}',\n      /* Item card */\n      '.cd-cart-item{display:flex;gap:12px;margin-bottom:0;padding:18px 0;border-bottom:1px solid var(--c-item-divider);position:relative;transition:background .15s ease}',\n      '.cd-cart-item:last-child{border-bottom:none}',\n      '.cd-cart-item.removing{opacity:0;transform:translateX(10px);pointer-events:none;transition:opacity .2s ease,transform .2s ease}',\n      '.cd-item-thumb{width:80px;height:80px;flex-shrink:0;border-radius:6px;overflow:hidden;background:var(--c-stage);display:flex;align-items:center;justify-content:center}',\n      '.cd-item-thumb img{width:100%;height:100%;object-fit:cover}',\n      '.cd-item-thumb-placeholder{color:#A3ACB2;font-size:22px}',\n      '.cd-item-info{flex:1;min-width:0;padding-right:28px}',\n      '.cd-item-title-row{position:relative;margin-bottom:2px}',\n      '.cd-item-title{font-size:16px;font-weight:500;color:var(--c-ink);line-height:1.35;padding-right:70px}',\n      '.cd-item-price{font-size:16px;font-weight:600;color:var(--c-ink);white-space:nowrap}',\n      '.cd-item-title-row > .cd-item-price{position:absolute;top:0;right:0;text-align:right}',\n      /* Price column when a campaign discount is active on this item */\n      '.cd-item-price-wrap{display:flex;flex-direction:column;align-items:center;gap:1px;position:absolute;top:0;right:0;text-align:center}',\n      '.cd-item-orig-price{font-size:13px;font-weight:400;color:#6B7280;text-decoration:line-through;line-height:1.3}',\n      /* Campaign name chip(s) below variant line */\n      '.cd-item-campaigns{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:4px}',\n      '.cd-campaign-name{display:inline-flex;align-items:center;gap:3px;font-size:11px;color:var(--c-teal);font-weight:500;background:var(--c-teal-bg);border-radius:20px;padding:2px 8px}',\n      '.cd-item-variant{font-size:14.5px;color:var(--c-sub);margin-bottom:4px}',\n      '.cd-item-personalisation{font-size:13px;color:var(--c-mid);margin-bottom:2px;cursor:pointer;display:flex;align-items:center;gap:4px;user-select:none}',\n      '.cd-personalisation-chevron{display:inline-block;width:5px;height:5px;border-right:1.5px solid #A3ACB2;border-bottom:1.5px solid #A3ACB2;transform:rotate(-45deg);transition:transform .2s ease;flex-shrink:0;margin-bottom:1px}',\n      '.cd-item-personalisation.cd-pers-open .cd-personalisation-chevron{transform:rotate(45deg)}',\n      /* Properties */\n      '.cd-item-props{margin-bottom:6px;overflow:hidden;max-height:0;transition:max-height .2s ease}',\n      '.cd-item-props.cd-props-open{max-height:200px}',\n      '.cd-item-prop{font-size:13px;color:var(--c-meta);line-height:1.4;display:flex;gap:4px}',\n      '.cd-prop-key{font-weight:400;color:var(--c-meta);flex-shrink:0}',\n      '.cd-prop-check{color:var(--c-success);font-weight:700}',\n      '.cd-prop-link{color:var(--c-teal);text-decoration:none;font-size:13px}',\n      '.cd-prop-link:hover{text-decoration:underline}',\n      /* Qty stepper \u2014 borderless fill */\n      '.cd-item-actions{display:flex;align-items:center;margin-top:10px}',\n      '.cd-qty-wrap{display:inline-flex;align-items:center;background:var(--c-surface);border-radius:6px;overflow:hidden}',\n      '.cd-qty{background:transparent;border:none;width:38px;height:38px;cursor:pointer;font-size:16px;color:#262626;display:inline-flex;align-items:center;justify-content:center;transition:background .1s ease;flex-shrink:0}',\n      '.cd-qty:hover:not(.cd-qty--floor){background:var(--c-divider)}',\n      '.cd-qty:active:not(.cd-qty--floor){transform:scale(0.88)}',\n      '.cd-qty.cd-qty--floor{opacity:0.3!important;cursor:not-allowed!important;pointer-events:none!important}',\n      '.cd-personalise{background:none;border:none;padding:0;margin-left:12px;font:inherit;font-size:12px;font-weight:600;color:var(--c-navy,#262626);text-decoration:underline;text-underline-offset:2px;cursor:pointer;white-space:nowrap}',\n      '.cd-personalise:hover{color:#00718C}',\n      '.cd-fixed-qty{font-size:13px;color:#262626;display:inline-flex;align-items:center;gap:6px;height:38px}',\n      '.cd-fixed-qty span{font-size:11px;color:#6B7280}',\n      '.cd-item-qty{min-width:32px;height:38px;text-align:center;font-size:14.5px;font-weight:500;color:var(--c-ink);line-height:38px}',\n      /* Remove \u2014 absolute top-right, fades in on hover */\n      '.cd-remove{position:absolute;top:18px;right:0;width:22px;height:22px;background:transparent;border:none;color:var(--c-ghost);cursor:pointer;font-size:13px;display:inline-flex;align-items:center;justify-content:center;padding:0;opacity:0;transition:opacity .15s ease,color .15s ease;line-height:1}',\n      '.cd-cart-item:hover .cd-remove{opacity:1}',\n      '.cd-remove:hover{color:var(--c-ink)}',\n      '@media(max-width:768px){.cd-remove{opacity:1}}',\n      /* Hears-style row (Kegan 28 Sep): price under the title, quantity pill + Remove in a right column,\n         so the stepper no longer takes its own row. Pill matches the PDP .bp-qty (1px line, no fill) */\n      '.cd-cart-item{display:grid;grid-template-columns:72px minmax(0,1fr) auto;column-gap:12px;padding:16px 0}',\n      '.cd-cart-item > .cd-item-thumb{grid-row:1 / span 2}',\n      '.cd-cart-item > .cd-item-side{grid-column:3;grid-row:1}',\n      '.cd-item-rest{grid-column:2 / span 2;grid-row:2;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;margin-top:0}',\n      '.cd-item-rest > .cd-item-campaigns{margin-bottom:0}',\n      '.cd-item-rest > .cd-item-props,.cd-item-rest > .cd-item-personalisation{flex-basis:100%}',\n      '.cd-item-rest > .cd-item-actions{margin-top:0}',\n      '.cd-item-rest:empty{display:none}',\n      '.cd-item-thumb{width:72px;height:72px}',\n      '.cd-item-info{padding-right:0}',\n      '.cd-item-title{font-size:14.5px;line-height:1.3;padding-right:0}',\n      '.cd-item-pricerow{display:flex;align-items:baseline;flex-wrap:wrap;gap:0 8px;margin:1px 0 3px}',\n      '.cd-item-pricerow .cd-item-price{font-size:15px;font-weight:600}',\n      '.cd-item-pricerow .cd-item-orig-price{font-size:13px;color:#6B7280}',\n      '.cd-item-variant{font-size:13.5px;margin-bottom:2px}',\n      '.cd-item-actions{margin-top:6px}',\n      '.cd-item-actions:empty{display:none}',\n      '.cd-item-side{display:flex;flex-direction:column;align-items:flex-end;gap:10px;flex-shrink:0}',\n      '.cd-item-side .cd-qty-wrap{background:#fff;border:1px solid #E4E9EC;border-radius:999px}',\n      '.cd-item-side .cd-qty{width:26px;height:30px;font-size:15px;color:#262626}',\n      '.cd-item-side .cd-qty:hover:not(.cd-qty--floor){background:#EAF7FC}',\n      '.cd-item-side .cd-item-qty{min-width:20px;height:30px;line-height:30px;font-size:14px}',\n      '.cd-item-side .cd-remove{position:static;width:auto;height:auto;opacity:1;font-size:12px;color:#6B7280;text-decoration:underline;text-underline-offset:2px}',\n      '.cd-item-side .cd-remove:hover{color:#262626}',\n      '.cd-personalise{margin-left:0}',\n      /* Mobile floating card */\n      '@media(max-width:768px){#cd-cart-panel{top:12px;right:12px;bottom:12px;width:calc(100vw - 24px);max-width:calc(100vw - 24px);height:auto;border-radius:10px 10px 16px 16px;box-shadow:0 8px 40px rgba(0,0,0,.22);overflow:hidden}}',\n      '@media(max-width:768px){#cd-cart-drawer.open #cd-cart-panel{transform:translateX(0)}}',\n      /* Empty + spinner */\n      '#cd-cart-empty{text-align:center;padding:48px 20px;color:#6B7280}',\n      '#cd-cart-empty-icon{font-size:40px;margin-bottom:12px;opacity:.4}',\n      '#cd-cart-empty p{font-size:13px;margin:0}',\n      '.cd-spinner{text-align:center;padding:48px 0;color:#6B7280;font-size:13px}',\n      /* Engraving item \u2014 show as subordinate */\n      '.cd-cart-item.cd-engraving-item .cd-item-title{font-weight:400;color:#6B7280;font-size:12px}',\n      '.cd-cart-item.cd-engraving-item .cd-item-thumb{opacity:.4}',\n      /* Free shipping bar */\n      '#cd-ship-bar{background:#fff;border-bottom:none;padding:0 20px 10px;flex-shrink:0}',\n      '#cd-ship-bar-msg{font-size:13px;font-weight:400;color:#262626;margin-bottom:8px;line-height:1.4;text-align:center}',\n      '#cd-ship-bar-track{position:relative;height:8px;background:var(--c-divider);border-radius:4px;overflow:hidden}',\n      /* Milestone notches on the multi-tier progress bar (gift tiers) */\n      '.cd-ship-milestone{position:absolute;top:0;bottom:0;width:3px;background:#fff;transform:translateX(-50%);z-index:2;border-radius:1px;pointer-events:none}',\n      /* Gift line colour swatches (reuse .cd-upsell-vpill look) */\n      '.cd-gift-variants{display:block;min-height:0}',\n      /* a free gift's colour pickers (22 Oct): the \"2 x Free in your Value Pack\" line on top, then one picker per unit, full width */\n      '.cd-item-actions--pick{flex-direction:column;align-items:flex-start;gap:8px}',\n      '.cd-item-actions--pick .cd-fixed-qty{height:auto}',\n      '.cd-item-actions--pick .cd-gift-variants,.cd-gift-unit{width:100%}',\n      '.cd-gift-unit{display:flex;align-items:flex-start;gap:6px}',\n      '.cd-gift-unit-n{flex:0 0 auto;min-width:40px;padding-top:6px;font-size:12px;font-weight:600;color:#262626}',\n      '.cd-gift-unit .cd-gift-variants{flex:1 1 auto;min-width:0}',\n      '.cd-gift-unit .cd-gift-change,.cd-gift-unit .cd-gift-curname{white-space:nowrap}',\n      /* a free 1L / 2L: Personalise on its own line under the colour (21 Oct 2026) */\n      '.cd-item-actions--gift{flex-wrap:wrap;row-gap:8px}',\n      '.cd-item-actions--gift .cd-personalise{flex-basis:100%;text-align:left}',\n      '.cd-gift-toggle{display:flex;align-items:center;gap:8px;background:none;border:none;padding:0;cursor:pointer;font:inherit;text-align:left}',\n      '.cd-gift-cur{flex-shrink:0;pointer-events:none;cursor:default}',\n      '.cd-gift-curname{font-size:12.5px;color:#6B7280}',\n      '.cd-gift-change{font-size:12px;font-weight:600;color:var(--c-teal);text-decoration:underline;text-underline-offset:2px}',\n      '.cd-gift-toggle[aria-expanded=\"true\"] .cd-gift-change{color:#6B7280}',\n      '.cd-gift-pills{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:8px}',\n      '.cd-gift-pills[hidden]{display:none}',\n      /* the final 2 days: the free bottle's 1L | 2L switch (D09, 24 Oct), the PDP's size pill pair */\n      '.cd-gift-size{display:inline-flex;border:1px solid #E4E9EC;border-radius:999px;padding:2px;margin:0 0 8px;flex-basis:100%;max-width:max-content}',\n      '.cd-gift-szb{min-height:32px;border:0;border-radius:999px;background:none;padding:6px 14px;font-family:inherit;font-size:12.5px;font-weight:700;line-height:1.2;color:#262626;cursor:pointer}',\n      '.cd-gift-szb[aria-checked=\"true\"]{background:#262626;color:#fff;cursor:default}',\n      '.cd-gift-szb[disabled]{opacity:.55;cursor:wait}',\n      /* solid kit blue #00BBE3, as the PDP progress track (Kegan 28 Sep: the old shimmer slid through #695959 brown and read as the colour changing) */\n      '#cd-ship-bar-fill{height:100%;background:var(--c-teal-light);border-radius:4px;width:0%;transition:width .4s ease}',\n      '#cd-ship-bar-fill.cd-unlocked{background:var(--c-teal-light)}',\n      '@keyframes cd-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}',\n      '@keyframes cd-confetti-fall{0%{transform:translateY(0) rotate(0deg);opacity:1}100%{transform:translateY(60px) rotate(720deg);opacity:0}}',\n      /* Pricing block */\n      '#cd-price-block{margin-bottom:12px}',\n      '#cd-total-row{display:flex;justify-content:space-between;align-items:baseline}',\n      '#cd-total-label{font-size:18px;font-weight:600;color:var(--c-ink)}',\n      '#cd-total-prices{display:flex;flex-direction:row;align-items:baseline;gap:10px}',\n      '#cd-original-price{display:none;font-size:14.5px;font-weight:400;color:var(--c-muted);text-decoration:line-through}',\n      '#cd-total-price{font-size:22px;font-weight:700;color:var(--c-ink)}',\n      /* states the saving as a number; the struck out total alone never says how much (19 Sep 2026) */\n      '#cd-total-save{display:none;margin-top:8px;background-color:#DC3220;background-image:linear-gradient(90deg,#D2402A 0%,#DC3220 45%,#B82A4E 100%);box-shadow:0 1px 2px rgba(184,42,78,.35),inset 0 1px 0 rgba(255,255,255,.18);text-shadow:0 1px 0 rgba(0,0,0,.12);color:#FFFFFF;font-family:\"Open Sans\",sans-serif;font-size:12px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;padding:5px 12px;border-radius:999px}',\n      '#cd-total-save.is-on{display:inline-block}',\n      '#cd-discount-subline{display:flex;justify-content:space-between;align-items:center;height:40px}',\n      /* Discount badge */\n      '.cd-discount-badge{display:inline-flex;align-items:center;gap:6px;background:var(--c-teal-bg);border-radius:20px;padding:4px 10px}',\n      '.cd-discount-code{font-size:13px;font-weight:600;color:var(--c-teal);text-transform:uppercase;letter-spacing:.04em}',\n      '#cd-discount-remove-btn{background:none;border:none;cursor:pointer;color:var(--c-teal);font-size:15px;line-height:1;padding:0;display:flex;align-items:center}',\n      '#cd-discount-remove-btn:hover{color:var(--c-teal-hover)}',\n      '#cd-discount-savings{font-size:14px;font-weight:500;color:var(--c-teal)}',\n      /* Discount input */\n      '#cd-discount-section{margin-bottom:14px;position:relative}',\n      '#cd-discount-loading{display:none;position:absolute;inset:0;background:rgba(255,255,255,.72);border-radius:10px;align-items:center;justify-content:center;z-index:1}',\n      '#cd-discount-loading.active{display:flex}',\n      '.cd-disc-spinner{width:18px;height:18px;border:2px solid #e0e0e0;border-top-color:var(--c-ui);border-radius:50%;animation:cd-spin .65s linear infinite}',\n      '@keyframes cd-spin{to{transform:rotate(360deg)}}',\n      /* Discount input \u2014 full-width underline style */\n      '#cd-discount-input-row{display:flex;align-items:center;width:100%;border-bottom:1px solid #e0e0e0;transition:border-color .2s}',\n      '#cd-discount-input-row:focus-within{border-bottom-color:var(--c-teal)}',\n      '#cd-discount-input{flex:1;height:38px;border:none;background:transparent;padding:0 14px 0 2px;font-size:14px;color:var(--c-ink);outline:none;box-sizing:border-box}',\n      '#cd-discount-input::placeholder{color:#6B7280}',\n      '#cd-discount-btn{background:transparent;border:none;color:var(--c-teal);font-size:13px;font-weight:600;cursor:pointer;padding:0 2px 0 12px;flex-shrink:0;transition:color .15s;letter-spacing:.02em}',\n      '#cd-discount-btn:hover{color:var(--c-teal-hover)}',\n      '#cd-discount-btn:disabled{color:#A3ACB2;cursor:not-allowed}',\n      '#cd-discount-msg{font-size:12px;margin-top:6px;padding:0 2px}',\n      '#cd-discount-msg.cd-msg-error{color:#c0392b}',\n      '#cd-discount-msg.cd-msg-loading{color:#6B7280}',\n      /* Upsell strip */\n      '#cd-upsell-strip{margin:12px 20px 16px;padding:12px 16px 14px;background:#fff;border:1.5px dashed var(--c-teal);border-radius:8px}',\n      '#cd-upsell-label{font-size:15px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--c-teal);margin-bottom:10px}',\n      '#cd-upsell-card-wrap{display:flex;align-items:stretch;gap:12px}',\n      '.cd-upsell-thumb{width:64px;height:64px;border-radius:6px;overflow:hidden;background:#f5f5f5;flex-shrink:0}',\n      '.cd-upsell-thumb img{width:100%;height:100%;object-fit:cover}',\n      '.cd-upsell-info{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between}',\n      '.cd-upsell-title{font-size:14px;font-weight:500;color:#262626;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}',\n      '.cd-upsell-right{display:flex;flex-direction:column;align-items:center;justify-content:space-between;flex-shrink:0}',\n      '.cd-upsell-price{font-size:15px;font-weight:600;color:#262626;text-align:center}',\n      /* what a second bottle hands over, row by row (Kegan 28 Sep: \"add another bottle and get $37 free\") */\n      '#cd-upsell-value{display:flex;flex-wrap:wrap;gap:2px 12px;margin:-4px 0 8px}',\n      '#cd-upsell-value[hidden]{display:none}',\n      /* compact add-on card, every mode (Kegan 28 Sep: \"not take as much real estate\", then \"make all the other\n         pop ups in the cart that size\"): 44px thumb, tighter padding, smaller label. The lone bottle's pair\n         also drops the repeated title and runs swatches + price + Add on one row */\n      '#cd-upsell-strip{margin:10px 20px 12px;padding:10px 12px}',\n      '#cd-upsell-label{font-size:12.5px;letter-spacing:.05em;margin-bottom:6px}',\n      '#cd-upsell-card-wrap{align-items:center;gap:10px}',\n      '.cd-upsell-thumb{width:44px;height:44px}',\n      '.cd-upsell-title{font-size:13px;line-height:1.3;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}',\n      '.cd-upsell-info{justify-content:center;gap:4px}',\n      '.cd-upsell-right{gap:4px}',\n      '.cd-upsell-price{font-size:14px;line-height:1.15}',\n      '.cd-upsell-vpill{width:26px;height:26px}',\n      /* more colours on show and the picked one named (Kegan 28 Sep: \"show more bottle colour options and then display which colour is picked\") */\n      /* the colour dots get their own full-width row under the product, ~8 on a phone instead of 3 */\n      '#cd-upsell-card-wrap{flex-wrap:wrap}',\n      '#cd-upsell-card-wrap > .cd-upsell-variants-row{flex-basis:100%;min-width:0;margin-top:8px}',\n      '.cd-upsell-variants{width:auto;flex:1;min-width:0}',\n      '.cd-upsell-vname{font-size:12px;line-height:1.2;color:#6B7280;margin-top:2px}',\n      '.cd-upsell-vname:empty{display:none}',\n      '.cd-up-pair #cd-upsell-label{margin-bottom:4px}',\n      '.cd-up-pair #cd-upsell-value{margin:0 0 8px}',\n      '.cd-up-pair .cd-upsell-title{display:none}',\n      '.cd-up-pair .cd-upsell-vname{font-size:13px;color:#262626;margin-top:0}',\n      '.cd-up-pair .cd-upsell-variants-row{min-width:0}',\n      '.cd-up-pair .cd-upsell-variants{width:auto;flex:1;min-width:0}',\n      '.cd-up-pair .cd-upsell-scroll-btn{display:none}',\n      '.cd-up-pair .cd-upsell-right{flex-direction:row;align-items:center;gap:8px}',\n      /* the sale's one-bottle card as the PDP's Add tile (Kegan 5 Nov: \"similar to this\", snippets/pdp-v3-style.liquid .bp-tslot--ghost) */\n      '#cd-upsell-strip.cd-up-pitch{border:0;padding:0;background:none}',\n      '.cd-up-pitch #cd-upsell-label,.cd-up-pitch #cd-upsell-value{display:none!important}',\n      '.cd-pitch{display:flex;align-items:center;gap:14px;width:100%;margin:0;padding:14px 16px;border:1.5px dashed #8A979E;border-radius:14px;background:#F6F8F9;color:#262626;font:inherit;text-align:left;cursor:pointer}',\n      '.cd-pitch:hover{border-color:#262626}',\n      '.cd-pitch.cd-upsell-add-err{border-color:#c0392b;background:#FDECEA!important}',\n      '.cd-pitch-pic{position:relative;flex:0 0 auto;width:52px;height:52px}',\n      '.cd-pitch-pic img{display:block;width:52px;height:52px;object-fit:cover;border-radius:8px}',\n      '.cd-pitch-plus{position:absolute;right:-7px;bottom:-5px;display:flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:50%;background:#00BBE3;color:#262626;font-size:19px;font-weight:600;line-height:1;padding-bottom:2px;box-shadow:0 0 0 2px #F6F8F9}',\n      '.cd-pitch:hover .cd-pitch-plus{background:#262626;color:#fff}',\n      '.cd-pitch-tx{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-width:0}',\n      '.cd-pitch-t{font-family:var(--f-sec,inherit);font-size:15px;font-weight:700;line-height:1.2}',\n      '.cd-pitch-now{font-size:13.5px;line-height:1.3;color:#262626}',\n      '.cd-pitch-row{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;margin-top:2px}',\n      '.cd-pitch-chip{border-radius:999px;white-space:nowrap;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#00718C;background:#EAF7FC;box-shadow:0 0 0 1px #CFE8F2;font-size:10.5px;line-height:1.3;padding:3px 9px}',\n      '.cd-pitch-vn{font-size:12px;color:#6B7280}',\n      '.cd-up-pitch .cd-upsell-variants-row{margin-top:10px}',\n      '.cd-fv-row{display:inline-flex;align-items:center;font-size:12.5px;color:var(--c-ink);white-space:nowrap}',\n      '.cd-fv-row s{color:var(--c-muted);margin:0 4px 0 5px}',\n      '.cd-fv-row b{color:var(--c-teal);font-weight:700;letter-spacing:.04em}',\n      '.cd-fv-tick{color:var(--c-teal);font-weight:700;margin-right:4px}',\n      '#cd-ship-row{display:flex;justify-content:space-between;font-size:13px;color:var(--c-mid);margin-bottom:4px}',\n      '#cd-ship-row[hidden]{display:none}',\n      '.cd-upsell-was{display:block;font-size:11px;font-weight:400;color:#6B7280;text-decoration:line-through}',\n      '.cd-upsell-add{background:var(--c-ui);border:none;border-radius:999px;color:#fff;font-size:12px;font-weight:600;letter-spacing:.03em;padding:6px 14px;cursor:pointer;transition:background .15s,transform .1s ease;white-space:nowrap}',\n      '.cd-upsell-add:hover{background:#000;transform:scale(1.03)}',\n      '.cd-upsell-add:active{transform:scale(0.96)}',\n      '.cd-upsell-add-err{background:#c0392b!important}',\n      /* SHORT VIEWPORTS: give the cart back its height (Kegan 21 Aug 2026).\n         The strip is 126px and flex-shrink:0, so it never yields to the items pane.\n         Measured on live at 430x700: the drawer's fixed furniture (header, progress\n         bar, this strip, total, discount row, checkout, trust icons) came to 523px,\n         leaving 177px for a list that needed 340px - 48% of the cart clipped. A\n         two-line cart needs a 900px viewport to show in full; phones give 700-800 and\n         an in-app browser less, so this is the normal mobile case, not an edge one.\n         Trimmed rather than hidden, because the gap-closer earns its place on AOV:\n         64px thumb -> 44px, tighter padding, label on one line with the card. */\n      /* Upsell skeleton */\n      '.cd-upsell-skel{width:100%;height:64px;border-radius:6px;background:linear-gradient(90deg,#f0f0f0 25%,#E4E9EC 50%,#f0f0f0 75%);background-size:200% 100%;animation:cd-skel 1.2s ease-in-out infinite}',\n      '@keyframes cd-skel{0%{background-position:200% 0}100%{background-position:-200% 0}}',\n      /* Upsell variant swatches \u2014 107px = 3 full pills + ~13px of 4th peeking */\n      '.cd-upsell-variants-row{display:flex;align-items:center;gap:4px}',\n      '.cd-upsell-variants{display:flex;flex-wrap:nowrap;gap:5px;width:107px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;flex-shrink:0;cursor:grab}',\n      '.cd-upsell-variants.cd-dragging{cursor:grabbing;user-select:none}',\n      '.cd-upsell-variants::-webkit-scrollbar{display:none}',\n      '.cd-upsell-scroll-btn{flex-shrink:0;background:none;border:none;padding:0 2px;color:#6B7280;font-size:18px;line-height:1;cursor:pointer;transition:color .1s}',\n      '.cd-upsell-scroll-btn:hover{color:#6B7280}',\n      '.cd-upsell-vpill{width:28px;height:28px;border-radius:50%;border:2px solid transparent;background:#EAF7FC;cursor:pointer;padding:0;overflow:hidden;display:flex;align-items:center;justify-content:center;transition:border-color .1s,box-shadow .1s;flex-shrink:0}',\n      '.cd-upsell-vpill:hover:not(.selected){border-color:#A3ACB2}',\n      '.cd-upsell-vpill.selected{border-color:#262626;box-shadow:0 0 0 2px #fff inset}',\n    ].join('');\n    document.head.appendChild(s);\n  }\n\n  function injectShell() {\n    if (document.getElementById(DRAWER_ID)) return;\n    var shell =\n      '<div id=\"cd-cart-drawer\">' +\n        '<div id=\"cd-cart-overlay\"></div>' +\n        '<div id=\"cd-cart-panel\">' +\n          '<div id=\"cd-cart-header\">' +\n            '<span id=\"cd-cart-title\">Cart<span id=\"cd-cart-count-badge\">0</span></span>' +\n            '<button id=\"cd-cart-close\" aria-label=\"Close cart\">&#x2715;</button>' +\n          '</div>' +\n          '<div id=\"cd-ship-bar\">' +\n            '<div id=\"cd-ship-bar-msg\"></div>' +\n            '<div id=\"cd-ship-bar-track\"><div id=\"cd-ship-bar-fill\"></div></div>' +\n          '</div>' +\n          '<div id=\"cd-items-wrap\">' +\n            '<div id=\"cd-cart-items\"></div>' +\n            /* The upsell lives INSIDE the scroll area, after the last item (Kegan\n               21 Aug 2026, pointing at hears.com's mobile cart). It used to be a\n               SIBLING of #cd-items-wrap with flex-shrink:0, which meant it claimed\n               its height off the top of the cart on every screen: at 430x700 it took\n               95px of the 304px between header and footer and the customer's own\n               items were left with 209px for 340px of content.\n               As a child of the scroller it competes for SCROLL instead of for\n               height, so the items get the whole pane and this is simply the last\n               thing you reach. It also no longer needs shrinking to earn its place,\n               which is why the short-viewport trim was dropped again.\n               NOTE it is a sibling of #cd-cart-items, not a child: render() rewrites\n               that element's innerHTML, which would destroy the strip on every\n               render. */\n            '<div id=\"cd-upsell-strip\" style=\"display:none\">' +\n              '<div id=\"cd-upsell-label\">You might also like</div>' +\n              '<div id=\"cd-upsell-card-wrap\"></div>' +\n            '</div>' +\n            '<div id=\"cd-items-loading\"><div class=\"cd-items-spinner\"></div></div>' +\n          '</div>' +\n          '<div id=\"cd-cart-footer\">' +\n            '<div id=\"cd-price-block\">' +\n              '<div id=\"cd-ship-row\" hidden><span>Shipping</span><span id=\"cd-ship-row-val\"></span></div>' +\n              '<div id=\"cd-total-row\">' +\n                '<span id=\"cd-total-label\">Total</span>' +\n                '<div id=\"cd-total-prices\">' +\n                  '<span id=\"cd-original-price\"></span>' +\n                  '<span id=\"cd-total-price\"></span>' +\n                '</div>' +\n              '</div>' +\n              '<span id=\"cd-total-save\"></span>' +\n            '</div>' +\n            '<div id=\"cd-discount-section\">' +\n              '<div id=\"cd-discount-loading\"><div class=\"cd-disc-spinner\"></div></div>' +\n              '<div id=\"cd-discount-subline\" style=\"display:none\">' +\n                '<div class=\"cd-discount-badge\">' +\n                  '<span class=\"cd-discount-code\" id=\"cd-discount-code-label\"></span>' +\n                  '<button id=\"cd-discount-remove-btn\" aria-label=\"Remove discount\">&#xD7;</button>' +\n                '</div>' +\n                '<span id=\"cd-discount-savings\"></span>' +\n              '</div>' +\n              '<div id=\"cd-discount-input-row\">' +\n                '<input id=\"cd-discount-input\" type=\"text\" placeholder=\"Add discount code\" autocomplete=\"off\" autocapitalize=\"none\" spellcheck=\"false\">' +\n                '<button id=\"cd-discount-btn\" type=\"button\">Apply</button>' +\n              '</div>' +\n              '<div id=\"cd-discount-msg\" style=\"display:none\"></div>' +\n            '</div>' +\n            '<a href=\"/checkout\" id=\"cd-cart-checkout\">' +\n              '<span>CHECKOUT</span>' +\n            '</a>' +\n            '<div id=\"cd-cart-trust\">' +\n              '<div class=\"cd-trust-item\">' +\n                '<img class=\"cd-trust-icon\" src=\"https://cdn.shopify.com/s/files/1/0409/1163/4582/files/Image_1_2x_ebe117da-508f-4ae5-bd42-0ca9f7fdc8c2.png?v=1721130433\" alt=\"Australian Owned\">' +\n                'Australian Owned &amp; Operated' +\n              '</div>' +\n              '<div class=\"cd-trust-item\">' +\n                '<img class=\"cd-trust-icon\" src=\"https://cdn.shopify.com/s/files/1/0409/1163/4582/files/Layer_1-2_2x_96bc48a1-f577-46db-89f5-1756996fb8a5.png?v=1721130851\" alt=\"5 Year Warranty\">' +\n                '5 Year Warranty' +\n              '</div>' +\n              '<div class=\"cd-trust-item\">' +\n                '<img class=\"cd-trust-icon\" src=\"https://cdn.shopify.com/s/files/1/0409/1163/4582/files/Layer_1-2_2x_67c7dbbc-4494-4d2a-a918-f8a79983c5c9.png?v=1721130907\" alt=\"30 Day Free Returns\">' +\n                '30 Day Free Returns' +\n              '</div>' +\n            '</div>' +\n          '</div>' +\n        '</div>' +\n      '</div>';\n    document.body.insertAdjacentHTML('beforeend', shell);\n    document.getElementById('cd-cart-close').addEventListener('click', closeDrawer);\n    document.getElementById('cd-cart-overlay').addEventListener('click', closeDrawer);\n    // Single persistent delegated listener \u2014 set up once, never re-added on re-render\n    document.getElementById('cd-cart-items').addEventListener('click', function (e) {\n      // Open/close the gift colour picker. Checked BEFORE the swatch branch: the\n      // toggle contains a copy of the current swatch as its own label, and without\n      // this it would fall through and be read as a colour choice.\n      var gift_size = e.target.closest('.cd-gift-szb');\n      if (gift_size) { if (gift_size.getAttribute('data-gift-size')) giftSizeSwap(gift_size); return; }\n      var gift_toggle = e.target.closest('.cd-gift-toggle');\n      if (gift_toggle) {\n        var pills = gift_toggle.parentElement.querySelector('.cd-gift-pills');\n        if (pills) {\n          var open = pills.hasAttribute('hidden');\n          if (open) pills.removeAttribute('hidden'); else pills.setAttribute('hidden', '');\n          gift_toggle.setAttribute('aria-expanded', open ? 'true' : 'false');\n          var lbl = gift_toggle.querySelector('.cd-gift-change');\n          if (lbl) lbl.textContent = open ? 'Close' : 'Change colour';\n        }\n        return;\n      }\n      // Gift colour swatch \u2014 swap the gift line to the chosen variant\n      var gift_pill = e.target.closest('.cd-gift-vpill');\n      if (gift_pill) {\n        if (gift_pill.classList.contains('selected')) return;\n        var gift_wrap = gift_pill.closest('.cd-gift-variants');\n        if (gift_wrap) {\n          // a pair-gift line (V / L / F grips, lids, a set's extras) passes its tag, units and set mark\n          swapGiftVariant(\n            gift_wrap.getAttribute('data-key'),\n            gift_pill.getAttribute('data-variant-id'),\n            gift_wrap.getAttribute('data-target'),\n            gift_wrap.getAttribute('data-prop'),\n            gift_wrap.getAttribute('data-qty'),\n            gift_wrap.getAttribute('data-set'),\n            gift_wrap.getAttribute('data-current')\n          );\n        }\n        return;\n      }\n      // Edit Engraving (23 Oct 2026): only printed where the page defines window.apEditEngraving (the new stubby page)\n      var edit_btn = e.target.closest('[data-edit-eng]');\n      if (edit_btn) {\n        if (typeof window.apEditEngraving === 'function') { window.apEditEngraving(edit_btn.getAttribute('data-cust-id')); }\n        return;\n      }\n      var pers_btn = e.target.closest('[data-personalise]');\n      if (pers_btn) {\n        var pv = pers_btn.getAttribute('data-variant-id'), ph = pers_btn.getAttribute('data-handle'), pga = pers_btn.getAttribute('data-gift'), pg = pga === 'c' ? 'c' : pga === '1';\n        if (typeof window.apEngraveLine === 'function') { window.apEngraveLine(pv, ph, pg); }\n        else { window.location.href = '/products/' + ph + '?variant=' + pv + '&engrave=' + pv + (pg ? '&eg=' + (pg === 'c' ? 'c' : '1') : ''); }\n        return;\n      }\n      var qty_btn = e.target.closest('.cd-qty');\n      if (qty_btn) {\n        if (qty_btn.disabled || qty_btn.classList.contains('cd-qty--floor')) return;\n        var qty = parseInt(qty_btn.getAttribute('data-qty'), 10);\n        var row = qty_btn.closest('.cd-cart-item');\n        if (qty_btn.getAttribute('data-logo')) {\n          // Logo line: + adds a branded unit to the SAME line (never a plain\n          // full-price bottle) and - lowers it; the fee lines follow in the\n          // same write (see logoLineUpdates)\n          logoQtyChange(qty_btn.getAttribute('data-key'), qty);\n          return;\n        }\n        if (qty_btn.classList.contains('cd-qty-plus') && qty_btn.getAttribute('data-is-customised')) {\n          if (row) row.querySelectorAll('.cd-qty').forEach(function (b) { b.disabled = true; b.style.opacity = '0.5'; });\n          fetch('/cart/add.js', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ items: [{ id: parseInt(qty_btn.getAttribute('data-variant-id'), 10), quantity: 1 }] })\n          }).then(function () { render(); });\n        } else {\n          // Optimistic: paint instantly, sync to Shopify in the background\n          optimisticChange(qty_btn.getAttribute('data-key'), qty, null);\n        }\n        return;\n      }\n      var rem_btn = e.target.closest('.cd-remove');\n      if (rem_btn) {\n        // Manual gift removal opts the customer out for this tier until they\n        // drop below the threshold and cross it again\n        var gift_target = rem_btn.getAttribute('data-gift-target');\n        if (gift_target) { cdGiftOptOut[gift_target] = true; saveGiftOptOut(); }\n        var rem_row = rem_btn.closest('.cd-cart-item');\n        if (rem_row) rem_row.classList.add('removing');\n        optimisticChange(rem_btn.getAttribute('data-key'), 0, rem_btn.getAttribute('data-engraving-key') || null);\n        return;\n      }\n      var pers_toggle = e.target.closest('.cd-item-personalisation');\n      if (pers_toggle) {\n        var props_el = pers_toggle.nextElementSibling;\n        if (props_el && props_el.classList.contains('cd-item-props')) {\n          pers_toggle.classList.toggle('cd-pers-open');\n          props_el.classList.toggle('cd-props-open');\n        }\n      }\n    });\n\n    // Upsell strip \u2014 delegated listener for variant pill selection and add-to-cart\n    document.getElementById('cd-upsell-strip').addEventListener('click', function(e) {\n      // Scroll arrows (\u2039 back, \u203A forward) \u2014 one pill = 33px\n      var scrollBtn = e.target.closest('.cd-upsell-scroll-btn');\n      if (scrollBtn) {\n        var varList = scrollBtn.classList.contains('cd-upsell-back')\n          ? scrollBtn.nextElementSibling\n          : scrollBtn.previousElementSibling;\n        if (varList) varList.scrollLeft += scrollBtn.classList.contains('cd-upsell-back') ? -33 : 33;\n        return;\n      }\n      // Variant pill selection\n      var pill = e.target.closest('.cd-upsell-vpill');\n      if (pill) {\n        var ustrip = document.getElementById('cd-upsell-strip');\n        ustrip.querySelectorAll('.cd-upsell-vpill').forEach(function(p){ p.classList.remove('selected'); });\n        pill.classList.add('selected');\n        var addBtn = ustrip.querySelector('.cd-upsell-add, .cd-pitch');\n        var pitchChip = document.getElementById('cd-pitch-chip');\n        if (pitchChip) {\n          var pPrice = parseInt(pill.getAttribute('data-price'), 10), pPct = parseInt(ustrip.dataset.pct || '0', 10);\n          pitchChip.textContent = 'Only ' + money(ustrip.dataset.pitch === 'gift' ? Math.round(pPrice * (100 - pPct) / 100) : cdPitchMore(pPrice, pPct)) + ' More';\n        }\n        if (addBtn) {\n          addBtn.setAttribute('data-variant-id', pill.getAttribute('data-variant-id'));\n          addBtn.style.opacity = '';\n          addBtn.style.pointerEvents = '';\n        }\n        var priceEl = document.getElementById('cd-upsell-price-val');\n        if (priceEl && document.getElementById('cd-upsell-strip').dataset.promoMode !== 'one-away') {\n          priceEl.innerHTML = upsellPriceHtml(parseInt(pill.getAttribute('data-price'), 10), parseInt(document.getElementById('cd-upsell-strip').dataset.pct || '0', 10));\n        }\n        var vname = document.getElementById('cd-upsell-vname'); if (vname) { vname.textContent = pill.getAttribute('title') || ''; }\n        var thumbImg = document.getElementById('cd-upsell-thumb-img');\n        var newThumb = pill.getAttribute('data-thumb');\n        if (thumbImg && newThumb) { thumbImg.src = newThumb; thumbImg.style.display = ''; }\n        return;\n      }\n      // Add to cart\n      var btn = e.target.closest('.cd-upsell-add, .cd-pitch');\n      if (!btn || btn.disabled || !btn.getAttribute('data-variant-id')) return;\n      var nudgeStrip = document.getElementById('cd-upsell-strip');\n      if (nudgeStrip && nudgeStrip.dataset.nudge) cdTrack('bf_nudge_' + nudgeStrip.dataset.nudge);\n      btn.disabled = true;\n      btn.style.opacity = '0.4';\n      showItemsLoading(true);\n      var fd = new FormData();\n      fd.append('id', btn.getAttribute('data-variant-id'));\n      fd.append('quantity', 1);\n      fetch('/cart/add.js', { method: 'POST', body: fd })\n        .then(function(r){ if (!r.ok) throw new Error(); return r.json(); })\n        .then(function(){ render(); })\n        .catch(function(){\n          showItemsLoading(false);\n          btn.disabled = false;\n          btn.style.opacity = '';\n          btn.classList.add('cd-upsell-add-err');\n          setTimeout(function(){ btn.classList.remove('cd-upsell-add-err'); }, 800);\n        });\n    });\n\n    // Desktop drag-to-scroll on variant swatch row\n    var _dragEl = null, _dragStartX = 0, _dragScrollStart = 0;\n    document.getElementById('cd-upsell-strip').addEventListener('mousedown', function(e) {\n      var vars = e.target.closest('.cd-upsell-variants');\n      if (!vars) return;\n      _dragEl = vars;\n      _dragStartX = e.clientX;\n      _dragScrollStart = vars.scrollLeft;\n      vars.classList.add('cd-dragging');\n      e.preventDefault();\n    });\n    document.addEventListener('mousemove', function(e) {\n      if (!_dragEl) return;\n      _dragEl.scrollLeft = _dragScrollStart - (e.clientX - _dragStartX);\n    });\n    document.addEventListener('mouseup', function() {\n      if (_dragEl) { _dragEl.classList.remove('cd-dragging'); _dragEl = null; }\n    });\n  }\n\n  function openDrawer() {\n    injectStyles();\n    injectShell();\n    var drawer = document.getElementById(DRAWER_ID);\n    if (drawer.classList.contains('open')) {\n      // Already open - a later background cart write (e.g. a second /cart/add\n      // firing after the drawer already rendered) still needs to refresh the\n      // contents, otherwise the drawer shows stale state until closed/reopened.\n      render();\n      return;\n    }\n    document.getElementById('cd-cart-items').innerHTML = '<div class=\"cd-spinner\">Loading\\u2026</div>';\n    drawer.classList.add('open');\n    // Desktop only: lock body scroll. On mobile/touch, the fixed full-screen overlay catches\n    // all touch events \u2014 no lock needed. Setting body overflow on iOS causes scroll to break\n    // after close because iOS re-evaluates scroll container via html (which has overflow-x:hidden in CSS).\n    if (!('ontouchstart' in window)) {\n      document.body.style.overflow = 'hidden';\n    }\n    render();\n  }\n\n  var cdJustClosed = false;\n\n  function unlockScroll() {\n    document.documentElement.style.overflow = '';\n    // Use setProperty with !important \u2014 iOS Safari locks the entire viewport scroll when\n    // overflow-x:hidden is set on html (Debutify base CSS, sheet 17). A plain assignment\n    // loses to that lock; !important inline overrides it.\n    document.documentElement.style.setProperty('overflow-y', 'auto', 'important');\n    document.documentElement.classList.remove('js-drawer-open');\n    document.documentElement.classList.remove('js-drawer-open-right');\n    document.body.style.overflow = '';\n    document.body.style.position = '';\n    document.body.style.top = '';\n    document.body.style.width = '';\n    document.body.classList.remove('js-drawer-open');\n    document.body.classList.remove('js-drawer-open-right');\n  }\n\n  function closeDrawer() {\n    var el = document.getElementById(DRAWER_ID);\n    if (el) el.classList.remove('open');\n    unlockScroll();\n    cdJustClosed = true;\n    setTimeout(function () { cdJustClosed = false; }, 500);\n    // Deferred unlock: Debutify cart code runs async (setTimeout 0-100ms) after our close.\n    // We can't catch it with watchOldDrawer because it may not touch body classes.\n    // Running unlockScroll again at 150ms ensures any late Debutify scroll-lock is cleared.\n    setTimeout(function () {\n      var drawer = document.getElementById(DRAWER_ID);\n      if (!drawer || !drawer.classList.contains('open')) {\n        unlockScroll();\n      }\n    }, 150);\n  }\n\n  function money(cents) {\n    return '$' + (cents / 100).toFixed(2);\n  }\n  function upsellPriceHtml(cents, pct) {\n    return pct ? '<span class=\"cd-upsell-was\">' + money(cents) + '</span>' + money(Math.round(cents * (100 - pct) / 100)) : money(cents);\n  }\n\n  /* Format a line item property value for display. */\n  function formatPropVal(v) {\n    var s = String(v).trim();\n    // Uploaded image URLs \u2192 \"View design \u2197\" link\n    if ((s.indexOf('http') === 0 || s.indexOf('//') === 0) && s.length > 60) {\n      var esc = s.replace(/\"/g, '&quot;');\n      return '<a href=\"' + esc + '\" target=\"_blank\" rel=\"noopener\" class=\"cd-prop-link\">View design <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"display:inline-block;vertical-align:middle;margin-bottom:1px\"><path d=\"M2 8L8 2\"/><path d=\"M4 2h4v4\"/></svg></a>';\n    }\n    // Finish values \u2192 friendly casing\n    if (s === 'uv') return 'Colour (UV)';\n    if (s === 'metallic') return 'Metallic';\n    return s;\n  }\n\n  /* Returns true for the DTC/B2B engraving service SKU.\n     Engraving SKU has \"_Customised Product\" (title case) \u2014 set by customizer.\n     The main product has \"_customised_product\" (lowercase) \u2014 different key, not an engraving item. */\n  function isEngravingItem(item) {\n    var props = item.properties || {};\n    return !!(props['_Customised Product']);\n  }\n\n  /* Logo lines (4 Oct 2026): B2B pop-up and co-brand studio lines carry\n     _cust_id plus \"B2B ...\" keys or _cobrand. Their logo fee is a separate\n     surcharge line (or several, a discount can split it) sharing _cust_id, and\n     its quantity must stay (logos per bottle) x (bottles). DTC engraved lines\n     have no B2B keys and keep their old +/- behaviour. */\n  function isLogoLine(props) {\n    props = props || {};\n    if (!props['_cust_id']) return false;\n    if (props['_cobrand'] === 'yes') return true;\n    return Object.keys(props).some(function (k) { return /^_?B2B /.test(k); });\n  }\n\n  // Logo fee units per bottle: one per non-empty \"B2B <ZONE> IMAGE\" and\n  // \"B2B <ZONE> NAME\" (the pop-up charges text and logo on a side separately).\n  function logoUnitsPerItem(props) {\n    var n = 0;\n    Object.keys(props || {}).forEach(function (k) {\n      if (/^B2B [A-Z]+ (IMAGE|NAME)$/.test(k) && String(props[k] || '').trim() !== '') n++;\n    });\n    return n;\n  }\n\n  // The /cart/update.js map for setting a logo line to `qty` bottles with its\n  // fee lines summed back to units x qty. Fee lines are matched by _cust_id\n  // across every line, so a fee split into two lines by a discount is counted\n  // once in total; extra units go on the largest fee line, and units come off\n  // the smallest fee lines first.\n  function logoLineUpdates(cart, key, qty) {\n    var items = (cart && cart.items) || [];\n    var item = null;\n    items.forEach(function (i) { if (i.key === key) item = i; });\n    if (!item) return null;\n    var props = item.properties || {};\n    var updates = {};\n    updates[key] = qty;\n    var linked = items.filter(function (i) {\n      return isEngravingItem(i) && (i.properties || {})['_cust_id'] === props['_cust_id'];\n    });\n    if (!linked.length) return updates;\n    var current = linked.reduce(function (n, i) { return n + i.quantity; }, 0);\n    var per = logoUnitsPerItem(props);\n    if (!per) per = item.quantity ? Math.max(1, Math.round(current / item.quantity)) : 1;\n    var diff = per * qty - current;\n    if (diff > 0) {\n      var big = linked.reduce(function (a, b) { return b.quantity > a.quantity ? b : a; });\n      updates[big.key] = big.quantity + diff;\n    } else if (diff < 0) {\n      var remove = -diff;\n      linked.slice().sort(function (a, b) { return a.quantity - b.quantity; }).forEach(function (l) {\n        if (!remove) return;\n        var take = Math.min(l.quantity, remove);\n        updates[l.key] = l.quantity - take;\n        remove -= take;\n      });\n    }\n    return updates;\n  }\n\n  function burstConfetti() {\n    var bar = document.getElementById('cd-ship-bar');\n    if (!bar) return;\n    var colors = ['#e8b84b', 'var(--c-teal)', '#c0392b', '#2980b9', '#8e44ad'];\n    bar.style.position = 'relative';\n    for (var i = 0; i < 22; i++) {\n      var p = document.createElement('div');\n      p.style.cssText = 'position:absolute;width:7px;height:7px;border-radius:2px' +\n        ';left:' + Math.random() * 100 + '%' +\n        ';top:0' +\n        ';background:' + colors[i % colors.length] +\n        ';animation:cd-confetti-fall ' + (0.6 + Math.random() * 0.6).toFixed(2) + 's ' +\n          (Math.random() * 0.4).toFixed(2) + 's ease-out both' +\n        ';pointer-events:none';\n      bar.appendChild(p);\n      p.addEventListener('animationend', function () { this.remove(); });\n    }\n    if (navigator.vibrate) navigator.vibrate(80);\n  }\n\n  // \u2500\u2500\u2500 AOV GIFT TIERS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // Auto-adds a free gift product when the qualifying cart total crosses a tier\n  // threshold, and removes it again when the cart drops back below. Tiers are\n  // configured in Theme Editor \u2192 \"Cart drawer gift tiers\" and injected by\n  // theme.liquid as window.cdGiftTiers ([{target, handle, label}], cents, sorted).\n  //\n  // The gift line is added at FULL price carrying a hidden '_aov_gift' property;\n  // a matching ACTIVE automatic BXGY discount in Admin zeroes it in cart and at\n  // checkout (same pattern as the Father's Day ice tray). The gift's own value\n  // never counts toward the threshold (see giftQualifyingTotal).\n  var GIFT_PROP = '_aov_gift';\n  var COOLER_PROP = '_cooler_gift';   /* BF Cooler Bag Week's free 1L (syncCooler): a gift, never a bottle anyone paid for */\n  var cdGiftOptOut = {};        // tier target \u2192 true when customer manually removed the gift\n  try { cdGiftOptOut = JSON.parse(sessionStorage.getItem('cdGiftOptOut') || '{}') || {}; } catch (e) {}\n  function saveGiftOptOut() {\n    try { sessionStorage.setItem('cdGiftOptOut', JSON.stringify(cdGiftOptOut)); } catch (e) {}\n  }\n  var cdGiftFailed = {};        // tier target \u2192 true when auto-add failed (e.g. sold out) \u2014 prevents retry loops\n  var cdGiftSyncing = false;    // suppress re-entrant syncs during our own cart writes\n  var cdGiftProductCache = {};  // handle \u2192 Promise<product JSON>\n  // Upsell strip caches. The strip re-runs on EVERY render, and both of its fetches\n  // were uncached, so one add-to-cart on a $138 cart fired 24 requests of which 16\n  // were duplicates: the same three products and the same three metafield lookups,\n  // three times each. Measured on live 23 Aug 2026.\n  // Session-lifetime, same trade-off cdGiftProductCache already makes: a product that\n  // sells out mid-session can still be offered until the next page load. The strip\n  // already tolerates that -- the add fails and it marks the variant unavailable.\n  var cdPinnedProductCache  = {};  // handle \u2192 Promise<normalised product JSON>\n  var cdDisabledVariantCache = {};  // handle \u2192 Promise<{variantId: true}>\n  var cdProductJsonCache    = {};  // handle \u2192 Promise<RAW product JSON, never mutated>\n\n  // One fetch per product per session, shared by the gift picker and the upsell strip.\n  // Both wanted stubby-cooler and were fetching it separately.\n  //\n  // Callers that MUTATE what they get back (the upsell strip rewrites v.available from\n  // the disable_variant metafields) must take a copy first -- see fetchPinnedProduct.\n  // Handing the same object to both would let the strip's availability edits leak into\n  // the gift picker's view of the same product, which is a behaviour change, not a\n  // caching change.\n  function cdProductJson(handle) {\n    if (!cdProductJsonCache[handle]) {\n      cdProductJsonCache[handle] = fetch('/products/' + handle + '.js')\n        .then(function (r) { return r.json(); })\n        .catch(function () { return null; });\n    }\n    return cdProductJsonCache[handle];\n  }\n\n  // Tiers with a sane config only \u2014 a blank/garbled threshold must never\n  // become target 0 (which would gift every cart and zero the bar maths).\n  // Co-brand and B2B carts get NO spend-tier gifts: the gift Function switches tiers off for them\n  // (cobrandCart / b2bCart), so a \"free\" bottle or bag the drawer added was charged at checkout\n  // (reported 1 Oct 2026: a co-brand buyer was charged for his free gift). Same test as pairCartBlocked.\n  function cdTierFreeCart(cart) {\n    return !!(cart && cart.items && cart.items.some(function (i) {\n      var props = i.properties || {};\n      return props._cobrand || Object.keys(props).some(function (k) { return k.indexOf('B2B ') === 0; });\n    }));\n  }\n  function activeGiftTiers() {\n    if (typeof cdLastCart !== 'undefined' && (cdTierFreeCart(cdLastCart) || cdSecretSetCart(cdLastCart))) return [];\n    return (window.cdGiftTiers || []).filter(function (t) {\n      return t && t.target > 0 && t.handle;\n    });\n  }\n\n  function isGiftItem(item) {\n    var p = item.properties || {};\n    return !!(p[GIFT_PROP] || p[COOLER_PROP]);\n  }\n\n  // The tier a tagged gift line belongs to under the CURRENT arm, or null when the line is stale.\n  // Target AND product (4 Oct 2026, live money bug): the gift Function frees a tagged line by the tier's HANDLE\n  // (aussiepal-gifts, any _aov_gift value), and J and M both use target 20000, so an M Lunch Pal ('20000',\n  // lunchpal) survived the redraw to J and was charged $119 (3 x 2L: $386 instead of $267 + a free 1L).\n  // And the arm (`_ob`, stamped by snippets/offer-test-bucket.liquid on every gift add): the Function prices by\n  // `_ob` when a checkout drops the cart attribute, so a line from another arm is stale even on a matching tier,\n  // unless the two arms run the same tier ladder (C and J, A and K), where it is still exactly the right gift.\n  function cdTierFor(item, tiers) {\n    var p = item.properties || {}, t = p[GIFT_PROP];\n    if (!t) return null;\n    var tier = tiers.filter(function (x) { return String(x.target) === String(t) && tierTakes(x, item.handle); })[0];\n    if (!tier) return null;\n    var cur = window.AP_OFFER_BUCKET;\n    if (p._ob && cur && p._ob !== cur && !cdSameTierRules(p._ob, cur)) return null;\n    return tier;\n  }\n  // The products a tier's gift may be. One handle, or, in the final 2 days (D09, 29 to 30 Nov), the 1L tier lists\n  // handles ['1l', '2l'] (snippets/offer-test-bucket.liquid), as the gift Function frees a tagged 2L then (pickOn). The\n  // drawer still ADDS the tier's own handle (the 1L); the gift row's 1L | 2L switch swaps it (giftSizeSwitch).\n  function tierTakes(t, handle) { return t.handle === handle || !!(t.handles && t.handles.indexOf(handle) !== -1); }\n  // the ladders live in snippets/offer-test-bucket.liquid (TIERS), which answers this\n  function cdSameTierRules(a, b) {\n    return typeof window.apSameTierLadder === 'function' && window.apSameTierLadder(a, b) === true;\n  }\n\n  // Line value the customer actually pays after EVERY discount touching the\n  // line. final_line_price reflects automatic/Scripts product discounts but\n  // NOT cart-level code allocations \u2014 those only appear in item.discounts.\n  // Subtract the unreflected remainder so gift thresholds always measure the\n  // real post-discount spend (proven live: a 20% code left final_line_price\n  // untouched while allocating per line in item.discounts).\n  function cdEffectiveLinePrice(i) {\n    var flp = typeof i.final_line_price === 'number' ? i.final_line_price : i.line_price;\n    var olp = typeof i.original_line_price === 'number' ? i.original_line_price : flp;\n    var alloc = 0;\n    (i.discounts || []).forEach(function (d) {\n      alloc += (typeof d.amount === 'number' ? d.amount : 0);\n    });\n    var unreflected = alloc - (olp - flp); // what flp hasn't already absorbed\n    if (unreflected > 0) flp -= unreflected;\n    return flp > 0 ? flp : 0;\n  }\n\n  // Qualifying total = post-discount line totals, excluding gift lines and any\n  // excluded handles (Theme Editor setting). An item another promo already made\n  // free contributes $0 \u2014 matching how checkout computes the BXGY spend\n  // requirement.\n  function giftQualifyingTotal(cart) {\n    var excl = String(window.cdGiftExcludeHandles || '').split(',')\n      .map(function (s) { return s.trim(); }).filter(Boolean);\n    return cart.items.reduce(function (sum, i) {\n      if (isGiftItem(i)) return sum;\n      if (excl.indexOf(i.handle) !== -1) return sum;\n      return sum + cdEffectiveLinePrice(i);\n    }, 0);\n  }\n  // A tier with basis 'bottles' (bucket H's 15L bag, 24 Sep) counts only the 1L/2L bottles the\n  // customer pays for, post-discount, never jugs, accessories or gift lines. Mirrors the gift\n  // Function's qualifyingBottles.\n  function giftQualifyingBottles(cart) {\n    return cart.items.reduce(function (sum, i) {\n      var p = i.properties || {};\n      if (p['_aov_gift'] || p['_pair_gift'] || p['_cooler_gift']) return sum;\n      if (i.handle !== '1l' && i.handle !== '2l') return sum;\n      return sum + cdEffectiveLinePrice(i);\n    }, 0);\n  }\n  function tierQual(cart, t) { return t && t.basis === 'bottles' ? giftQualifyingBottles(cart) : giftQualifyingTotal(cart); }\n\n  function fetchGiftProduct(handle) {\n    if (!cdGiftProductCache[handle]) cdGiftProductCache[handle] = cdProductJson(handle);\n    return cdGiftProductCache[handle];\n  }\n\n  // Reconcile gift lines against tiers. Resolves to a fresh cart when a\n  // mutation happened, or null when nothing changed. All writes run serially \u2014\n  // Shopify carts do not tolerate racing.\n  // ---------------------------------------------------------------------------\n  // HIS & HERS PAIR GIFT (launch night, 6 Sep 2026, Kegan): the pair box adds\n  // its gift line itself, but a customer who reaches two bottles any other way\n  // (qty +, a second colour from the upsell strip, a second visit) must get the\n  // same free gift, or the \"add another and get a free cup holder\" message\n  // would be a lie. Contract (aussiepal-gifts launch/choc-pair-offer): one gift\n  // line carrying `_pair_gift: yes`; the Function frees ONE unit when the cart\n  // holds >= 2 bottles with handle 1l/2l. Holder if any 1L is in the pair,\n  // ice tray for 2 x 2L. Below two bottles the tagged gift is removed again.\n  // Skipped for B2B carts and for secret-offer carts (attribute _secret_offer),\n  // whose tagged trays the Function prices on its own rule.\n  // ---------------------------------------------------------------------------\n  var PAIR_GIFT_PROP = '_pair_gift';\n  var PAIR_BOTTLE_HANDLES = { '1l': true, '2l': true };\n  var PAIR_HOLDER_VID = 45128518205637;   // Car Cupholder For 1L Bottle\n  var PAIR_TRAY_VID   = 46299413643461;   // Ice Tray - 1L & 2L Size\n  var PAIR_HOLDER_HANDLE = 'car-cupholder-for-1l-bottle';\n  var PAIR_TRAY_HANDLE   = 'ice-tray-1l-2l-size';\n  var cdPairSyncing = false, cdPairFailed = false;\n\n  // BF OFFER TEST (19 Sep 2026, snippets/offer-test-bucket.liquid): the bucket\n  // decides what a pair earns. window.cdOfferTest.pairGift is 'standard'\n  // (holder / tray, today's rule), 'engrave' (bucket B: engraving free, no gift\n  // line), 'kit' (bucket F: a matching grip and a Smart Lid per paired bottle)\n  // or 'none' (bucket A: the 20% + free 1L offer carries no pair gift).\n  // The gift Function (aussiepal-gifts OFFER_TEST) frees the same lines, so the\n  // two must agree on handles.\n  var PAIR_KIT_GRIP = { '1l': '1l-bottle-silicone-sleeve', '2l': '2l-bottle-silicone-sleeve' };\n  var PAIR_KIT_LID = '1l-2l-dual-action-smart-lid';\n  function offerRules() { return window.cdOfferTest || { pairGift: 'standard' }; }\n  function pairGiftMode() { return offerRules().pairGift || 'standard'; }\n  // The colour a gift should come in, given the bottle it goes with. Grip and\n  // lid titles are plain (\"Latte\", \"Seabreeze\"); bottles carry \"Latte Layers\",\n  // \"Seabreeze Layers\", \"Stainless Black\". Exact title first, then the bottle\n  // name with those words dropped, then any colour that is in stock.\n  function cdVariantFor(handle, colour) {\n    return cdProductJson(handle).then(function (prod) {\n      if (!prod || !prod.variants) return null;\n      var block = (window.cdGiftVariantBlock || {})[handle];\n      var ok = prod.variants.filter(function (v) { return v.available && !(block && block.test(String(v.title))); });\n      var want = String(colour || '').trim().toLowerCase();\n      var plain = want.replace(/\\s*layers$/, '').replace(/^stainless\\s+/, '');\n      var hit = ok.filter(function (v) { return String(v.title).toLowerCase() === want; })[0]\n             || ok.filter(function (v) { return String(v.title).toLowerCase() === plain; })[0]\n             || ok[0] || null;\n      return hit;\n    });\n  }\n\n  // OCTOBER (1 Oct 2026, Kegan \"Go: J vs Two Looks + holder\"): J ('pairOnce') and L ('twoLooks') give ONE\n  // gift per order at 2+ bottles, picked by what is in stock right now. J leads with the ice tray (its\n  // promise); L leads with the car cup holder when the cart has a 1L (the holder does not fit the 2L).\n  // Trays run out ~3 Oct until PO 73 lands, so both fall back to the holder (1L carts) or a Smart Lid.\n  // Mirrors freeOnePairGift in aussiepal-gifts 841b238, which frees whichever ONE tagged gift is there.\n  var cdGiftOk = {};\n  var PAIR_STUBBY_HANDLE = 'stubby-cooler'; /* J / M 2L-only gift (Kegan 2 Oct) */\n  function cdPrimeGiftStock() {\n    if (!(PAIR_STUBBY_HANDLE in cdGiftOk)) {\n      cdGiftOk[PAIR_STUBBY_HANDLE] = (window.cdGiftStock || {}).stubby !== false;\n      cdProductJson(PAIR_STUBBY_HANDLE).then(function (prod) {\n        if (prod && prod.variants) cdGiftOk[PAIR_STUBBY_HANDLE] = prod.variants.some(function (v) { return v.available; });\n      });\n    }\n    // V's grips (any colour in stock counts: cdVariantFor picks the colour)\n    [PAIR_KIT_GRIP['1l'], PAIR_KIT_GRIP['2l']].forEach(function (h) {\n      if (h in cdGiftOk || pairGiftMode() !== 'valuePack') return;\n      cdGiftOk[h] = true;\n      cdProductJson(h).then(function (prod) {\n        if (prod && prod.variants) cdGiftOk[h] = prod.variants.some(function (v) { return v.available; });\n      });\n    });\n    [PAIR_TRAY_HANDLE, PAIR_HOLDER_HANDLE].forEach(function (h) {\n      if (h in cdGiftOk) return;\n      var built = (window.cdGiftStock || {})[h === PAIR_TRAY_HANDLE ? 'tray' : 'holder'];\n      cdGiftOk[h] = built !== false;\n      cdProductJson(h).then(function (prod) {\n        var v = prod && prod.variants && prod.variants[0];\n        if (v) cdGiftOk[h] = !!v.available;\n      });\n    });\n  }\n  // fresh stock for these gift handles (no cache), after a refused add\n  function cdRecheckGiftStock(handles) {\n    handles.forEach(function (h) {\n      fetch('/products/' + h + '.js', { cache: 'no-store' }).then(function (r) { return r.json(); }).then(function (prod) {\n        if (prod && prod.variants) cdGiftOk[h] = prod.variants.some(function (v) { return v.available; });\n      }).catch(function () {});\n    });\n  }\n  function isOneGiftMode(mode) { return mode === 'pairOnce' || mode === 'twoLooks'; }\n  // the gifts this cart may hold as its ONE free gift, in the bucket's order (the holder only with a 1L)\n  function oneGiftOrder(b, mode) {\n    // window.cdTrayGiftOff (Kegan 2 Oct, trays short): the tray is not a gift at all, so a tray already in the cart is\n    // swapped for the holder (1L) or lid (2L-only) on the next sync, not kept\n    var holder = b.has1L ? [PAIR_HOLDER_HANDLE] : [], tray = window.cdTrayGiftOff ? [] : [PAIR_TRAY_HANDLE];\n    // J and M: a 2L-only order's gift is the stubby holder (the car cup holder doesn't fit the 2L), then the lid\n    var stubby = (mode === 'pairOnce' || mode === 'twoLooks') && !b.has1L ? [PAIR_STUBBY_HANDLE] : []; /* L too (Kegan 2 Oct) */\n    return (mode === 'pairOnce' ? tray.concat(holder) : holder.concat(tray)).concat(stubby, [PAIR_KIT_LID]);\n  }\n  // the one to ADD: the first in that order that is in stock (the lid always is, 14k)\n  function oneGiftHandle(b, mode) {\n    cdPrimeGiftStock();\n    return oneGiftOrder(b, mode).filter(function (h) { return h === PAIR_KIT_LID || cdGiftOk[h] !== false; })[0];\n  }\n  // V \"Value Pack\" (4 Oct 2026, aussiepal-gifts 03e1cd7 'valuePack'): at 2+ bottles ONE ice tray, ONE car cup holder\n  // (any 1L in the cart) or ONE stubby holder (2L-only carts, the holder doesn't fit the 2L) and TWO grips size for size,\n  // 1L grips first: 2 x 1L -> 2 x 1L grip, 1L + 2L -> one of each, 2 x 2L -> 2 x 2L grip, 3 x 1L + 2L -> 2 x 1L grip.\n  // The Function frees exactly these from `_pair_gift` lines and nothing in their place, so a gift that is out of stock\n  // is SKIPPED, never swapped for another (a swap would be charged). window.cdTrayGiftOff is J / L / M's switch and does\n  // not apply: the tray is the Value Pack's lead gift and trays sell ahead for it (Kegan 4 Oct).\n  function valuePackDue(b) {\n    var due = {};\n    if (b.units < 2) return due;\n    due[PAIR_TRAY_HANDLE] = 1;\n    due[b.has1L ? PAIR_HOLDER_HANDLE : PAIR_STUBBY_HANDLE] = 1;\n    var g1 = Math.min(b.ones, 2), g2 = Math.min(b.twos, 2 - g1);\n    if (g1) due[PAIR_KIT_GRIP['1l']] = g1;\n    if (g2) due[PAIR_KIT_GRIP['2l']] = g2;\n    return due;\n  }\n  var ONE_GIFT_NAME = {};\n  ONE_GIFT_NAME[PAIR_HOLDER_HANDLE] = '1L cup holder'; ONE_GIFT_NAME[PAIR_TRAY_HANDLE] = 'ice tray'; ONE_GIFT_NAME[PAIR_KIT_LID] = 'Smart Lid'; ONE_GIFT_NAME[PAIR_STUBBY_HANDLE] = 'stubby holder';\n  // L's default second grip per bottle colour lives in snippets/offer-test-bucket.liquid, so the bundle box\n  // (which runs before this file) pre-selects exactly the colour the drawer would add\n  function twoLooksGrip(size, bottleColour) { return window.apTwoLooksGrip ? window.apTwoLooksGrip(size, bottleColour) : 'Pink'; }\n\n  // One gift per PAIR of bottles (Kegan, 15 Sep 2026), like with like first: each\n  // pair of 1Ls earns a car cup holder, each pair of 2Ls earns the small ice tray,\n  // and a leftover 1L + leftover 2L earn one more holder. 4 x 1L + 2 x 2L = 2\n  // holders + 1 tray; 2 x 1L + 2 x 2L = 1 holder + 1 tray; no cap. Mirrors the\n  // gift Function's rule 1b, which is what actually frees the lines.\n  function pairBottleUnits(cart) {\n    var ones = 0, twos = 0, colours = { '1l': [], '2l': [] };\n    cart.items.forEach(function (i) {\n      // a FREE 1L from a spend tier (buckets A / C) or Cooler Bag Week is a gift, not a bottle they paired\n      if ((i.properties || {})[GIFT_PROP] || (i.properties || {})[COOLER_PROP]) return;\n      if (i.handle === '1l' || i.handle === '2l') {\n        if (i.handle === '1l') ones += i.quantity; else twos += i.quantity;\n        for (var k = 0; k < i.quantity; k++) colours[i.handle].push(i.variant_title || '');\n      }\n    });\n    var mixed = (ones % 2 === 1 && twos % 2 === 1) ? 1 : 0;\n    var holders = Math.floor(ones / 2) + mixed;\n    var trays = Math.floor(twos / 2);\n    // Build Your Pair (bucket F): the bottles that ARE in a pair earn a grip each and a lid each\n    var paired1L = Math.floor(ones / 2) * 2 + mixed, paired2L = Math.floor(twos / 2) * 2 + mixed;\n    return { units: ones + twos, ones: ones, twos: twos, has1L: ones > 0, pairs: holders + trays, holders: holders, trays: trays,\n             paired1L: paired1L, paired2L: paired2L, colours: colours };\n  }\n  // A secret set marks the cart with _secret_offer and prices its own tagged\n  // extras. The attribute lingers after the set is removed, so it only blocks\n  // the pair rule while a set signature line (a tagged grip or Lunch Pal) is\n  // still in the cart, mirroring the Function's signatureOk.\n  var SECRET_SIGNATURE = { '1l-bottle-silicone-sleeve': true, '2l-bottle-silicone-sleeve': true, 'lunchpal': true };\n  // SECRET SET MID-FLOW (4 Oct 2026, live money bug): a set with Personalise ticked adds its bottles one\n  // engraved bottle at a time (snippets/brand-2026-pair-box.liquid secretSet) and its signature lines only in\n  // finish(), so for the whole flow the cart looked like a plain pair: J / M added their holder, L its grips\n  // and holder. Once the set landed the gift Function (secretActive) stopped freeing them, and the spend tier\n  // then added J's free 1L / M's Lunch Pal at full price: Big Day Kit + Personalise on J was $89 over.\n  // secretSet() marks it with the page flag window.apSecretFlowLive: true only once it has validated the link and\n  // started, false again when finish() ends either way (after the signature lines are in the cart, or a failed\n  // final add) or when the flow cannot start. The pair box's inline script runs during parse, before this deferred\n  // file, so the flag is up before the drawer's first sync. Not the URL any more (4 Oct 2026): any ?secret=..&v=..\n  // counted, so a stale or invalid link, or a failed final add (finish() kept the params), blocked the pair and\n  // tier gifts and swept an _aov_gift line the Function would still have freed.\n  function cdSecretFlowLive() {\n    return window.apSecretFlowLive === true;\n  }\n  // a secret-set cart: mid-flow, or marked with the set signature line in it (the Function prices the set on its\n  // own rule and switches the spend tiers off for it, so the drawer adds no tier gift there either)\n  function cdSecretSetCart(cart) {\n    if (cdSecretFlowLive()) return true;\n    return !!(cart && cart.items && cart.attributes && cart.attributes._secret_offer &&\n      cart.items.some(function (i) { return (i.properties || {})[PAIR_GIFT_PROP] && SECRET_SIGNATURE[i.handle]; }));\n  }\n  // THE SET AS THE FUNCTION READS IT (4 Oct 2026, live money bug on V): aussiepal-gifts secretActive is _secret_offer =\n  // PALS26, a _secret_bundle it knows, that set's bottles (every 1L / 2L unit counts) and each of its PRICED extras as a\n  // tagged line (the Road Pair's 1L grip, the Big Day Kit's Lunch Pal). While it holds, the Function prices the set and\n  // NO arm rule at all (pairRulesOn, twoLooks, valuePack, the spend tiers), so the drawer must not touch a single line:\n  // V used to skip the block below (its own grips look like a set line) and cut a real Road Pair's two holders to one and\n  // added an ice tray the Function then charged ($174 for the $149 set). Mirrors SECRET_BUNDLES; amounts and handles\n  // must match aussiepal-gifts.\n  // THE SET'S OWN LINES (4 Oct 2026, fix round 2): V's own tagged 1L grips look exactly like the Road Pair's, so leftover\n  // Road Pair attributes on a finished Value Pack read as the set here and in the Function: $174 for a $138 pair, the\n  // drawer frozen. Every line a set adds now carries `_secret_set: duo|lunch` (sections/secret-welcome.liquid itemsFor,\n  // snippets/brand-2026-pair-box.liquid secretSet, snippets/brand-2026-sets-card.liquid), and only a priced extra marked\n  // for this set counts. A cart from before the mark falls back to the set's shape: a Road Pair has 2+ tagged holders\n  // and no tagged tray (a Value Pack has one holder and a tray), a Big Day Kit a tagged Lunch Pal. `extras` is every\n  // extra the Function prices per set (SECRET_BUNDLES), handle -> units.\n  var SECRET_OFFER_KEY = 'PALS26';\n  var SECRET_SET_PROP = '_secret_set';\n  var SECRET_SETS = {\n    duo: { bottles: { '1l': 2 }, priced: ['1l-bottle-silicone-sleeve'],\n           extras: { 'car-cupholder-for-1l-bottle': 2, '1l-bottle-silicone-sleeve': 2 } },\n    lunch: { bottles: { '1l': 1, '2l': 1 }, priced: ['lunchpal'],\n             extras: { 'car-cupholder-for-1l-bottle': 1, 'ice-tray-1l-2l-size': 1, '1l-bottle-silicone-sleeve': 1, '2l-bottle-silicone-sleeve': 1, 'lunchpal': 1 } }\n  };\n  // a cart made since the mark shipped: some line carries it\n  function cdSecretMarked(cart) {\n    return cart.items.some(function (i) { return !!(i.properties || {})[SECRET_SET_PROP]; });\n  }\n  function cdTaggedUnits(cart, handle) {\n    return cart.items.reduce(function (n, i) { return n + ((i.properties || {})[PAIR_GIFT_PROP] && i.handle === handle ? i.quantity : 0); }, 0);\n  }\n  function cdSecretActive(cart) {\n    var a = (cart && cart.attributes) || {}, set = a._secret_bundle;\n    var spec = a._secret_offer === SECRET_OFFER_KEY && Object.prototype.hasOwnProperty.call(SECRET_SETS, set) ? SECRET_SETS[set] : null;\n    if (!spec || !cart.items) return false;\n    var units = {};\n    cart.items.forEach(function (i) { if (i.handle === '1l' || i.handle === '2l') units[i.handle] = (units[i.handle] || 0) + i.quantity; });\n    if (!Object.keys(spec.bottles).every(function (h) { return (units[h] || 0) >= spec.bottles[h]; })) return false;\n    var marked = cdSecretMarked(cart);\n    var priced = spec.priced.every(function (h) {\n      return cart.items.some(function (i) { var p = i.properties || {}; return p[PAIR_GIFT_PROP] && i.handle === h && (!marked || p[SECRET_SET_PROP] === set); });\n    });\n    if (!priced) return false;\n    return marked || set !== 'duo' || (cdTaggedUnits(cart, PAIR_HOLDER_HANDLE) >= 2 && cdTaggedUnits(cart, PAIR_TRAY_HANDLE) === 0);\n  }\n  // a tagged line the set itself prices (drawer copy): marked for this set, or any tagged line in a set from before the mark\n  // and the line must carry a cut: an extra over the set's units is charged in full, so it is not 'Free with your pair'\n  function cdSetLine(item, cart) {\n    var p = item.properties || {};\n    var paid = item.final_line_price !== undefined ? item.final_line_price : item.line_price;\n    return !!p[PAIR_GIFT_PROP] && item.original_line_price > paid &&\n      (!cdSecretMarked(cart) || p[SECRET_SET_PROP] === (cart.attributes || {})._secret_bundle);\n  }\n  // Leftover set attributes (4 Oct 2026, fix round 2): on the cart, yet no set the Function will price and no set flow\n  // under way on this page. A Road Pair taken apart, a set page opened and left, or the attributes a set wrote before\n  // its lines went in. Every pair sync clears them in its own write (V's box posts its grips with the bottles, so the\n  // drawer often has nothing left to add, and the old clear only ran beside an add), and reads the cart as it will be\n  // once they are gone.\n  var SECRET_CLEAR = { _secret_offer: '', _secret_bundle: '' };\n  function cdSecretStale(cart) {\n    var a = (cart && cart.attributes) || {};\n    return !!(a._secret_offer || a._secret_bundle) && !cdSecretFlowLive() && !cdSecretActive(cart);\n  }\n  function cdSecretCleared(cart) {\n    if (!cdSecretStale(cart)) return cart;\n    var out = {}, attrs = {};\n    Object.keys(cart).forEach(function (k) { out[k] = cart[k]; });\n    Object.keys(cart.attributes).forEach(function (k) { if (!(k in SECRET_CLEAR)) attrs[k] = cart.attributes[k]; });\n    out.attributes = attrs;\n    return out;\n  }\n  // a finished set the Function prices, outside a set flow and a B2B account: the drawer takes out what is not the set's\n  function cdSecretSetTrim(cart) {\n    return !window.b2bCompanyName && !cdSecretFlowLive() && cdSecretActive(cart);\n  }\n  // The tagged lines a finished set may not keep (4 Oct 2026, fix round 2). While the Function prices the set it frees\n  // only the set's own extras and runs no arm rule, so any other tagged line is charged in full: V's box grips beside a\n  // Road Pair were $12 each under 'Free with your pair' ($311 for $287), and a Value Pack from before the set kept its\n  // tray at $25. Marked carts: every tagged line without a set mark goes (one marked for the other set stays, it is the\n  // customer's and shows at its price). Before the mark: each extra is trimmed to the set's own units, oldest lines\n  // first (Shopify lists the newest first), and any other tagged handle goes.\n  // Marked extras over the set's units (5 Oct 2026, last gate): the Function prices only the set's own units, so a\n  // second marked Lunch Pal or grip (a colour swap whose old line stayed) was charged in full. Each extra marked for\n  // this set is trimmed to the set's units too, keeping the NEWEST lines, so the customer's latest pick survives.\n  function secretSetRemovals(cart) {\n    var set = cart.attributes._secret_bundle, updates = {}, spec = SECRET_SETS[set];\n    var tagged = cart.items.filter(function (i) { return (i.properties || {})[PAIR_GIFT_PROP]; });\n    if (cdSecretMarked(cart)) {\n      var room = {};\n      Object.keys(spec.extras).forEach(function (h) { room[h] = spec.extras[h]; });\n      tagged.forEach(function (i) {\n        var mark = (i.properties || {})[SECRET_SET_PROP];\n        if (!mark) { updates[i.key] = 0; return; }\n        if (mark !== set) return;\n        var keep = Math.min(i.quantity, room[i.handle] || 0);\n        if (keep < i.quantity) updates[i.key] = keep;\n        room[i.handle] = (room[i.handle] || 0) - keep;\n      });\n      return updates;\n    }\n    var left = {};\n    Object.keys(spec.extras).forEach(function (h) { left[h] = spec.extras[h]; });\n    tagged.slice().reverse().forEach(function (i) {\n      var keep = Math.min(i.quantity, left[i.handle] || 0);\n      if (keep < i.quantity) updates[i.key] = keep;\n      if (left[i.handle]) left[i.handle] -= keep;\n    });\n    return updates;\n  }\n  function pairCartBlocked(cart) {\n    if (window.b2bCompanyName || cdSecretFlowLive() || cdSecretActive(cart)) return true;\n    // the arms that give tagged grips of their own (F's kit, L's second looks, V's Value Pack) would block themselves on\n    // the wider rule below, so for them only the exact set above counts\n    if (cart.attributes && cart.attributes._secret_offer && pairGiftMode() !== 'kit' && pairGiftMode() !== 'twoLooks' && pairGiftMode() !== 'valuePack' &&\n        cart.items.some(function (i) { return (i.properties || {})[PAIR_GIFT_PROP] && SECRET_SIGNATURE[i.handle]; })) return true;\n    return cart.items.some(function (i) {\n      var props = i.properties || {};\n      return props._cobrand || Object.keys(props).some(function (k) { return k.indexOf('B2B ') === 0; });\n    });\n  }\n  // Co-brand and logged-in B2B carts get NO pair gifts or L grips: the gift Function switches the pair rule off\n  // for them (cobrandCart / b2bCart), so a tagged holder, tray, lid or grip already in the cart would be charged.\n  // Remove them rather than only stop adding (secret-set carts keep theirs; the Function prices those).\n  function pairGiftStripAll(cart) {\n    return !!((window.b2bCompanyName || cdTierFreeCart(cart)) && !(cart.attributes && cart.attributes._secret_offer));\n  }\n  // The tagged pair-gift lines this cart may not keep under the current arm, as /cart/update.js `updates`\n  // (0 = remove, n = trim to n units). The drawer adds what is missing on top (syncPairGiftWith); the /cart\n  // page applies only these (cdGiftRemovals).\n  function pairGiftRemovals(cart) {\n    var updates = {};\n    cart = cdSecretCleared(cart);\n    if (pairGiftStripAll(cart)) {\n      cart.items.forEach(function (i) { if ((i.properties || {})[PAIR_GIFT_PROP]) updates[i.key] = 0; });\n      return updates;\n    }\n    if (cdSecretSetTrim(cart)) return secretSetRemovals(cart);\n    return pairCartBlocked(cart) ? updates : pairGiftPlan(cart).updates;\n  }\n  // Always work from a FRESH cart: Shopify re-merges or re-splits gift lines as\n  // discounts come and go, so keys in the snapshot the drawer holds can be stale.\n  // A stale key on update.js is a 404, and one 404 used to switch the sync off\n  // for the rest of the page. Now the fail flag clears itself after 8 seconds.\n  function syncPairGift(cart) {\n    if (cdPairSyncing || cdPairFailed) return Promise.resolve(null);\n    var view = cdSecretCleared(cart), clearSecret = view !== cart;\n    if (pairGiftStripAll(view)) {\n      var strip = pairGiftRemovals(view);\n      if (!Object.keys(strip).length && !clearSecret) return Promise.resolve(null);\n      cdPairSyncing = true;\n      var body = { updates: strip };\n      if (clearSecret) body.attributes = SECRET_CLEAR;\n      return fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })\n        .then(function () { return cdFetchCart().then(function (r) { return r.json(); }); })\n        .catch(function () { return null; })\n        .then(function (c) { cdPairSyncing = false; return c; });\n    }\n    // nothing to write: a B2B account, a set flow under way, or a cart no arm may touch (co-brand)\n    if (pairCartBlocked(view) && !clearSecret && !cdSecretSetTrim(view)) return Promise.resolve(null);\n    cdPairSyncing = true;\n    return cdFetchCart().then(function (r) { return r.json(); })\n      .then(function (fresh) { cdPairSyncing = false; return syncPairGiftWith(fresh); })\n      .catch(function () { cdPairSyncing = false; return null; });\n  }\n  // The current arm's pair rule on this cart, without writing: how many tagged units of each gift it wants, how\n  // many are there, and the `updates` that remove every tagged line it does not give and trim units over what it\n  // gives. Callers check pairCartBlocked first.\n  function pairGiftPlan(cart) {\n    var b = pairBottleUnits(cart);\n    var tagged = cart.items.filter(function (i) { return (i.properties || {})[PAIR_GIFT_PROP]; });\n    // how many tagged units of each gift the cart should hold, per bucket\n    var mode = pairGiftMode();\n    var want = {};\n    if (mode === 'kit') {\n      want[PAIR_KIT_GRIP['1l']] = b.paired1L; want[PAIR_KIT_GRIP['2l']] = b.paired2L; want[PAIR_KIT_LID] = b.paired1L + b.paired2L;\n    } else if (mode === 'engrave') {\n      // engraving is freed on the surcharge lines themselves; three bottles also earn a tray, one per three (Kegan, 20 Sep)\n      want[PAIR_TRAY_HANDLE] = Math.floor(b.units / 3);\n    } else if (mode === 'none' || mode === 'names') {\n      // bucket A and P (the 20%, or P's $19 pair price, sit on the bottle lines): no gift line.\n      // N: the free names are the surcharge lines themselves (the Function frees one per bottle): no gift line\n    } else if (mode === 'valuePack') {\n      // V: the Value Pack (valuePackDue). A gift that has sold out is wanted only up to what the cart already holds,\n      // so the drawer never retries an add Shopify refuses and never trims one that is already there\n      cdPrimeGiftStock();\n      var vp = valuePackDue(b);\n      Object.keys(vp).forEach(function (h) {\n        var inCart = 0;\n        tagged.forEach(function (i) { if (i.handle === h) inCart += i.quantity; });\n        want[h] = cdGiftOk[h] === false ? Math.min(vp[h], inCart) : vp[h];\n      });\n    } else if (mode === 'tray') {\n      // bucket H (24 Sep): every pair earns the ice tray, 1L pairs included, never a holder\n      want[PAIR_TRAY_HANDLE] = b.pairs;\n    } else if (mode === 'trayOnce') {\n      // buckets H and K (28 Sep): ONE ice tray per order once there are 2+ bottles; the Function frees one tray only\n      want[PAIR_TRAY_HANDLE] = b.units >= 2 ? 1 : 0;\n    } else if (isOneGiftMode(mode)) {\n      // J and L (1 Oct): ONE gift at 2+ bottles. A gift already in the cart that the order may still have\n      // is kept (no swapping a tray for a holder mid-visit); otherwise the first one in stock is added\n      if (b.units >= 2) {\n        var allowed = oneGiftOrder(b, mode);\n        var kept = tagged.filter(function (i) { return allowed.indexOf(i.handle) >= 0; })[0];\n        want[kept ? kept.handle : oneGiftHandle(b, mode)] = 1;\n      }\n      if (mode === 'twoLooks') {\n        // L: a free second-colour grip for every paid bottle, size for size\n        want[PAIR_KIT_GRIP['1l']] = b.ones; want[PAIR_KIT_GRIP['2l']] = b.twos;\n      }\n    } else {\n      want[PAIR_HOLDER_HANDLE] = b.holders; want[PAIR_TRAY_HANDLE] = b.trays;\n    }\n    var giftHandlesNow = Object.keys(want);\n    // Count UNITS per gift, not lines: Shopify can hand a qty-2 gift back as two\n    // lines with different keys (a native discount splitting the discounted unit\n    // off), and treating that as a duplicate made the drawer loop on update.js.\n    var have = {}; giftHandlesNow.forEach(function (h) { have[h] = 0; });\n    tagged.forEach(function (i) { if (have[i.handle] !== undefined) have[i.handle] += i.quantity; });\n    var updates = {}, dirty = false;\n    tagged.forEach(function (i) {\n      // a tagged line that is not a gift this bucket gives is removed, so a\n      // visitor who changes bucket never keeps the old bucket's gift. A secret set\n      // is left alone: the Function prices those lines. Only a set the Function\n      // really reads (cdSecretActive), not its leftover attributes (4 Oct 2026): those\n      // outlive the set, and V's own grips keep them alive, so a V cart taken down to\n      // one bottle kept its whole pack, every line of it charged\n      if (have[i.handle] === undefined && !cdSecretActive(cart)) { updates[i.key] = 0; dirty = true; }\n    });\n    giftHandlesNow.forEach(function (h) {\n      var due = want[h] || 0, got = have[h] || 0;\n      if (got <= due) return;\n      // trim from the last lines down until the units match\n      var excess = got - due;\n      tagged.filter(function (i) { return i.handle === h; }).reverse().forEach(function (i) {\n        if (excess <= 0) return;\n        var cut = Math.min(i.quantity, excess);\n        updates[i.key] = i.quantity - cut; dirty = true; excess -= cut;\n      });\n    });\n    return { b: b, mode: mode, want: want, have: have, updates: updates, dirty: dirty };\n  }\n  function syncPairGiftWith(cart) {\n    if (cdPairSyncing || cdPairFailed) return Promise.resolve(null);\n    // leftover set attributes go in this sync's own write, whatever else it does (see cdSecretStale)\n    var clearSecret = cdSecretStale(cart);\n    if (clearSecret) cart = cdSecretCleared(cart);\n    if (cdSecretSetTrim(cart)) {\n      var setUpdates = secretSetRemovals(cart);\n      return Object.keys(setUpdates).length ? pairGiftWrite(setUpdates, false, [], [], 'set', {}) : Promise.resolve(null);\n    }\n    if (pairCartBlocked(cart)) return clearSecret ? pairGiftWrite({}, true, [], [], pairGiftMode(), {}) : Promise.resolve(null);\n    var plan = pairGiftPlan(cart), b = plan.b, mode = plan.mode, want = plan.want, have = plan.have;\n    var updates = plan.updates, dirty = plan.dirty, adds = [];\n    // Kit gifts follow the bottle colours, one add per colour (the picker in the\n    // drawer swaps any of them afterwards). Holder and tray have one variant.\n    function kitAddsFor(h, due) {\n      var colours = h === PAIR_KIT_GRIP['1l'] ? b.colours['1l'].slice(0, b.paired1L)\n                  : h === PAIR_KIT_GRIP['2l'] ? b.colours['2l'].slice(0, b.paired2L)\n                  : b.colours['1l'].slice(0, b.paired1L).concat(b.colours['2l'].slice(0, b.paired2L));\n      // the units already in the cart cover the first colours; add for the rest\n      colours = colours.slice(colours.length - due);\n      return Promise.all(colours.map(function (c) { return cdVariantFor(h, c); })).then(function (vs) {\n        var byId = {};\n        vs.forEach(function (v) { if (v) byId[v.id] = (byId[v.id] || 0) + 1; });\n        return Object.keys(byId).map(function (id) { return { id: parseInt(id, 10), quantity: byId[id] }; });\n      });\n    }\n    // L: the grips the box did not already add come in each bottle's default second colour; J/L's\n    // fallback Smart Lid comes in the first bottle's colour (the drawer's picker swaps either)\n    function twoLooksAddsFor(h, due) {\n      var size = h === PAIR_KIT_GRIP['2l'] ? '2l' : '1l';\n      // V: the two grips belong to the first bottles of their size, the ones the bundle box shows them on\n      var bottleColours = mode === 'valuePack' ? b.colours[size].slice(0, want[h] || 0) : b.colours[size];\n      // the free stubby always starts in Plum (Kegan 2 Oct), changeable in the cart; any in-stock colour if Plum runs out\n      var colours = h === PAIR_STUBBY_HANDLE ? ['Plum'] : h === PAIR_KIT_LID ? [b.colours['1l'].concat(b.colours['2l'])[0]]\n                  : bottleColours.map(function (c) { return twoLooksGrip(size, c); });\n      colours = colours.slice(Math.max(0, colours.length - due));\n      return Promise.all(colours.map(function (c) { return cdVariantFor(h, c); })).then(function (vs) {\n        var byId = {};\n        vs.forEach(function (v) { if (v) byId[v.id] = (byId[v.id] || 0) + 1; });\n        return Object.keys(byId).map(function (id) { return { id: parseInt(id, 10), quantity: byId[id] }; });\n      });\n    }\n    var kitAdds = [];\n    Object.keys(want).forEach(function (h) {\n      var due = want[h] || 0, got = have[h] || 0;\n      if (got < due) {\n        if (mode === 'kit') kitAdds.push(kitAddsFor(h, due - got));\n        else if (h === PAIR_KIT_LID || h === PAIR_STUBBY_HANDLE || h === PAIR_KIT_GRIP['1l'] || h === PAIR_KIT_GRIP['2l']) kitAdds.push(twoLooksAddsFor(h, due - got));\n        else adds.push({ id: h === PAIR_HOLDER_HANDLE ? PAIR_HOLDER_VID : PAIR_TRAY_VID, quantity: due - got });\n      }\n      // units over what the arm gives are trimmed in pairGiftPlan's updates\n    });\n    if (!dirty && !adds.length && !kitAdds.length && !clearSecret) return Promise.resolve(null);\n    // the clear goes in the same write as the removals, before the gift lines go in: with the attributes still on, this\n    // arm's own tagged grips could complete a set's signature and the Function would price the set, not the arm\n    return pairGiftWrite(updates, clearSecret, adds, kitAdds, mode, want);\n  }\n  // One pair sync's writes, serially: the removals and the set clear in one /cart/update.js, then the adds in one\n  // /cart/add.js. Resolves to the fresh cart when anything was written, else null.\n  function pairGiftWrite(updates, clearSecret, adds, kitAdds, mode, want) {\n    var dirty = Object.keys(updates).length > 0;\n    cdPairSyncing = true;\n    var p = Promise.resolve();\n    if (dirty || clearSecret) {\n      p = p.then(function () {\n        var body = {};\n        if (dirty) body.updates = updates;\n        if (clearSecret) body.attributes = SECRET_CLEAR;\n        return fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })\n          .then(function (r) { if (!r.ok) throw new Error('pair gift update failed'); });\n      });\n    }\n    if (kitAdds.length) {\n      p = p.then(function () { return Promise.all(kitAdds); }).then(function (groups) {\n        groups.forEach(function (g) { g.forEach(function (a) { adds.push(a); }); });\n      });\n    }\n    if (adds.length || kitAdds.length) {\n      p = p.then(function () {\n        if (!adds.length) return;\n        var props = {}; props[PAIR_GIFT_PROP] = 'yes';\n        var items = adds.map(function (a) { return { id: a.id, quantity: a.quantity, properties: props }; });\n        return fetch('/cart/add.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ items: items }) })\n          .then(function (r) { if (!r.ok) throw new Error('pair gift add failed'); });\n      });\n    }\n    // a colour lookup that found nothing in stock adds nothing: with nothing written either, report no change, or the\n    // drawer would repaint and sync again for ever\n    return p.then(function () { return (dirty || clearSecret || adds.length) ? cdFetchCart().then(function (r) { return r.json(); }) : null; })\n      .catch(function () {\n        // J / L: a refused tray or holder add is almost always that gift selling out mid-visit, so the\n        // retry after the cool-off picks the next gift in the order instead of trying the same one again\n        if (isOneGiftMode(mode)) adds.forEach(function (a) { if (a.id === PAIR_TRAY_VID) cdGiftOk[PAIR_TRAY_HANDLE] = false; if (a.id === PAIR_HOLDER_VID) cdGiftOk[PAIR_HOLDER_HANDLE] = false; });\n        if (isOneGiftMode(mode) && want[PAIR_STUBBY_HANDLE]) cdGiftOk[PAIR_STUBBY_HANDLE] = false;\n        // V: the add is one atomic request, so which gift ran out is not known; ask the store again for each one wanted,\n        // and the retry after the cool-off skips whatever is now out (valuePackDue never swaps it for another gift)\n        if (mode === 'valuePack') cdRecheckGiftStock(Object.keys(want));\n        cdPairFailed = true; setTimeout(function () { cdPairFailed = false; }, 8000); return null;\n      })\n      .then(function (c) { cdPairSyncing = false; return c; });\n  }\n\n  // ---- Jug kit lines are pinned to the jugs (Kegan, 15 Sep 2026) ----\n  // The 4L/6L \"Add the kit\" adds a sling and a tray tagged `_jug_bundle: yes`.\n  // Order #239504 shipped with two kit slings for one jug; #239511 and #238703\n  // had two and four kit trays. Whatever the path (a second tap, the sticky bar,\n  // the personalise button, a quantity stepper), a kit line may never hold more\n  // units than there are jugs to wear it: tagged sling units are capped at the\n  // jugs of that size, tagged trays at the jugs in total, and kit lines with no\n  // jug left are removed. It only trims, never adds: the kit stays opt-in.\n  var JUG_KIT_SLING = { 'insulated-water-jug-3-8l': '4l-hydro-jug-bottle-sling-black', 'insulated-hydro-jug-6l': '6l-hydro-jug-bottle-sling' };\n  var JUG_KIT_TRAY = 'silicon-ice-mold-aqua';\n  var JUG_KIT_PROP = '_jug_bundle';\n  var cdKitSyncing = false, cdKitFailed = false;\n  function syncJugKit(cart) {\n    if (cdKitSyncing || cdKitFailed) return Promise.resolve(null);\n    var tagged = cart.items.filter(function (i) { return (i.properties || {})[JUG_KIT_PROP]; });\n    if (!tagged.length) return Promise.resolve(null);\n    var jugs = {}, jugsTotal = 0;\n    cart.items.forEach(function (i) { if (JUG_KIT_SLING[i.handle]) { jugs[i.handle] = (jugs[i.handle] || 0) + i.quantity; jugsTotal += i.quantity; } });\n    var allowed = {};\n    Object.keys(JUG_KIT_SLING).forEach(function (jug) { allowed[JUG_KIT_SLING[jug]] = jugs[jug] || 0; });\n    allowed[JUG_KIT_TRAY] = jugsTotal;\n    var have = {};\n    tagged.forEach(function (i) { have[i.handle] = (have[i.handle] || 0) + i.quantity; });\n    var updates = {}, dirty = false;\n    Object.keys(have).forEach(function (h) {\n      var cap = allowed[h] === undefined ? have[h] : allowed[h];   // an unknown tagged handle is left alone\n      var excess = have[h] - cap;\n      if (excess <= 0) return;\n      tagged.filter(function (i) { return i.handle === h; }).reverse().forEach(function (i) {\n        if (excess <= 0) return;\n        var cut = Math.min(i.quantity, excess);\n        updates[i.key] = i.quantity - cut; dirty = true; excess -= cut;\n      });\n    });\n    if (!dirty) return Promise.resolve(null);\n    cdKitSyncing = true;\n    return fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ updates: updates }) })\n      .then(function (r) { if (!r.ok) throw new Error('kit trim failed'); return cdFetchCart().then(function (x) { return x.json(); }); })\n      .catch(function () { cdKitFailed = true; setTimeout(function () { cdKitFailed = false; }, 8000); return null; })\n      .then(function (c) { cdKitSyncing = false; return c; });\n  }\n\n  // BLACK FRIDAY DUO PACKS (10 to 17 Nov 2026, assets/pdp-v3.js): a Duo posts its 2 bottles as plain lines and 2 ice trays\n  // + 2 extra grips tagged _bf_duo = its size ('1l' / '2l'); the gift Function prices the set. Like the jug kit, the\n  // drawer only ever trims: tagged lines of a size are capped at 2 trays and 2 grips per 2 bottles of that size in the\n  // cart (engraved bottles count), and every tagged line comes out once Duo week is over (window.AP_BF, the schedule)\n  // or on a B2B / co-brand cart. A bottle removed in the drawer takes its Duo's gear with it, never charged.\n  var DUO_PROP = '_bf_duo', DUO_TRAY = 'ice-tray-1l-2l-size';\n  var cdDuoSyncing = false, cdDuoFailed = false;\n  function duoPlan(cart, strip) {\n    var tagged = (cart.items || []).filter(function (i) { return (i.properties || {})[DUO_PROP]; }), updates = {}, dirty = false;\n    if (!tagged.length) return { updates: updates, dirty: false };\n    var bf = window.AP_BF, weekOff = !!(bf && typeof bf.on === 'function' && !bf.on('duo'));\n    var bottles = { '1l': 0, '2l': 0 };\n    cart.items.forEach(function (i) { var p = i.properties || {}; if (bottles.hasOwnProperty(i.handle) && !p[DUO_PROP] && !p[GIFT_PROP] && !p[PAIR_GIFT_PROP] && !p._cooler_gift) bottles[i.handle] += i.quantity; });\n    ['1l', '2l'].forEach(function (z) {\n      var sets = strip || weekOff ? 0 : Math.floor(bottles[z] / 2);\n      [true, false].forEach(function (isTray) {\n        var lines = tagged.filter(function (i) { return i.properties[DUO_PROP] === z && (i.handle === DUO_TRAY) === isTray; });\n        var excess = lines.reduce(function (n, i) { return n + i.quantity; }, 0) - 2 * sets;\n        lines.slice().reverse().forEach(function (i) { if (excess <= 0) return; var cut = Math.min(i.quantity, excess); updates[i.key] = i.quantity - cut; dirty = true; excess -= cut; });\n      });\n    });\n    // a tag that names no size we sell is never ours to keep\n    tagged.forEach(function (i) { if (i.properties[DUO_PROP] !== '1l' && i.properties[DUO_PROP] !== '2l') { updates[i.key] = 0; dirty = true; } });\n    return { updates: updates, dirty: dirty };\n  }\n  function syncDuo(cart) {\n    if (cdDuoSyncing || cdDuoFailed) return Promise.resolve(null);\n    var plan = duoPlan(cart, !!(window.b2bCompanyName || cdTierFreeCart(cart)));\n    if (!plan.dirty) return Promise.resolve(null);\n    cdDuoSyncing = true;\n    return fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ updates: plan.updates }) })\n      .then(function (r) { if (!r.ok) throw new Error('duo trim failed'); return cdFetchCart().then(function (x) { return x.json(); }); })\n      .catch(function () { cdDuoFailed = true; setTimeout(function () { cdDuoFailed = false; }, 8000); return null; })\n      .then(function (c) { cdDuoSyncing = false; return c; });\n  }\n\n  // Cooler Bag Week (BF, 19 Nov 9am to 27 Nov 9am QLD; Kegan 17/18 Oct: \"any cooler bag\", the RidePal 6L too). A paid\n  // cooler bag earns ONE free 1L on top of the $165 one, two free bottles at most: the gift Function (coolerOn) frees the\n  // `_cooler_gift` 1L. The drawer adds that line (a 1L colour not already in the cart, never a hidden one), keeps it at\n  // one (two for a RidePal under coolerTwo, below), and takes it out when no paid bag is left, the week ends, or the\n  // cart is B2B / co-brand / a secret set. Bucket A's coolerGift flag gates it, with the Function deploy that prices it. A colour swap holds cdPairSyncing (the\n  // swapGiftVariant pair path), so this waits for it rather than trimming the swap's second line.\n  var COOLER_BAGS = { 'booze-bag-15l': 1, '20l': 1, 'backpack-pal': 1, 'the-booze-bag-35l-grey-with-valve-backpack': 1, 'bundaberg-rum-cooler-backpack-35l': 1, 'insulated-ridepal-6l-cooler-bag': 1, 'lunchpal': 1 };   /* Lunch PAL joined 4 Nov 2026 (Kegan); the gift Function's COOLER_BAGS must match */\n  var cdCoolerSyncing = false, cdCoolerFailed = false;\n  function coolerOn(cart) {\n    var bf = window.AP_BF, r = window.cdOfferTest || {};\n    return !!(r.coolerGift && bf && typeof bf.on === 'function' && bf.on('cooler_week') && !window.b2bCompanyName && !cdTierFreeCart(cart) && !cdSecretSetCart(cart));\n  }\n  // RidePal 2 free (Kegan 21 Oct 2026): with bucket A's coolerTwo flag a paid RidePal 6L keeps TWO `_cooler_gift` 1Ls,\n  // while no $165 gift is in the cart (two free 1Ls per order at most). The flag goes on with the gift Function deploy that\n  // frees the second one (03 specs it); off, every cooler bag keeps one. assets/pdp-v3-cooler.js reads the same flag.\n  function coolerKeep(cart) {\n    if (!(window.cdOfferTest || {}).coolerTwo) return 1;\n    var items = cart.items || [];\n    var ride = items.some(function (i) { var p = i.properties || {}; return i.handle === 'insulated-ridepal-6l-cooler-bag' && !p[GIFT_PROP] && !p[PAIR_GIFT_PROP] && !p[COOLER_PROP] && i.original_line_price > 0; });\n    return ride && !items.some(function (i) { return (i.properties || {})[GIFT_PROP]; }) ? 2 : 1;\n  }\n  function coolerPlan(cart, on) {\n    var items = cart.items || [], updates = {}, dirty = false, kept = 0, keep = on ? coolerKeep(cart) : 1;\n    var bag = !!on && items.some(function (i) { var p = i.properties || {}; return COOLER_BAGS[i.handle] && !p[GIFT_PROP] && !p[PAIR_GIFT_PROP] && !p[COOLER_PROP] && i.original_line_price > 0; });\n    // A personalised free 1L (its own _cust_id, 3 Nov 2026) is kept first, so its plain twin goes, and whenever it is\n    // removed its engraving lines (same _cust_id) go with it\n    var engOf = {}, engFirst = function (i) { return (i.properties || {})._cust_id ? 0 : 1; };\n    items.forEach(function (i) { var c = (i.properties || {})._cust_id; if (c && (i.properties || {})['_Customised Product']) (engOf[c] = engOf[c] || []).push(i); });\n    items.slice().sort(function (a, b) { return engFirst(a) - engFirst(b); }).forEach(function (i) {\n      if (!(i.properties || {})[COOLER_PROP]) return;\n      if (bag && kept < keep && i.handle === '1l') { var q = Math.min(i.quantity, keep - kept); kept += q; if (i.quantity !== q) { updates[i.key] = q; dirty = true; } return; }\n      updates[i.key] = 0; dirty = true;\n      (engOf[(i.properties || {})._cust_id] || []).forEach(function (e) { updates[e.key] = 0; });\n    });\n    return { updates: updates, dirty: dirty, add: bag && kept < keep, bag: bag };\n  }\n  /* a free bottle's starting colour (Kegan 4 Nov): Seabreeze Layers, a slow seller to phase out, then Seabreeze, then the\n     first in admin order; other gift products keep their first colour. The customer can still change it in the drawer. */\n  function freeFirst(vs, handle) {\n    vs = vs || [];\n    if (handle === '1l' || handle === '2l') {\n      for (var n = 0, NAMES = ['seabreeze layers', 'seabreeze']; n < NAMES.length; n++) {\n        for (var k = 0; k < vs.length; k++) { if (String(vs[k].title).trim().toLowerCase() === NAMES[n]) { return vs[k]; } }\n      }\n    }\n    return vs[0];\n  }\n  function syncCooler(cart) {\n    if (cdCoolerSyncing || cdCoolerFailed || cdPairSyncing || cdGiftSyncing) return Promise.resolve(null);\n    var plan = coolerPlan(cart, coolerOn(cart));\n    // Remove on the free 1L opts out until the bag leaves the cart (as a tier gift's cdGiftOptOut), so it never bounces back\n    if (!plan.bag && cdGiftOptOut.cooler) { delete cdGiftOptOut.cooler; saveGiftOptOut(); }\n    if (cdGiftOptOut.cooler) plan.add = false;\n    if (!plan.dirty && !plan.add) return Promise.resolve(null);\n    cdCoolerSyncing = true;\n    var post = function (url, body) { return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }).then(function (r) { if (!r.ok) throw new Error('cooler gift ' + url); }); };\n    var p = plan.dirty ? post('/cart/update.js', { updates: plan.updates }) : Promise.resolve();\n    if (plan.add) {\n      p = p.then(function () { return fetchGiftProduct('1l'); }).then(function (prod) {\n        var block = (window.cdGiftVariantBlock || {})['1l'], used = {};\n        (cart.items || []).forEach(function (i) { if (i.handle === '1l') used[i.variant_id] = 1; });\n        var ok = ((prod && prod.variants) || []).filter(function (v) { return v.available && !(block && block.test(String(v.title))); });\n        var v = freeFirst(ok.filter(function (x) { return !used[x.id]; }), '1l') || ok[0], props = {};\n        if (!v) throw new Error('no 1L for the cooler gift');\n        props[COOLER_PROP] = 'yes'; props._source = 'cooler-gift';\n        return post('/cart/add.js', { items: [{ id: v.id, quantity: 1, properties: props }] });\n      });\n    }\n    return p.then(function () { return cdFetchCart().then(function (x) { return x.json(); }); })\n      .catch(function () { cdCoolerFailed = true; setTimeout(function () { cdCoolerFailed = false; }, 8000); return null; })\n      .then(function (c) { cdCoolerSyncing = false; return c; });\n  }\n\n  // What syncGiftTiers changes in this cart, without writing: { updates, dirty, adds }. The /cart page applies only\n  // its removals (cdGiftRemovals); the drawer also adds the gifts in `adds`.\n  function giftTierPlan(cart) {\n    // a co-brand / B2B cart has no tiers, so the sweep below also removes a gift added before the co-brand item went in.\n    // Nor does a secret-set cart (the Function's tiers are off when secretActive): no free 1L / Lunch Pal to charge.\n    var tiers = (cdTierFreeCart(cart) || cdSecretSetCart(cart)) ? [] : activeGiftTiers();\n\n    var qual = giftQualifyingTotal(cart);\n    var adds = [], updates = {}, dirty = false;\n\n    // Sweep pass: remove orphaned gift lines (tier disabled or threshold edited\n    // since the line was added, another arm's gift: see cdTierFor) and duplicate\n    // lines for the same tier. Runs even with zero tiers configured \u2014 a stale gift\n    // must never reach checkout at full price. keptLine holds the single surviving line per tier.\n    // A personalised free bottle (its own _cust_id, Kegan 21 Oct 2026) is the one kept for its tier, so its\n    // plain twin goes, and whenever it is removed its engraving lines (same _cust_id) go with it.\n    var keptLine = {}, engOf = {};\n    cart.items.forEach(function (i) { var c = (i.properties || {})['_cust_id']; if (c && (i.properties || {})['_Customised Product']) (engOf[c] = engOf[c] || []).push(i); });\n    var drop = function (i) {\n      updates[i.key] = 0; dirty = true;\n      (engOf[(i.properties || {})['_cust_id']] || []).forEach(function (e) { updates[e.key] = 0; });\n    };\n    var engFirst = function (i) { return (i.properties || {})['_cust_id'] ? 0 : 1; };\n    cart.items.slice().sort(function (a, b) { return engFirst(a) - engFirst(b); }).forEach(function (i) {\n      var t = (i.properties || {})[GIFT_PROP];\n      if (!t) return;\n      if (!cdTierFor(i, tiers) || keptLine[t]) { drop(i); return; }\n      keptLine[t] = i;\n    });\n\n    tiers.forEach(function (t) {\n      var key = String(t.target);\n      var line = keptLine[key];\n      if ((t.basis === 'bottles' ? giftQualifyingBottles(cart) : qual) >= t.target) {\n        if (!line && !cdGiftOptOut[key] && !cdGiftFailed[key]) adds.push(t);\n        // Gift is always qty 1 \u2014 clamp anything else\n        if (line && line.quantity > 1) { updates[line.key] = 1; dirty = true; }\n      } else {\n        if (cdGiftOptOut[key]) { delete cdGiftOptOut[key]; saveGiftOptOut(); } // dropping below re-arms the tier\n        if (line) drop(line);\n      }\n    });\n    return { updates: updates, dirty: dirty, adds: adds };\n  }\n\n  // The gift lines this cart may not keep under the current arm, as /cart/update.js `updates`: tier gifts it does\n  // not free, then pair gifts it does not give, by the drawer's own rules. Removals only, never an add. Used by the\n  // /cart page (cleanupGiftLines) and after an arm change (cdDropOldArmGifts); the drawer's syncs add on top.\n  function cdGiftRemovals(cart) {\n    var updates = giftTierPlan(cart).updates, pair = pairGiftRemovals(cart), duo = duoPlan(cart, !!(window.b2bCompanyName || cdTierFreeCart(cart))).updates, cool = coolerPlan(cart, coolerOn(cart)).updates;\n    Object.keys(pair).forEach(function (k) { if (!(k in updates)) updates[k] = pair[k]; });\n    Object.keys(duo).forEach(function (k) { if (!(k in updates)) updates[k] = duo[k]; });\n    Object.keys(cool).forEach(function (k) { if (!(k in updates)) updates[k] = cool[k]; });\n    return updates;\n  }\n\n  // An arm change (a redraw like L / M to J on 4 Oct, an expired pin, the October switch-off) leaves the old arm's\n  // gifts in the cart, charged, until the drawer opens; a Buy-now never opens it. The bucket snippet writes the new\n  // arm to the cart and then fires 'ap:offerarm'. One fresh /cart.js read (the snippet's copy predates its own\n  // write, and the Function re-prices on the new arm, which can re-split lines and change their keys), then one\n  // write, only when something must go. Removals only: an add here would pop the drawer open on page load\n  // (patchCartAdd); the new arm's gifts are added when the drawer next opens, as for any visitor. Skipped while a\n  // drawer sync is writing (that sync reconciles the same lines).\n  function cdDropOldArmGifts() {\n    if (cdGiftSyncing || cdPairSyncing) return Promise.resolve(null);\n    cdGiftSyncing = true; cdPairSyncing = true;\n    return cdFetchCart().then(function (r) { return r.json(); })\n      .then(function (cart) {\n        var updates = cart && cart.items ? cdGiftRemovals(cart) : {};\n        if (!Object.keys(updates).length) return null;\n        return fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ updates: updates }) })\n          .then(function (r) { return r.ok ? r.json() : null; });\n      })\n      .catch(function () { return null; })\n      .then(function (c) { cdGiftSyncing = false; cdPairSyncing = false; return c; });\n  }\n\n  function syncGiftTiers(cart) {\n    if (cdGiftSyncing || window.b2bCompanyName) return Promise.resolve(null);\n    var plan = giftTierPlan(cart), adds = plan.adds, updates = plan.updates, dirty = plan.dirty;\n    if (!adds.length && !dirty) return Promise.resolve(null);\n    cdGiftSyncing = true;\n    var p = Promise.resolve();\n    if (dirty) {\n      p = p.then(function () {\n        return fetch('/cart/update.js', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ updates: updates })\n        }).then(function (r) {\n          // A failed update must not loop render\u2194sync \u2014 bail out of this pass\n          if (!r.ok) throw new Error('cart update failed');\n        });\n      });\n    }\n    // Gift adds: look the products up in PARALLEL, then add them in ONE write.\n    //\n    // This used to be read -> write, read -> write, strictly serially. Measured on\n    // 23 Aug with a $207 cart (both tiers): first gift landed at 2.7s and the second\n    // at 3.9s, over 11 requests. Two costs were avoidable:\n    //   - the product lookups (281ms + 215ms) sat INSIDE the serial write chain,\n    //     even though they are plain reads and already memoised in cdGiftProductCache\n    //   - each gift got its own /cart/add.js, and each add costs ~950ms of Shopify's\n    //     own latency\n    //\n    // Batching is NOT the racing the rest of this file guards against: /cart/add.js\n    // takes an items array and applies it atomically, so this is still one serial\n    // write, just carrying both gifts.\n    if (adds.length) {\n      p = p.then(function () {\n        return Promise.all(adds.map(function (t) { return fetchGiftProduct(t.handle); }));\n      }).then(function (prods) {\n        var items = [];\n        var batched = [];\n        adds.forEach(function (t, idx) {\n          var prod = prods[idx];\n          var tBlock = (window.cdGiftVariantBlock || {})[t.handle];\n          var variant = freeFirst(prod && prod.variants && prod.variants.filter(function (v) { return v.available && !(tBlock && tBlock.test(String(v.title))); }), t.handle);\n          if (!variant) { cdGiftFailed[t.target] = true; return; }\n          var props = {};\n          props[GIFT_PROP] = String(t.target);\n          props['_source'] = 'aov-gift';\n          items.push({ id: variant.id, quantity: 1, properties: props });\n          batched.push(t);\n        });\n        if (!items.length) return;\n        return fetch('/cart/add.js', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ items: items })\n        }).then(function (r) {\n          // One request now covers several tiers, so a failure marks all of them.\n          // Coarser than before, and correct: the add is atomic, so none landed.\n          if (!r.ok) batched.forEach(function (t) { cdGiftFailed[t.target] = true; });\n        });\n      });\n    }\n    return p\n      .then(function () { return cdFetchCart(); })\n      .then(function (r) { return r.json(); })\n      .then(function (c) { cdGiftSyncing = false; return c; })\n      .catch(function () { cdGiftSyncing = false; return null; });\n  }\n\n  // \u2500\u2500 /cart STOPS HERE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // The /cart page (top of this file) reuses the gift rules above and never runs the drawer below. Everything\n  // between that block and this line must stay declarations only (vars, functions): no listeners, no DOM, no fetch.\n  if (CD_CART_PAGE) return;\n\n  // Swap the gift line to a different colour: add the new variant first, then\n  // drop the old line (serial \u2014 never parallel cart writes). Re-entrancy guard\n  // stops rapid double-clicks creating duplicate gift lines; if a duplicate\n  // ever slips through anyway, syncGiftTiers' sweep pass removes it.\n  // Pair gifts (4 Oct 2026): the click handler never passed `prop` / `qty`, so a pair gift's new colour went in as an\n  // `_aov_gift: yes` line the tier sweep removed, and the pair sync re-added the old default colour (a V grip picked\n  // in Black came back Pink). Now they keep `_pair_gift`, their units and a set's `_secret_set`, and the pair sync is\n  // held off while both lines are briefly in the cart, so it does not trim the new one.\n  // THE OLD LINE BY A FRESH READ (5 Oct 2026, last gate): the second line of a handle moves the Function's limited\n  // discount (a set's one Lunch Pal, one grip per size, the Road Pair's two grips) to the newer line, and Shopify\n  // re-keys the old one. The change.js on the key read before the add then 400'd unchecked, so the old colour stayed\n  // in the cart at full price under 'Free with your pair' ($308 for a $189 Big Day Kit, $161 for a $149 Road Pair).\n  // Now the old line is found again after the add, by its variant and the same tag (the same set mark, or the same\n  // tier), and its swapped units come out under its key as it is now, retried once on a fresh read if Shopify still\n  // refuses it. Both sync locks stay held until that write settles, so no sync sees the two colours side by side.\n  function swapGiftVariant(oldKey, newVariantId, target, prop, qty, set, oldVariantId) {\n    var pair = !!(prop && prop !== GIFT_PROP);\n    if (cdGiftSyncing || (pair && cdPairSyncing)) return;\n    showItemsLoading(true);\n    cdGiftSyncing = true;\n    if (pair) cdPairSyncing = true;\n    var units = parseInt(qty, 10) || 1;\n    var mark = set && Object.prototype.hasOwnProperty.call(SECRET_SETS, set) ? set : '';\n    var props = {};\n    if (pair) {\n      // a pair-gift line (bucket F grips / lids, V and L grips, set extras): keep its tag, its quantity and its set\n      props[prop] = 'yes';\n      if (mark) props[SECRET_SET_PROP] = mark;\n    } else {\n      props[GIFT_PROP] = String(target);\n      props['_source'] = 'aov-gift';\n    }\n    // the swapped-out units as `updates`: the line read before the add if it still has that key, then the oldest\n    // lines of the old colour with the same tag (Shopify lists the newest first)\n    function oldUnits(cart) {\n      var hits = ((cart && cart.items) || []).filter(function (i) {\n        var p = i.properties || {};\n        if (!oldVariantId) return i.key === oldKey;\n        if (String(i.variant_id) !== String(oldVariantId)) return false;\n        var m = Object.prototype.hasOwnProperty.call(SECRET_SETS, p[SECRET_SET_PROP]) ? p[SECRET_SET_PROP] : '';\n        return pair ? !!p[prop] && m === mark : String(p[GIFT_PROP]) === String(target);\n      }).reverse();\n      hits.sort(function (x, y) { return (y.key === oldKey) - (x.key === oldKey); });\n      var left = units, updates = {}, n = 0;\n      hits.forEach(function (i) {\n        if (left <= 0) return;\n        var take = Math.min(i.quantity, left);\n        updates[i.key] = i.quantity - take;\n        left -= take; n++;\n      });\n      return n ? updates : null;\n    }\n    function dropOld(retry) {\n      return fetch('/cart.js', { cache: 'no-store' })\n        .then(function (r) { if (!r.ok) throw new Error('cart read failed'); return r.json(); })\n        .then(function (cart) {\n          var updates = oldUnits(cart);\n          if (!updates) return null; // already gone\n          var keys = Object.keys(updates);\n          var req = keys.length === 1\n            ? { url: '/cart/change.js', body: { id: keys[0], quantity: updates[keys[0]] } }\n            : { url: '/cart/update.js', body: { updates: updates } };\n          return fetch(req.url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(req.body) })\n            .then(function (r) {\n              if (r.ok) return null;\n              if (retry && r.status >= 400 && r.status < 500) return dropOld(false);\n              throw new Error('gift swap: old line not removed');\n            });\n        });\n    }\n    fetch('/cart/add.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ items: [{ id: parseInt(newVariantId, 10), quantity: units, properties: props }] })\n    })\n      .then(function (r) {\n        // Add failed (e.g. colour sold out since paint) \u2192 keep the old line\n        if (!r.ok) throw new Error('gift variant add failed');\n        return dropOld(true);\n      })\n      .then(function () { cdGiftSyncing = false; if (pair) cdPairSyncing = false; return render(); })\n      .catch(function () { cdGiftSyncing = false; if (pair) cdPairSyncing = false; render(); });\n  }\n\n  // THE FINAL 2 DAYS (D09, 9am 29 Nov to midnight 30 Nov; Kegan 24 Oct: \"they can get the 2L if they like for the free\n  // gift\"): the free bottle's row gets a 1L | 2L switch while its tier takes both sizes. A tap swaps the gift line to the\n  // other size in the same colour when that colour can be a free bottle in that size, else the first colour that can,\n  // keeping its tag (swapGiftVariant). Never on an engraved free bottle (its size and colour are set) or a trade login.\n  function giftSizeSwitch(item, props) {\n    if (window.b2bCompanyName || !PAIR_BOTTLE_HANDLES[item.handle]) return '';\n    var t = cdTierFor(item, activeGiftTiers());\n    if (!t || !t.handles || t.handles.length < 2) return '';\n    return '<div class=\"cd-gift-size\" role=\"radiogroup\" aria-label=\"Free bottle size\">' + t.handles.filter(function (h) { return PAIR_BOTTLE_HANDLES[h]; }).map(function (h) {\n      var on = h === item.handle;\n      return '<button type=\"button\" class=\"cd-gift-szb\" role=\"radio\" aria-checked=\"' + on + '\"' + (on ? '' : ' data-gift-size=\"' + h + '\"') +\n        ' data-key=\"' + item.key + '\" data-target=\"' + props[GIFT_PROP] + '\" data-current=\"' + item.variant_id + '\" data-colour=\"' + String(item.variant_title || '').replace(/\"/g, '&quot;') + '\">' + (h === '2l' ? '2L' : '1L') + '</button>';\n    }).join('') + '</div>';\n  }\n  function giftSizeSwap(btn) {\n    var size = btn.getAttribute('data-gift-size'), colour = String(btn.getAttribute('data-colour') || '').toLowerCase();\n    if (!size || cdGiftSyncing) return;\n    btn.closest('.cd-gift-size').querySelectorAll('.cd-gift-szb').forEach(function (b) { b.disabled = true; });\n    fetchGiftProduct(size).then(function (prod) {\n      var block = (window.cdGiftVariantBlock || {})[size];\n      var ok = ((prod && prod.variants) || []).filter(function (v) { return v.available && !/bundaberg/i.test(String(v.title)) && !(block && block.test(String(v.title))); });\n      var v = ok.filter(function (x) { return String(x.title).toLowerCase() === colour; })[0] || ok[0];\n      if (!v) { render(); return; }\n      swapGiftVariant(btn.getAttribute('data-key'), v.id, btn.getAttribute('data-target'), null, 1, null, btn.getAttribute('data-current'));\n    }).catch(function () { render(); });\n  }\n\n  // Paint colour swatches onto gift lines after render (product JSON is async).\n  // Reuses .cd-upsell-vpill styling.\n  function populateGiftSwatches() {\n    document.querySelectorAll('.cd-gift-variants').forEach(function (el) {\n      var handle = el.getAttribute('data-handle');\n      if (!handle) return;\n      fetchGiftProduct(handle).then(function (prod) {\n        if (!prod || !prod.variants) return;\n        var current = parseInt(el.getAttribute('data-current'), 10);\n        // Co-brand variants (Bundaberg Rum) are licensed stock \u2014 never offered\n        // as a free-gift colour choice (still shown if somehow already chosen).\n        var block = (window.cdGiftVariantBlock || {})[handle];\n        var choices = prod.variants.filter(function (v) {\n          return (v.available || v.id === current) &&\n                 (!/bundaberg/i.test(String(v.title)) || v.id === current) &&\n                 (!block || !block.test(String(v.title)) || v.id === current);\n        });\n        if (choices.length < 2) return;\n        function pillFor(v) {\n          var img = (v.featured_image && (v.featured_image.src || v.featured_image.url)) || '';\n          img = img ? img.replace(/(\\.[^.?]+)(\\?.*)?$/, '_32x32_crop_center$1') : '';\n          var title = String(v.title).replace(/\"/g, '&quot;');\n          var inner = img\n            ? '<img src=\"' + img + '\" width=\"24\" height=\"24\" alt=\"' + title + '\" style=\"display:block;width:100%;height:100%;object-fit:cover\">'\n            : '<span style=\"font-size:9px;line-height:1;color:#666\">' + String(v.title).charAt(0) + '</span>';\n          return '<button class=\"cd-upsell-vpill cd-gift-vpill' + (v.id === current ? ' selected' : '') + '\" data-variant-id=\"' + v.id + '\" title=\"' + title + '\">' + inner + '</button>';\n        }\n        // COLLAPSED BY DEFAULT (Kegan 23 Aug). The stubby has 11 colours, which laid\n        // out as two rows of swatches and made the gift line 179px tall - taller than\n        // the customer's actual purchase (129px) and the single biggest row in the\n        // cart. Now it shows the chosen colour and opens on demand.\n        var cur = choices.filter(function (v) { return v.id === current; })[0] || choices[0];\n        var curTitle = String(cur.title).replace(/\"/g, '&quot;');\n        // The preview swatch is a SPAN, not a button. pillFor() builds a <button>, and\n        // a button inside a button is invalid HTML: the parser closes the toggle at the\n        // nested one and hoists everything after it out as siblings, so the pills\n        // escaped their hidden container and stayed on screen. Cost me one build.\n        var curImg = (cur.featured_image && (cur.featured_image.src || cur.featured_image.url)) || '';\n        curImg = curImg ? curImg.replace(/(\\.[^.?]+)(\\?.*)?$/, '_32x32_crop_center$1') : '';\n        var curInner = curImg\n          ? '<img src=\"' + curImg + '\" width=\"24\" height=\"24\" alt=\"' + curTitle + '\" style=\"display:block;width:100%;height:100%;object-fit:cover\">'\n          : '<span style=\"font-size:9px;line-height:1;color:#666\">' + String(cur.title).charAt(0) + '</span>';\n        el.innerHTML =\n          '<button type=\"button\" class=\"cd-gift-toggle\" aria-expanded=\"false\">' +\n            '<span class=\"cd-upsell-vpill cd-gift-cur\">' + curInner + '</span>' +\n            '<span class=\"cd-gift-curname\">' + curTitle + '</span>' +\n            '<span class=\"cd-gift-change\">Change colour</span>' +\n          '</button>' +\n          '<div class=\"cd-gift-pills\" hidden>' + choices.map(pillFor).join('') + '</div>';\n      });\n    });\n  }\n\n  // \u2500\u2500\u2500 RECOMMENDATION RULES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // Pin specific products to the front of the \"You might also like\" strip.\n  // Rules are evaluated in ORDER \u2014 first match gets slot 1, second gets slot 2.\n  //\n  // To add a rule, append an entry to CD_UPSELL_RULES below:\n  //   {\n  //     handle : 'product-handle',          // Shopify product handle (string)\n  //     test   : function(items) { ... }    // return true to activate this rule\n  //   }\n  //\n  // 'items' = visible (non-engraving) cart items. Useful fields per item:\n  //   item.product_type   e.g. 'Insulated Bottle'\n  //   item.product_title  e.g. 'Insulated Bottle 1L'\n  //   item.handle         e.g. '1l'\n  //   item.sku            e.g. 'H_ALMD_1L'\n  //   item.product_id     numeric Shopify product ID\n  //\n  // If a pinned product is already in the cart it is skipped automatically\n  // and the next rule (or Shopify's recommendations) takes over.\n  // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n  // Master switch for the 3-for-2 promo strip below. Flip to true to re-enable \u2014\n  // BUY_X_GET_Y_IDS and getPromoBottleTarget stay intact while this is false.\n  var CD_PROMO_3FOR2_ENABLED = false;\n\n  // Products eligible for the 3-for-2 promotion, in priority order.\n  // Identified by product_id (stable \u2014 never changes even if handle or title is edited).\n  // Exclusions: Bundles (product_type), Bundaberg/Bundy (title), car cupholder, shoulder straps, 3pk.\n  var BUY_X_GET_Y_IDS = [\n    5298283610262,  // Insulated Stubby Holder\n    7093177712837,  // Insulated Bottle 1L\n    7407543779525,  // Insulated Bottle 2L\n    8376842125509,  // Ice Tray 1L & 2L\n    8208157802693,  // Ice Tray 4L & 6L\n    8293363810501,  // 1L Silicone Grip\n    8293364105413,  // 2L Silicone Grip\n    7407547023557,  // Insulated Hydro Jug 4L\n    8095656640709,  // Insulated Hydro Jug 6L\n    8738477899973,  // Stainless Steel Straw\n    7556025614533,  // Lunch PAL\n    7001515065541,  // Insulated Cooler Bag 15L\n    7377427235013,  // Insulated Cooler Backpack 20L\n    6698293067973,  // Insulated Cooler Backpack 35L\n    7092974846149,  // DrainPro 35L Backpack\n    8432338763973,  // Insulated RidePal 6L\n    7498728276165,  // 6PACKPAL\n    8095688261829,  // Insulated Wine Holder\n    8293365547205,  // 1L & 2L Smart Lid\n    7669526560965,  // 4L & 6L HydroJUG Lid\n    8424305787077,  // 4L Bottle Sling\n    8424431583429   // 6L Bottle Sling\n  ];\n\n  // 3-for-2 promotion: find the highest-priority eligible product in the cart.\n  // Priority 1: \"1-away\" (count=2) before \"2-away\" (count=1).\n  // Tie-break within same priority: order defined by BUY_X_GET_Y_IDS above.\n  // Returns { handle, count } or null if no actionable product found.\n  function getPromoBottleTarget(items) {\n    var idMap = {};\n    items.forEach(function(i) {\n      if (BUY_X_GET_Y_IDS.indexOf(i.product_id) === -1) return;\n      if (!idMap[i.product_id]) idMap[i.product_id] = { count: 0, handle: i.handle };\n      idMap[i.product_id].count += i.quantity;\n    });\n    // Iterate in canonical priority order (BUY_X_GET_Y_IDS index)\n    var oneAway = null, twoAway = null;\n    BUY_X_GET_Y_IDS.forEach(function(pid) {\n      var info = idMap[pid];\n      if (!info) return;\n      if (info.count === 2 && !oneAway) oneAway = info;   // 1 more completes the deal\n      if (info.count === 1 && !twoAway) twoAway = info;   // 2 more needed\n    });\n    return oneAway || twoAway || null;\n  }\n\n  var CD_UPSELL_RULES = [\n    {\n      // 1L & 2L bottles \u2192 1L & 2L ice tray\n      handle: 'ice-tray-1l-2l-size',\n      test: function(items) {\n        return items.some(function(i) {\n          return i.product_type === 'Insulated Bottle' && /\\b[12]L\\b/i.test(i.product_title);\n        });\n      }\n    },\n    {\n      // 4L & 6L jugs \u2192 4L & 6L ice tray\n      handle: 'silicon-ice-mold-aqua',\n      test: function(items) {\n        return items.some(function(i) {\n          return i.product_type === 'Insulated Hydro Jug' && /\\b[46]L\\b/i.test(i.product_title);\n        });\n      }\n    }\n    // \u2193 Add more rules here\n  ];\n\n  function loadUpsell(cart) {\n    var strip = document.getElementById('cd-upsell-strip');\n    if (!strip) return;\n    var visible = cart.items.filter(function(i){ return !isEngravingItem(i); });\n    if (!visible.length) { strip.style.display = 'none'; return; }\n\n    // One skeleton covers the whole strip (label + card) \u2014 shell re-injected on resolve\n    strip.innerHTML = '<div class=\"cd-upsell-skel\"></div>';\n    strip.style.display = '';\n\n    var inCartIds = {};\n    cart.items.forEach(function(i){ inCartIds[i.product_id] = true; });\n\n    // Resolve image URL regardless of whether it's a string or {src,url} object\n    function imgUrl(val, size) {\n      if (!val) return '';\n      var u = typeof val === 'string' ? val : (val.src || val.url || '');\n      return u ? u.replace(/(\\.[^.?]+)(\\?.*)?$/, '_' + size + '$1') : '';\n    }\n\n    // Gift-gap targeting: when a gift tier is within reach, the strip leads with\n    // the cheapest single item that closes the gap (\"one add unlocks the gift\").\n    var nextGiftGap = 0, nextGiftLabel = '';\n    // what an add will actually cost: the offer test's % comes off every untagged line, so a $59 add is\n    // $47.20 towards a tier. Gap maths on the full price promised unlocks the cart then missed (28 Sep)\n    var gapPct = (offerRules().pct && !pairCartBlocked(cart) && !(cart.attributes || {})._secret_offer) ? offerRules().pct : 0;\n    var netPrice = function (c) { return Math.round(c * (100 - gapPct) / 100); };\n    if (!window.b2bCompanyName) {\n      var giftTiersU = activeGiftTiers();\n      var qualU = giftQualifyingTotal(cart);\n      for (var gi = 0; gi < giftTiersU.length; gi++) {\n        if (giftTiersU[gi].basis === 'bottles') continue;   // only a bottle closes a bottles-only gap\n        if (qualU < giftTiersU[gi].target) {\n          nextGiftGap = giftTiersU[gi].target - qualU;\n          nextGiftLabel = giftTiersU[gi].label;\n          break;\n        }\n      }\n    }\n\n    // Promotion rule fires first \u2014 suppresses existing rules entirely when active\n    // B2B company contacts (co-brand + wholesale) skip the 3-for-2 promo\n    var promoTarget = (CD_PROMO_3FOR2_ENABLED && !window.b2bCompanyName) ? getPromoBottleTarget(visible) : null;\n    var promoHandle = promoTarget ? promoTarget.handle : null;\n    // count=2 \u2192 1 more needed (one-away); count=1 \u2192 2 more needed (two-away)\n    var promoMode = promoTarget ? (promoTarget.count === 2 ? 'one-away' : 'two-away') : null;\n\n    // Fetch disable_variant metafield values via the Liquid metafields endpoint.\n    // Returns an object keyed by variant ID; truthy = disabled.\n    function fetchDisabledVariants(handle) {\n      if (cdDisabledVariantCache[handle]) return cdDisabledVariantCache[handle];\n      return (cdDisabledVariantCache[handle] = fetch('/products/' + handle + '?view=metafields')\n        .then(function(r) { return r.json(); })\n        .then(function(arr) {\n          var disabled = {};\n          (arr || []).forEach(function(v) { if (v.disable) disabled[v.id] = true; });\n          return disabled;\n        })\n        .catch(function() { return {}; }));\n    }\n\n    // Mark disabled-by-metafield variants as unavailable in-place.\n    // If none remain available, sets product.available = false so products.find() skips it.\n    function applyDisabledVariants(product, disabledMap) {\n      if (!product) return;\n      var anyAvailable = false;\n      product.variants.forEach(function(v) {\n        if (disabledMap[v.id]) v.available = false;\n        if (v.available) anyAvailable = true;\n      });\n      if (!anyAvailable) product.available = false;\n    }\n\n    // /products/{handle}.js returns price in cents, accurate variant.available booleans,\n    // and featured_image already populated per variant.\n    // disable_variant metafields are applied in parallel so pinned products are fully\n    // normalised before products.find() runs.\n    function fetchPinnedProduct(handle) {\n      if (cdPinnedProductCache[handle]) return cdPinnedProductCache[handle];\n      return (cdPinnedProductCache[handle] = Promise.all([\n        cdProductJson(handle).then(function (d) {\n          // deep copy: applyDisabledVariants() below rewrites v.available in place, and\n          // the cached object is shared with the gift picker\n          return d ? JSON.parse(JSON.stringify(d)) : null;\n        }),\n        fetchDisabledVariants(handle)\n      ]).then(function(results) {\n        var p = results[0];\n        if (p) applyDisabledVariants(p, results[1]);\n        return p;\n      }).catch(function() { return null; }));\n    }\n\n    // Fetch pinned products (rules that fire) + Shopify recommendations in parallel\n    // When promo fires, skip CD_UPSELL_RULES so the promo product leads exclusively\n    var matchedRules = promoHandle ? [] : CD_UPSELL_RULES.filter(function(rule) { return rule.test(visible); });\n    var promoFetch      = promoHandle ? [fetchPinnedProduct(promoHandle)] : [];\n    var pinnedFetches   = promoFetch.concat(matchedRules.map(function(rule) {\n      return fetchPinnedProduct(rule.handle);\n    }));\n    var recoFetch = fetch('/recommendations/products.json?product_id=' + visible[0].product_id + '&limit=6')\n      .then(function(r) { return r.json(); })\n      .then(function(d) { return d.products || []; })\n      .catch(function() { return []; });\n\n    // Gap mode: products already in the cart are candidates too (\"add another\n    // 1L bottle\" is often the natural gap-closer). Shopify recommendations\n    // never include the cart's own products, so fetch them explicitly.\n    if (nextGiftGap > 0 && !promoHandle) {\n      var seenCartHandles = {};\n      visible.forEach(function (i) {\n        if (i.handle && !seenCartHandles[i.handle]) {\n          seenCartHandles[i.handle] = true;\n          pinnedFetches.push(fetchPinnedProduct(i.handle));\n        }\n      });\n      // Guarantee the small bottles are always in the candidate pool \u2014 Shopify's\n      // recommendations often omit them (e.g. on a 4L jug cart), leaving only\n      // expensive closers. Fetches are cached, so this is cheap.\n      ['1l', '2l'].forEach(function (h) {\n        if (!seenCartHandles[h]) { seenCartHandles[h] = true; pinnedFetches.push(fetchPinnedProduct(h)); }\n      });\n      // A jug owner's most coherent closer is their jug's own sling.\n      if (seenCartHandles['insulated-water-jug-3-8l'] && !seenCartHandles['4l-hydro-jug-bottle-sling-black']) {\n        pinnedFetches.push(fetchPinnedProduct('4l-hydro-jug-bottle-sling-black'));\n      }\n      if (seenCartHandles['insulated-hydro-jug-6l'] && !seenCartHandles['6l-hydro-jug-bottle-sling']) {\n        pinnedFetches.push(fetchPinnedProduct('6l-hydro-jug-bottle-sling'));\n      }\n    }\n\n    // Lone bottle (6 Sep 2026): the most coherent add is a second bottle, which\n    // completes the His & Hers pair (free shipping + free gift via syncPairGift).\n    var pairSingle = !promoHandle && !pairCartBlocked(cart) && pairBottleUnits(cart).units === 1;\n    if (pairSingle) {\n      visible.forEach(function (i) {\n        if (PAIR_BOTTLE_HANDLES[i.handle]) pinnedFetches.push(fetchPinnedProduct(i.handle));\n      });\n    }\n    // Sale, cart already past the free 1L: the next add is another 1L in a new colour, never a 2L. A 4 x 1L cart was offered\n    // \"You might also like: Insulated Bottle 2L\" (the 1L is in the cart, so the strip skipped it) and a customer who tapped\n    // Add for a 5th 1L got a 2L (Gorgias 212494262, 5 Nov 2026)\n    var more1LWanted = !promoHandle && !pairSingle && nextGiftGap <= 0 && cdSaleNudgeOn(cart) &&\n      cdPaidBottles(cart).some(function (i) { return i.handle === '1l'; });\n    if (more1LWanted) pinnedFetches.push(fetchPinnedProduct('1l'));\n\n    Promise.all([recoFetch].concat(pinnedFetches))\n      .then(function(results) {\n        var recoProducts = results[0];\n        var pinnedProducts = results.slice(1).filter(Boolean);\n        // Pinned products lead; Shopify's picks fill the rest\n        var products = pinnedProducts.concat(recoProducts);\n\n        // --- DIAGNOSTIC LOGS (remove once race condition / stale-cart root cause confirmed) ---\n        // --------------------------------------------------------------------------------------\n\n        var SERVICE_RE = /customis|upload|engrav|service/i;\n        // Never recommend a gift-tier product \u2014 the gift engine owns those\n        var giftHandles = {};\n        (window.cdGiftTiers || []).forEach(function (t) { giftHandles[t.handle] = true; });\n        // Products never shown in the upsell strip (by product ID)\n        var UPSELL_BLOCK_IDS = [\n          8738477899973,  // Stainless Steel Straw\n          7498728276165,  // 6PACKPAL\n          8751068872901,  // 1L Bundaberg Rum Bottle (co-brand \u2014 never a DTC upsell)\n          8751087616197,  // Bundaberg Rum Drink Cooler (co-brand)\n          8751327805637,  // 4L Bundaberg Rum Jug (co-brand)\n          8751380103365   // Bundaberg Rum Cooler Backpack 35L (co-brand)\n        ];\n        function upsellBlocked(p) { return UPSELL_BLOCK_IDS.indexOf(p.id) !== -1; }\n\n        // Low-margin accessories are never SUGGESTED as gap-closers (the margin\n        // on these doesn't cover the gift's cost, so steering shoppers to them\n        // loses money). They still count toward thresholds and still appear as\n        // regular upsells \u2014 this only shapes the recommendation.\n        var GAP_CLOSER_BLOCK_IDS = [\n          8376842125509,  // Ice Tray 1L & 2L\n          8208157802693,  // Ice Tray 4L & 6L\n          8293363810501,  // 1L Silicone Grip\n          8293364105413,  // 2L Silicone Grip\n          8293365547205,  // 1L & 2L Smart Lid\n          7669526560965,  // 4L & 6L HydroJUG Lid\n          8432339222725,  // Car Cupholder For 1L Bottle\n          7251778240709   // 15L Shoulder straps x2\n        ];\n\n        // Gap-closer takes the lead slot: cheapest available product whose price\n        // covers the remaining distance to the next gift tier. Excluded handles\n        // can't close the gap (their value doesn't count toward thresholds).\n        var isGapClose = false, gapPickId = null;\n        if (nextGiftGap > 0 && !promoHandle) {\n          var gapExcl = String(window.cdGiftExcludeHandles || '').split(',')\n            .map(function (s) { return s.trim(); }).filter(Boolean);\n          // Gap-closer rule (agreed 19-07): the CHEAPEST PREFERRED product that\n          // covers the gap wins. Preferred = core bottles (always a coherent\n          // add \u2014 \"one for you / the wife / the kids\") plus, when the cart has\n          // a 4L/6L jug, that jug's own sling (its natural accessory). Other\n          // products only appear when nothing preferred can cover the gap.\n          var CORE_BOTTLE_IDS = [\n            7093177712837,  // Insulated Bottle 1L\n            7407543779525,  // Insulated Bottle 2L\n            7407547023557,  // Insulated Hydro Jug 4L\n            8095656640709   // Insulated Hydro Jug 6L\n          ];\n          if (inCartIds[7407547023557]) CORE_BOTTLE_IDS.push(8424305787077); // 4L in cart -> 4L sling preferred\n          if (inCartIds[8095656640709]) CORE_BOTTLE_IDS.push(8424431583429); // 6L in cart -> 6L sling preferred\n          var closers = products.filter(function (p) {\n            return p.available && netPrice(p.price) >= nextGiftGap &&\n                   !SERVICE_RE.test(p.title) && !SERVICE_RE.test(p.handle) &&\n                   /* a core bottle may close the gap even when it is also the free tier gift: in the sale the 1L is the\n                      $165 gift, and blocking it sent 2 x 1L carts a $71.20 2L instead of a $55.20 1L (Kegan 5 Nov) */\n                   (!giftHandles[p.handle] || CORE_BOTTLE_IDS.indexOf(p.id) !== -1) && !upsellBlocked(p) &&\n                   GAP_CLOSER_BLOCK_IDS.indexOf(p.id) === -1 &&\n                   gapExcl.indexOf(p.handle) === -1;\n          }).sort(function (a, b) {\n            var aB = CORE_BOTTLE_IDS.indexOf(a.id) !== -1 ? 0 : 1;\n            var bB = CORE_BOTTLE_IDS.indexOf(b.id) !== -1 ? 0 : 1;\n            if (aB !== bB) return aB - bB;\n            return a.price - b.price;\n          });\n          if (closers.length) {\n            isGapClose = true;\n            gapPickId = closers[0].id;\n            products = [closers[0]].concat(products.filter(function (p) { return p.id !== gapPickId; }));\n          }\n        }\n\n        var more1L = false;\n        if (more1LWanted && !isGapClose) {\n          var oneL = products.find(function (p) { return p.handle === '1l' && p.available; });\n          if (oneL) {\n            more1L = true; gapPickId = oneL.id;\n            products = [oneL].concat(products.filter(function (p) { return p.id !== oneL.id; }));\n          }\n        }\n\n        if (pairSingle) {\n          var mine = products.find(function (p) { return PAIR_BOTTLE_HANDLES[p.handle] && inCartIds[p.id]; });\n          if (mine) {\n            isGapClose = true; gapPickId = mine.id;\n            products = [mine].concat(products.filter(function (p) { return p.id !== mine.id; }));\n          }\n        }\n\n        var product = products.find(function(p){\n          var isPromo = promoHandle && p.handle === promoHandle;\n          // inCartIds bypass for promo and the gap-closer \u2014 both may recommend more of an in-cart item\n          // a lone bottle's pair pick passes the gift-handle filter: on the offer-test arms the 1L is ALSO the\n          // free tier gift, and blocking it sent a lone 1L a 4L jug instead of its pair (found 28 Sep)\n          var pairPick = pairSingle && p.id === gapPickId && PAIR_BOTTLE_HANDLES[p.handle];\n          return (isPromo || p.id === gapPickId || !inCartIds[p.id]) && p.available && !SERVICE_RE.test(p.title) && !SERVICE_RE.test(p.handle) && (!giftHandles[p.handle] || pairPick || ((isGapClose || more1L) && p.id === gapPickId)) && !upsellBlocked(p);\n        });\n        if (!product) { strip.style.display = 'none'; return; }\n\n        // Pinned products already had disable_variant applied inside fetchPinnedProduct.\n        // For reco products (not pinned), apply it now for the one product we'll show.\n        var pinnedSet = {};\n        pinnedProducts.forEach(function(p) { if (p) pinnedSet[p.handle] = true; });\n        var mfPromise = pinnedSet[product.handle]\n          ? Promise.resolve()\n          : fetchDisabledVariants(product.handle).then(function(dm) { applyDisabledVariants(product, dm); });\n\n        return mfPromise.then(function() {\n          if (!product.available) { strip.style.display = 'none'; return; }\n\n          var hasVariants = product.variants.length > 1 && product.variants[0].title !== 'Default Title';\n          var availableVariants = hasVariants ? product.variants.filter(function(vv){ return vv.available; }) : [];\n          // a product the cart already holds (a lone bottle's pair, the 2 x 1L closer, another 1L) leads with a colour the cart\n          // doesn't have yet, free gift colours included (Kegan 5 Nov 2026: \"keep a different colour\")\n          var inCartVariant = {};\n          cart.items.forEach(function (i) { inCartVariant[i.variant_id] = true; });\n          var freshColour = false;\n          if (inCartIds[product.id] && availableVariants.length > 1) {\n            var fresh = availableVariants.filter(function (vv) { return !inCartVariant[vv.id]; });\n            if (fresh.length) {\n              freshColour = true;\n              availableVariants = fresh.concat(availableVariants.filter(function (vv) { return inCartVariant[vv.id]; }));\n            }\n          }\n          var defaultVariant = availableVariants[0] || product.variants[0];\n\n          // Thumbnail: default variant image \u2192 product image \u2192 blank\n          var thumbSrc = imgUrl(defaultVariant.featured_image, '120x120') ||\n                         imgUrl(product.images && product.images[0], '120x120') ||\n                         imgUrl(product.featured_image, '120x120');\n\n          var pillsHtml = '';\n          if (hasVariants) {\n            var pills = availableVariants.map(function(vv, idx){\n              var swatchSrc = imgUrl(vv.featured_image, '32x32_crop_center');\n              var thumbData = imgUrl(vv.featured_image, '120x120') || thumbSrc;\n              var inner = swatchSrc\n                ? '<img src=\"' + swatchSrc + '\" width=\"24\" height=\"24\" alt=\"' + vv.title.replace(/\"/g,'&quot;') + '\" style=\"display:block;width:100%;height:100%;object-fit:cover\">'\n                : '<span style=\"font-size:9px;line-height:1;color:#666\">' + vv.title.charAt(0) + '</span>';\n              return '<button class=\"cd-upsell-vpill' + (idx === 0 ? ' selected' : '') + '\" data-variant-id=\"' + vv.id + '\" data-price=\"' + vv.price + '\" data-thumb=\"' + thumbData.replace(/\"/g,'&quot;') + '\" title=\"' + vv.title.replace(/\"/g,'&quot;') + '\">' + inner + '</button>';\n            }).join('');\n            // Scroll arrow only shown when more than 3 variants\n            var hasMore = availableVariants.length > 3;\n            var backBtn = hasMore ? '<button class=\"cd-upsell-scroll-btn cd-upsell-back\" aria-label=\"Previous colours\">&#8249;</button>' : '';\n            var fwdBtn  = hasMore ? '<button class=\"cd-upsell-scroll-btn cd-upsell-fwd\"  aria-label=\"Next colours\">&#8250;</button>' : '';\n            pillsHtml = '<div class=\"cd-upsell-variants-row\">' + backBtn + '<div class=\"cd-upsell-variants\">' + pills + '</div>' + fwdBtn + '</div>';\n          }\n\n          // Re-inject label + card-wrap shell now that skeleton is done\n          strip.innerHTML = '<div id=\"cd-upsell-label\"></div><div id=\"cd-upsell-value\" hidden></div><div id=\"cd-upsell-card-wrap\"></div>';\n          // the card shows the price the cart will charge: the offer test's % comes off every untagged line\n          var upPct = (offerRules().pct && !pairCartBlocked(cart) && !(cart.attributes || {})._secret_offer) ? offerRules().pct : 0;\n          strip.dataset.pct = upPct;\n          var wrap = document.getElementById('cd-upsell-card-wrap');\n\n          wrap.innerHTML =\n            '<div class=\"cd-upsell-thumb\"><img id=\"cd-upsell-thumb-img\" src=\"' + thumbSrc + '\" alt=\"' + product.title.replace(/\"/g,'&quot;') + '\" width=\"64\" height=\"64\"' + (thumbSrc ? '' : ' style=\"visibility:hidden\"') + '></div>' +\n            '<div class=\"cd-upsell-info\">' +\n              '<div class=\"cd-upsell-title\">' + product.title + '</div>' +\n              '<div class=\"cd-upsell-vname\" id=\"cd-upsell-vname\">' + (hasVariants && defaultVariant && defaultVariant.title !== 'Default Title' ? defaultVariant.title : '') + '</div>' +\n            '</div>' +\n            '<div class=\"cd-upsell-right\">' +\n              '<div class=\"cd-upsell-price\" id=\"cd-upsell-price-val\">' + (promoMode === 'one-away' ? '<span class=\"cd-upsell-was\">' + money(defaultVariant.price) + '</span>Free' : upsellPriceHtml(defaultVariant.price, upPct)) + '</div>' +\n              '<button class=\"cd-upsell-add\" data-variant-id=\"' + defaultVariant.id + '\" aria-label=\"Add ' + product.title.replace(/\"/g,'&quot;') + ' to cart\">Add &#8594;</button>' +\n            '</div>' +\n            pillsHtml;\n\n          // Sale, one bottle under free shipping: the card is the PDP's Add tile, the whole tile one tap\n          var shipStep = pairSingle && product.id === gapPickId && product.handle === (cdShipStep(cart) || {}).handle ? cdShipStep(cart) : null;\n          strip.dataset.pitch = shipStep ? '1' : '';\n          strip.classList.toggle('cd-up-pitch', !!shipStep);\n          if (shipStep) {\n            var vTitle = defaultVariant && defaultVariant.title !== 'Default Title' ? defaultVariant.title : '';\n            wrap.innerHTML =\n              '<button type=\"button\" class=\"cd-pitch\" data-variant-id=\"' + defaultVariant.id + '\" aria-label=\"Make it 2, shipping\\'s free. Add a ' + shipStep.size + (vTitle ? ' in ' + vTitle.replace(/\"/g, '&quot;') : '') + ', only ' + money(cdPitchMore(defaultVariant.price, upPct)) + ' more\">' +\n                '<span class=\"cd-pitch-pic\"><img id=\"cd-upsell-thumb-img\" src=\"' + thumbSrc + '\" alt=\"\" width=\"52\" height=\"52\"' + (thumbSrc ? '' : ' style=\"visibility:hidden\"') + '><span class=\"cd-pitch-plus\" aria-hidden=\"true\">+</span></span>' +\n                '<span class=\"cd-pitch-tx\">' +\n                  '<span class=\"cd-pitch-t\">Make It 2, Shipping\\'s Free</span>' +\n                  '<span class=\"cd-pitch-now\">The ' + wholeMoney(CD_STANDARD_SHIP) + ' shipping comes off</span>' +\n                  '<span class=\"cd-pitch-row\"><span class=\"cd-pitch-chip\" id=\"cd-pitch-chip\">Only ' + money(cdPitchMore(defaultVariant.price, upPct)) + ' More</span>' +\n                  '<span class=\"cd-pitch-vn\">' + shipStep.size + (vTitle ? ' \\u00b7 <span id=\"cd-upsell-vname\">' + vTitle + '</span>' : '') + '</span></span>' +\n                '</span>' +\n              '</button>' +\n              pillsHtml;\n          }\n\n          // Update label and store promoMode for pill click handler\n          strip.dataset.pairSingle = (pairSingle && product.id === gapPickId) ? '1' : '';\n          strip.classList.toggle('cd-up-pair', strip.dataset.pairSingle === '1');\n          var labelEl = document.getElementById('cd-upsell-label');\n          strip.dataset.nudge = '';\n          if (labelEl) {\n            if (promoMode === 'two-away') labelEl.textContent = 'BUY 2, GET 1 FREE';\n            else if (promoMode === 'one-away') labelEl.textContent = 'ADD IT FOR FREE!';\n            else if (pairSingle && product.id === gapPickId) {\n              var promiseCaps = pairPromise(cart, true);\n              labelEl.textContent = 'ADD ANOTHER \\u00b7 UNLOCK FREE SHIPPING' + (promiseCaps ? ' + ' + promiseCaps : '') + '!';\n              paintFreeValue(cart); /* swaps in \"GET $37 FREE\" + the rows once the prices are known */\n              if (cdShipNudge(cart)) strip.dataset.nudge = 'ship';\n            }\n            else if (more1L && product.id === gapPickId) labelEl.textContent = 'ADD ANOTHER 1L' + (freshColour ? ' \\u00b7 NEW COLOUR' : '');\n            else if (isGapClose && product.id === gapPickId) {\n              // List EVERY milestone this one add would unlock (shipping + gift tiers)\n              var unlocks = [];\n              if (window.cdFreeShipTarget && cart.total_price < window.cdFreeShipTarget &&\n                  cart.total_price + netPrice(product.price) >= window.cdFreeShipTarget) {\n                unlocks.push('FREE SHIPPING');\n              }\n              var qNow = giftQualifyingTotal(cart);\n              activeGiftTiers().forEach(function (t) {\n                var isBottle = product.handle === '1l' || product.handle === '2l';\n                if (t.basis === 'bottles' && !isBottle) return;\n                var qT = t.basis === 'bottles' ? giftQualifyingBottles(cart) : qNow;\n                // the \"(worth $69)\" lives on the gift row; kept off the label so it stays one line on a phone\n                if (qT < t.target && qT + netPrice(product.price) >= t.target) {\n                  unlocks.push('FREE ' + String(t.label).replace(/\\s*\\(worth[^)]*\\)/i, '').toUpperCase());\n                  if (t.handle === '1l' && cdSaleNudgeOn(cart)) strip.dataset.nudge = 'gift';\n                }\n              });\n              labelEl.textContent = unlocks.length ? 'ADD THIS \\u00b7 UNLOCK ' + unlocks.join(' + ') : 'YOU MIGHT ALSO LIKE';\n            }\n            else labelEl.textContent = 'YOU MIGHT ALSO LIKE';\n          }\n          // Sale, one more 1L reaches the free 1L: the card is the PDP's 2-bottle Add tile (Kegan 5 Nov), the whole tile one tap\n          var giftStep = strip.dataset.nudge === 'gift' && product.handle === '1l' ? cdGiftStep(cart) : null;\n          if (giftStep) {\n            var gTitle = defaultVariant && defaultVariant.title !== 'Default Title' ? defaultVariant.title : '';\n            var gMore = money(Math.round(defaultVariant.price * (100 - upPct) / 100));\n            strip.dataset.pitch = 'gift';\n            strip.classList.add('cd-up-pitch');\n            wrap.innerHTML =\n              '<button type=\"button\" class=\"cd-pitch\" data-variant-id=\"' + defaultVariant.id + '\" aria-label=\"' + giftStep.title + '. ' + giftStep.now + '. Add a 1L' + (gTitle ? ' in ' + gTitle.replace(/\"/g, '&quot;') : '') + ', only ' + gMore + ' more\">' +\n                '<span class=\"cd-pitch-pic\"><img id=\"cd-upsell-thumb-img\" src=\"' + thumbSrc + '\" alt=\"\" width=\"52\" height=\"52\"' + (thumbSrc ? '' : ' style=\"visibility:hidden\"') + '><span class=\"cd-pitch-plus\" aria-hidden=\"true\">+</span></span>' +\n                '<span class=\"cd-pitch-tx\">' +\n                  '<span class=\"cd-pitch-t\">' + giftStep.title + '</span>' +\n                  '<span class=\"cd-pitch-now\">' + giftStep.now + '</span>' +\n                  '<span class=\"cd-pitch-row\"><span class=\"cd-pitch-chip\" id=\"cd-pitch-chip\">Only ' + gMore + ' More</span>' +\n                  '<span class=\"cd-pitch-vn\">1L' + (gTitle ? ' \\u00b7 <span id=\"cd-upsell-vname\">' + gTitle + '</span>' : '') + '</span></span>' +\n                '</span>' +\n              '</button>' +\n              pillsHtml;\n          }\n          strip.dataset.promoMode = promoMode || '';\n        });\n      })\n      .catch(function(){ strip.style.display = 'none'; });\n  }\n\n  // Multi-milestone progress bar: free shipping + gift tiers on one track.\n  // Shipping progress is measured on cart.total_price (matches checkout's\n  // free-shipping condition); gift progress on the qualifying total.\n  var cdMilestoneUnlocked = {};\n\n  // what the second bottle earns, in this bucket, as the bar and the strip say it\n  function pairPromise(cart, caps) {\n    var mode = pairGiftMode(), t, cut = offerRules().pairCut;\n    // P (4 Oct): the pair is the price, $19 off every 2 bottles; no gift\n    if (cut) return caps ? wholeMoney(cut) + ' OFF THE PAIR' : '<strong>' + wholeMoney(cut) + ' off</strong> the pair';\n    if (mode === 'none') return '';\n    if (mode === 'names') return caps ? 'A FREE NAME ON EACH' : 'a <strong>FREE</strong> name engraved on each';\n    if (mode === 'valuePack') return caps ? 'FREE VALUE PACK' : 'a <strong>FREE</strong> Value Pack';\n    if (mode === 'engrave') t = caps ? 'FREE ENGRAVING ON BOTH' : 'a <strong>FREE</strong> engraving on both';\n    else if (mode === 'kit') t = caps ? 'FREE GRIPS + LIDS FOR BOTH' : '<strong>FREE</strong> grips + lids for both';\n    else if (isOneGiftMode(mode)) {\n      var gn = ONE_GIFT_NAME[oneGiftHandle(pairBottleUnits(cart), mode)];\n      t = caps ? 'FREE ' + gn.toUpperCase() : 'a <strong>FREE</strong> ' + gn;\n    }\n    else t = (caps ? 'FREE ' : 'a <strong>FREE</strong> ') + (mode !== 'tray' && mode !== 'trayOnce' && pairBottleUnits(cart).has1L ? (caps ? 'CAR CUP HOLDER' : 'car cup holder') : (caps ? 'ICE TRAY' : 'ice tray'));\n    return t;\n  }\n\n  // What a second bottle hands over for free, in dollars (Kegan 28 Sep: \"add another bottle and get\n  // $37 of value for free\"). Standard shipping is $12 under the free line (Shopify delivery profile\n  // \"Aus post\", Standard $0-$99.99); a bottle is always over the $3 small-order rate. Gift prices are\n  // the live product prices. Returns null while a price is still loading, or for the engrave and kit\n  // arms, so the copy falls back to words rather than show a wrong number.\n  var CD_STANDARD_SHIP = 1200;\n  // true = one summed figure (\"get $37 free\", shipping counted in); false = Kegan's 18 Aug BF brief rule,\n  // free shipping is never counted in a saving (\"FREE $25 ice tray + FREE shipping\"). Kegan to confirm, 28 Sep.\n  var CD_FV_COUNT_SHIPPING = false;\n\n  // BLACK FRIDAY DRAWER NUDGES (03 brief 2026-11-05-drawer-nudge-single-bottle, Kegan \"go\" 5 Nov): bucket A inside the sale\n  // only, never a B2B / co-brand / secret-set cart. Every amount is worked out from the cart, so 17 Nov, Cyber Monday and any\n  // price change stay right. Paid bottles only: the free 1L (and any cooler or pair gift, or a Duo part) never counts.\n  function cdSaleNudgeOn(cart) {\n    var bf = window.AP_BF, r = offerRules();\n    return !!(r.pct && (r.bucket === 'A' || window.AP_OFFER_BUCKET === 'A') && bf && typeof bf.on === 'function' && bf.on('sale') &&\n      !window.b2bCompanyName && !pairCartBlocked(cart) && !cdTierFreeCart(cart) && !cdSecretSetCart(cart) && !(cart.attributes || {})._secret_offer);\n  }\n  function cdPaidBottles(cart) {\n    return (cart.items || []).filter(function (i) {\n      var p = i.properties || {};\n      return (i.handle === '1l' || i.handle === '2l') && !isGiftItem(i) && !p[PAIR_GIFT_PROP] && !p[DUO_PROP] && i.quantity > 0;\n    });\n  }\n  function cdUnitPaid(i) { return Math.round(cdEffectiveLinePrice(i) / i.quantity); }\n  // one bottle under the free-shipping line: \"Add a second 1L for just $43.20 more, and shipping's FREE\" ($55.20 less the $12)\n  function cdShipStep(cart) {\n    if (!cdSaleNudgeOn(cart) || !window.cdFreeShipTarget || cart.total_price >= window.cdFreeShipTarget) return null;\n    var b = cdPaidBottles(cart);\n    if (b.length !== 1 || b[0].quantity !== 1) return null;\n    var one = cdUnitPaid(b[0]);\n    if (one <= CD_STANDARD_SHIP || cart.total_price + one < window.cdFreeShipTarget) return null;\n    return { size: b[0].handle.toUpperCase(), handle: b[0].handle, one: one, more: one - CD_STANDARD_SHIP };\n  }\n  function cdShipNudge(cart) {\n    var st = cdShipStep(cart);\n    return st ? 'Add a second ' + st.size + ' for just <strong>' + money(st.more) + '</strong> more, and shipping\\'s <strong>FREE</strong>' : '';\n  }\n  // the one-bottle card's tile (PDP Add tile wording, assets/pdp-v3.js pitchFor): what the picked colour adds, less the $12\n  function cdPitchMore(variantPrice, pct) { return Math.round(variantPrice * (100 - (pct || 0)) / 100) - CD_STANDARD_SHIP; }\n  // one more 1L reaches the free 1L tier: \"Add 1 more 1L, get a FREE $69 bottle (4 for $165.60)!\"; '' = keep the \"$X away\" line\n  function cdGiftNudge(cart, next) {\n    if (!next || next.type !== 'gift' || next.basis === 'bottles' || !cdSaleNudgeOn(cart)) return '';\n    var tier = activeGiftTiers().filter(function (t) { return t.target === next.target; })[0];\n    if (!tier || tier.handle !== '1l') return '';\n    cdPrimeGiftPrices();\n    var paid = cdPaidBottles(cart), ones = paid.filter(function (i) { return i.handle === '1l'; });\n    var list = ones.length ? Math.round((ones[0].original_line_price || 0) / ones[0].quantity) : cdGiftPrice['1l'];\n    if (!list) return '';\n    var one = ones.length ? cdUnitPaid(ones[0]) : Math.round(list * (100 - offerRules().pct) / 100);\n    var qual = giftQualifyingTotal(cart);\n    if (qual >= next.target || qual + one < next.target) return '';\n    // \"(4 for $165.60)\" only when the cart is nothing but bottles, so the sum is the bottles' own\n    var n = paid.reduce(function (sum, i) { return sum + i.quantity; }, 0);\n    var plain = cart.items.every(function (i) { return isGiftItem(i) || paid.indexOf(i) !== -1; });\n    return 'Add 1 more 1L, get a <strong>FREE</strong> ' + wholeMoney(list) + ' bottle' + (plain ? ' (' + (n + 2) + ' for ' + money(qual + one) + ')' : '') + '!';\n  }\n  // the 2-bottle card's tile (PDP Add tile wording, assets/pdp-v3.js pitchFor): \"Add 1 More, Get 1 Free\" / \"4 For $165.60 \u00B7 The 4th 1L Is On Us\"\n  function cdGiftStep(cart) {\n    if (!cdSaleNudgeOn(cart)) return null;\n    var tier = activeGiftTiers().filter(function (t) { return t.handle === '1l' && t.basis !== 'bottles'; })[0];\n    if (!tier) return null;\n    cdPrimeGiftPrices();\n    var paid = cdPaidBottles(cart), ones = paid.filter(function (i) { return i.handle === '1l'; });\n    var list = ones.length ? Math.round((ones[0].original_line_price || 0) / ones[0].quantity) : cdGiftPrice['1l'];\n    if (!list) return null;\n    var one = ones.length ? cdUnitPaid(ones[0]) : Math.round(list * (100 - offerRules().pct) / 100);\n    var qual = giftQualifyingTotal(cart);\n    if (qual >= tier.target || qual + one < tier.target) return null;\n    var n = paid.reduce(function (sum, i) { return sum + i.quantity; }, 0), k = n + 2;\n    var all1L = paid.length > 0 && ones.length === paid.length;\n    var plain = cart.items.every(function (i) { return isGiftItem(i) || paid.indexOf(i) !== -1; });\n    var ord = k + (k % 10 === 1 && k % 100 !== 11 ? 'st' : k % 10 === 2 && k % 100 !== 12 ? 'nd' : k % 10 === 3 && k % 100 !== 13 ? 'rd' : 'th');\n    return {\n      title: all1L ? 'Add 1 More, Get 1 Free' : 'Add 1 More, Get 1L Free',\n      now: plain ? k + ' For ' + money(qual + one) + ' \\u00b7 ' + (all1L ? 'The ' + ord + ' 1L Is On Us' : 'Plus A Free 1L') : 'Plus A Free ' + wholeMoney(list) + ' 1L'\n    };\n  }\n  // a tap on a nudge's Add button, for 03's step-up rate (GA4 and Clarity, when the page has them)\n  function cdTrack(name) {\n    try {\n      if (typeof window.gtag === 'function') window.gtag('event', name);\n      if (typeof window.clarity === 'function') window.clarity('event', name);\n    } catch (e) { /* tracking never blocks the add */ }\n  }\n\n  // The drawer's Personalise chip, priced as the gift Function charges (display only; assets/customizer-pz.js bfEngPrice):\n  // inside the sale A's 20% covers engraving (engPct, not a secret set), and on the free engraving day (engFreeDay) one\n  // engraving per bottle is free, the free 1L included. Everyday $9 otherwise, B2B and co-brand always.\n  var CD_ENG_UNIT = 900;\n  function cdEngChip(cart) {\n    var r = offerRules(), bf = window.AP_BF, unit = CD_ENG_UNIT, everyday = 'from ' + wholeMoney(unit);\n    if (!r.pct || !bf || typeof bf.on !== 'function' || !bf.on('sale') || window.b2bCompanyName || cdTierFreeCart(cart)) return everyday;\n    if (r.engFreeDay && bf.on('free_engraving')) return '<strong>1 FREE</strong> today';\n    var secret = !!(cart.attributes || {})._secret_offer || cdSecretSetCart(cart);\n    var sale = r.engPct && !secret ? Math.round(unit * (100 - r.pct) / 100) : unit;\n    return sale < unit ? 'from <s>' + wholeMoney(unit) + '</s> ' + money(sale) : everyday;\n  }\n  var cdGiftPrice = {};\n  function cdPrimeGiftPrices() {\n    [PAIR_TRAY_HANDLE, PAIR_HOLDER_HANDLE, PAIR_KIT_LID, PAIR_STUBBY_HANDLE, PAIR_KIT_GRIP['1l'], PAIR_KIT_GRIP['2l'], '1l'].forEach(function (h) {\n      if (h in cdGiftPrice) return;\n      cdGiftPrice[h] = null;\n      cdProductJson(h).then(function (prod) {\n        var v = prod && prod.variants && prod.variants[0];\n        cdGiftPrice[h] = v ? v.price : 0;\n        if (cdLastCart) { updateShipBar(cdLastCart); paintFreeValue(cdLastCart); }\n      });\n    });\n  }\n  function pairFreeValue(cart) {\n    cdPrimeGiftPrices();\n    var mode = pairGiftMode(), rows = [], gift = null;\n    if (mode === 'engrave' || mode === 'kit' || mode === 'names') return null;\n    var b = pairBottleUnits(cart);\n    // P: the pair price is a saving, not a gift (a row of its own, said as \"$19 off\", never \"free\")\n    if (offerRules().pairCut) rows.push({ name: 'Pair price', value: offerRules().pairCut, cut: true });\n    // V: the whole Value Pack the second bottle unlocks, sized as the cart would get it (a 1L cart: holder + 1L grips)\n    if (mode === 'valuePack') {\n      var vb = { units: 2, ones: b.has1L ? 2 : 0, twos: b.has1L ? 0 : 2, has1L: b.has1L }, vd = valuePackDue(vb);\n      var vname = {}; vname[PAIR_TRAY_HANDLE] = 'Ice tray'; vname[PAIR_HOLDER_HANDLE] = '1L cup holder'; vname[PAIR_STUBBY_HANDLE] = 'Stubby holder';\n      vname[PAIR_KIT_GRIP['1l']] = '2 extra colour grips'; vname[PAIR_KIT_GRIP['2l']] = '2 extra colour grips'; /* the box's words (Kegan 10 Oct) */\n      var missing = false;\n      Object.keys(vd).forEach(function (h) {\n        if (cdGiftOk[h] === false) return; /* sold out: not promised */\n        if (!cdGiftPrice[h]) { missing = true; return; }\n        rows.push({ name: vname[h], value: cdGiftPrice[h] * vd[h], pack: true });\n      });\n      if (missing) return null;\n    }\n    if (mode === 'tray' || mode === 'trayOnce' || (mode === 'standard' && !b.has1L)) gift = { name: 'Ice tray', handle: PAIR_TRAY_HANDLE };\n    else if (mode === 'standard') gift = { name: 'Car cup holder', handle: PAIR_HOLDER_HANDLE };\n    else if (isOneGiftMode(mode)) { var oh = oneGiftHandle(b, mode), on = ONE_GIFT_NAME[oh]; gift = { name: on.charAt(0).toUpperCase() + on.slice(1), handle: oh }; }\n    if (gift) {\n      if (!cdGiftPrice[gift.handle]) return null;\n      rows.push({ name: gift.name, value: cdGiftPrice[gift.handle] });\n    }\n    // L: the second bottle brings its own free grip too (same size as the one in the cart)\n    if (mode === 'twoLooks') {\n      var gh = PAIR_KIT_GRIP[b.has1L ? '1l' : '2l'];\n      if (!cdGiftPrice[gh]) return null;\n      rows.push({ name: '2nd colour grip', value: cdGiftPrice[gh] });\n    }\n    // shipping only counts if the second bottle really takes the cart over the free line\n    var bottle = cart.items.filter(function (i) { return (i.handle === '1l' || i.handle === '2l') && !(i.properties || {})[GIFT_PROP] && !(i.properties || {})[COOLER_PROP]; })[0];\n    var one = bottle ? Math.round((bottle.final_line_price || 0) / bottle.quantity) : 0;\n    if (window.cdFreeShipTarget && cart.total_price < window.cdFreeShipTarget && cart.total_price + one >= window.cdFreeShipTarget) {\n      rows.push({ name: 'Shipping', value: CD_STANDARD_SHIP, ship: true });\n    }\n    if (!rows.length) return null;\n    return { rows: rows, total: rows.reduce(function (sum, r) { return sum + r.value; }, 0) };\n  }\n  function wholeMoney(cents) { return cents % 100 ? money(cents) : '$' + (cents / 100); }\n  // the headline, in both wordings; caps for the card label\n  function freeValueLine(fv, caps) {\n    var cutRow = fv.rows.filter(function (r) { return r.cut; })[0], packRows = fv.rows.filter(function (r) { return r.pack; });\n    var shipRow = fv.rows.some(function (r) { return r.ship; });\n    // P: \"$19 off the pair\", never called free\n    if (cutRow) {\n      if (caps) return 'ADD ANOTHER \\u00b7 ' + wholeMoney(cutRow.value) + ' OFF THE PAIR'; /* one line on a phone; the rows say the shipping */\n      return 'Add a bottle: <strong>' + wholeMoney(cutRow.value) + ' off</strong> the pair' + (shipRow ? ' + <strong>FREE</strong> shipping' : '');\n    }\n    // V: one figure for the pack (its rows list what is in it)\n    if (packRows.length) {\n      var pv = packRows.reduce(function (n, r) { return n + r.value; }, 0);\n      if (caps) return 'ADD ANOTHER \\u00b7 FREE VALUE PACK';\n      return 'Add a bottle: <strong>FREE</strong> ' + wholeMoney(pv) + ' Value Pack' + (shipRow ? ' + <strong>FREE</strong> shipping' : '');\n    }\n    if (CD_FV_COUNT_SHIPPING) return caps ? 'ADD ANOTHER \\u00b7 GET ' + wholeMoney(fv.total) + ' FREE' : 'Add another bottle and get <strong>' + wholeMoney(fv.total) + ' free</strong>';\n    var gift = fv.rows.filter(function (r) { return !r.ship; })[0], ship = fv.rows.some(function (r) { return r.ship; });\n    // the card's rows carry the detail, so its label stays one line on a phone\n    if (caps) return 'ADD ANOTHER \\u00b7 ' + (fv.rows.length >= 3 ? 'GET ALL ' + fv.rows.length + ' FREE' : gift && ship ? 'GET BOTH FREE' : gift ? 'FREE ' + gift.name.toUpperCase() : 'FREE SHIPPING');\n    if (gift) return 'Add a bottle: <strong>FREE</strong> ' + wholeMoney(gift.value) + ' ' + gift.name.toLowerCase() + (ship ? ' + <strong>FREE</strong> shipping' : '');\n    return 'Add another bottle for <strong>FREE</strong> shipping';\n  }\n  // the add-another card: headline dollar figure plus one row per freebie; only on the one-bottle card\n  function paintFreeValue(cart) {\n    var strip = document.getElementById('cd-upsell-strip');\n    var box = document.getElementById('cd-upsell-value'), labelEl = document.getElementById('cd-upsell-label');\n    if (!strip || !box || !labelEl || strip.dataset.pairSingle !== '1') return;\n    if (strip.dataset.pitch === '1') { box.hidden = true; return; } /* the tile says it */\n    var fv = pairFreeValue(cart);\n    if (!fv) { box.hidden = true; return; }\n    labelEl.textContent = freeValueLine(fv, true);\n    box.innerHTML = fv.rows.map(function (r) {\n      if (r.cut) return '<div class=\"cd-fv-row\"><span class=\"cd-fv-tick\" aria-hidden=\"true\">&#10003;</span>' + r.name + '<b style=\"margin-left:5px\">' + wholeMoney(r.value) + ' OFF</b></div>';\n      return '<div class=\"cd-fv-row\"><span class=\"cd-fv-tick\" aria-hidden=\"true\">&#10003;</span>' + r.name + '<s>' + wholeMoney(r.value) + '</s><b>FREE</b></div>';\n    }).join('');\n    box.hidden = false;\n  }\n\n  function updateShipBar(cart) {\n    // shipping line above the total: say the $12 in the cart, beside how to lose it (one-bottle carts only)\n    var shipRow = document.getElementById('cd-ship-row');\n    if (shipRow) {\n      var single = !pairCartBlocked(cart) && pairBottleUnits(cart).units === 1 && window.cdFreeShipTarget && cart.total_price < window.cdFreeShipTarget;\n      var sfv = single ? pairFreeValue(cart) : null;\n      var shipOn = !!(sfv && sfv.rows.some(function (r) { return r.ship; }));\n      if (shipOn) { document.getElementById('cd-ship-row-val').textContent = wholeMoney(CD_STANDARD_SHIP) + ' \\u00b7 free with 2 bottles'; }\n      shipRow.hidden = !shipOn;\n    }\n    var bar = document.getElementById('cd-ship-bar');\n    if (!bar) return;\n    var milestones = [];\n    if (window.cdFreeShipTarget) {\n      milestones.push({ target: window.cdFreeShipTarget, type: 'ship', name: 'FREE shipping' });\n    }\n    if (!window.b2bCompanyName) {\n      activeGiftTiers().forEach(function (t) {\n        milestones.push({ target: t.target, type: 'gift', name: 'FREE ' + t.label, basis: t.basis });\n      });\n    }\n    milestones.sort(function (a, b) { return a.target - b.target; });\n    if (!milestones.length) { bar.style.display = 'none'; return; }\n    bar.style.display = '';\n\n    var qual = giftQualifyingTotal(cart), qualBottles = giftQualifyingBottles(cart);\n    function progressOf(m) { return m.type === 'ship' ? cart.total_price : (m.basis === 'bottles' ? qualBottles : qual); }\n\n    var max   = milestones[milestones.length - 1].target;\n    var fill  = document.getElementById('cd-ship-bar-fill');\n    var msg   = document.getElementById('cd-ship-bar-msg');\n    var track = document.getElementById('cd-ship-bar-track');\n\n    // Milestone marker dots (only when more than one milestone). Rebuilt only\n    // when the milestone set changes, so the fill transition stays smooth.\n    if (track) {\n      var sig = milestones.map(function (m) { return m.type + m.target; }).join('|');\n      if (track.getAttribute('data-msig') !== sig) {\n        track.querySelectorAll('.cd-ship-milestone').forEach(function (d) { d.remove(); });\n        if (milestones.length > 1) {\n          milestones.forEach(function (m) {\n            if (m.target === max) return; // the end of the bar IS the last milestone\n            var dot = document.createElement('div');\n            dot.className = 'cd-ship-milestone';\n            dot.style.left = Math.min(m.target / max * 100, 100) + '%';\n            track.appendChild(dot);\n          });\n        }\n        track.setAttribute('data-msig', sig);\n      }\n    }\n\n    // Fill % tracks the next locked milestone's own progress measure\n    var next = null;\n    for (var i = 0; i < milestones.length; i++) {\n      if (progressOf(milestones[i]) < milestones[i].target) { next = milestones[i]; break; }\n    }\n    var fillProgress = next ? progressOf(next) : max;\n    if (fill) {\n      fill.style.width = Math.min(fillProgress / max * 100, 100) + '%';\n      fill.classList.toggle('cd-unlocked', !next);\n    }\n\n    // Confetti on every fresh unlock\n    var burst = false;\n    milestones.forEach(function (m) {\n      var k = m.type + m.target;\n      var unlocked = progressOf(m) >= m.target;\n      if (unlocked && cdMilestoneUnlocked[k] === false) burst = true;\n      cdMilestoneUnlocked[k] = unlocked;\n    });\n    if (burst) burstConfetti();\n\n    if (msg) {\n      if (!next) {\n        var last = milestones[milestones.length - 1];\n        msg.innerHTML = '<strong>' + last.name + '</strong> unlocked!';\n      } else if (next.type === 'ship' && !pairCartBlocked(cart) && pairBottleUnits(cart).units === 1) {\n        // one bottle in the cart: sell the pair, not the dollar gap (Kegan, 6 Sep 2026)\n        var promise = pairPromise(cart, false), fv = pairFreeValue(cart), sn = cdShipNudge(cart);\n        msg.innerHTML = sn ? sn : fv ? freeValueLine(fv, false)\n                           : 'Add another bottle and get <strong>FREE</strong> shipping' + (promise ? ' + ' + promise : '') + '!';\n      } else if (next.type === 'ship') {\n        msg.innerHTML = 'You\\'re <strong>' + money(next.target - progressOf(next)) + '</strong> away from <strong>FREE</strong> shipping!';\n      } else {\n        msg.innerHTML = cdGiftNudge(cart, next) || 'You\\'re <strong>' + money(next.target - progressOf(next)) + '</strong>' + (next.basis === 'bottles' ? ' of bottles' : '') + ' away from a <strong>' + next.name + '</strong>! &#127873;';\n      }\n    }\n  }\n\n  function showDiscountMsg(text, cls) {\n    var msg = document.getElementById('cd-discount-msg');\n    if (!msg) return;\n    msg.textContent = text;\n    msg.className = cls;\n    msg.style.display = text ? '' : 'none';\n  }\n\n  function showDiscountLoading(on) {\n    var el = document.getElementById('cd-discount-loading');\n    if (el) el.classList.toggle('active', on);\n  }\n\n  function showItemsLoading(on) {\n    var el = document.getElementById('cd-items-loading');\n    if (el) el.classList.toggle('active', on);\n  }\n\n  function setDiscountCode(code) {\n    return fetch('/cart/update.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ discount: code })\n    }).then(function (r) { return r.json(); });\n  }\n\n  // Was THIS code accepted? Read cart.discount_codes[].applicable, which is Shopify's\n  // own answer to exactly that question.\n  //\n  // The old test was `cart_level_discount_applications.length === 0`, which is not the\n  // same question: a code restricted to particular products lands in the LINE's\n  // allocations, not at cart level, so a code that worked perfectly well could be\n  // reported back to the customer as invalid.\n  function codeAccepted(cart, code) {\n    var wanted = (code || '').trim().toLowerCase();\n    var list = cart.discount_codes || [];\n    for (var i = 0; i < list.length; i++) {\n      if ((list[i].code || '').trim().toLowerCase() === wanted) return !!list[i].applicable;\n    }\n    return false;\n  }\n\n  function applyDiscount() {\n    var input = document.getElementById('cd-discount-input');\n    var btn   = document.getElementById('cd-discount-btn');\n    var code  = input ? input.value.trim() : '';\n    if (!code) return;\n    if (btn) btn.disabled = true;\n    showDiscountLoading(true);\n\n    // Read the cart FIRST, to note any code that is currently working. /cart/update.js\n    // holds one discount code, so submitting a second REPLACES it: without this, a\n    // customer who already had a working code and then mistyped a second one lost the\n    // working one, silently, and nothing on screen said so.\n    cdFetchCart()\n      .then(function (r) { return r.json(); })\n      .then(function (before) {\n        var previous = null;\n        var had = before.discount_codes || [];\n        for (var i = 0; i < had.length; i++) {\n          if (had[i].applicable) { previous = had[i].code; break; }\n        }\n        return setDiscountCode(code).then(function (cart) {\n          if (codeAccepted(cart, code)) {\n            showDiscountLoading(false);\n            if (btn) btn.disabled = false;\n            showDiscountMsg('', '');\n            if (input) input.value = '';\n            // /cart/update.js answers before the discount totals are calculated, so\n            // re-read the cart to render fully-processed numbers.\n            return cdFetchCart().then(function (r) { return r.json(); }).then(function (c) { return render(c); });\n          }\n\n          // Rejected. Put the customer's working code back (or clear the dud so it does\n          // not sit on the cart as applicable:false), then re-read and render.\n          return setDiscountCode(previous || '')\n            .then(function () { return cdFetchCart(); })\n            .then(function (r) { return r.json(); })\n            .then(function (fresh) {\n              showDiscountLoading(false);\n              if (btn) btn.disabled = false;\n              var out = render(fresh);\n              // AFTER render, never before. render()'s no-discount branch calls\n              // showDiscountMsg('', '') itself, so a message set beforehand was wiped\n              // ~200ms later and the customer saw nothing at all. Measured 21 Aug 2026:\n              // error shown at 0ms, blanked at 213ms.\n              return Promise.resolve(out).then(function () {\n                showDiscountMsg(\n                  previous\n                    ? 'That code did not work, so ' + previous + ' is still on. Check the spelling.'\n                    : 'That code did not work. Check the spelling, or it may not apply to these items.',\n                  'cd-msg-error'\n                );\n                // leave the text in the box so they can correct it rather than retype\n              });\n            });\n        });\n      })\n      .catch(function () {\n        showDiscountLoading(false);\n        if (btn) btn.disabled = false;\n        showDiscountMsg('Something went wrong. Try again.', 'cd-msg-error');\n      });\n  }\n\n  function removeDiscount() {\n    // Optimistic UI clear for instant feedback\n    var discountSubline  = document.getElementById('cd-discount-subline');\n    var discountInputRow = document.getElementById('cd-discount-input-row');\n    var discountInput    = document.getElementById('cd-discount-input');\n    if (discountSubline)  discountSubline.style.display  = 'none';\n    if (discountInputRow) discountInputRow.style.display = '';\n    if (discountInput)    discountInput.value = '';\n    showDiscountMsg('', '');\n    fetch('/cart/update.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ discount: '' })\n    }).then(function (r) { return r.json(); }).then(function (cart) { return render(cart); });\n  }\n\n  function render(cartData, opts) {\n    var optimistic = !!(opts && opts.optimistic);\n    var cartP = cartData\n      ? Promise.resolve(cartData)\n      : cdFetchCart().then(function (r) { return r.json(); });\n    // A code that arrived on an empty cart applies as soon as items exist \u2014\n    // never on optimistic paints (no network on the tap path).\n    if (!optimistic) cartP = cartP.then(cdApplyDeferredDiscount);\n    // Fetch Liquid discount applications in parallel \u2014 covers Shopify Scripts campaigns\n    // that /cart.js AJAX does not expose (Scripts modify line prices directly).\n    // Optimistic paints reuse the cached copy: no network on the tap path.\n    var discP = optimistic\n      ? Promise.resolve(cdLastLiquidDiscounts)\n      : fetch('/?sections=cart-discounts')\n      .then(function (r) { return r.json(); })\n      .then(function (s) {\n        var raw = (s && s['cart-discounts']) || '[]';\n        try { return JSON.parse(raw.trim()); } catch (e) { return []; }\n      })\n      .catch(function () { return []; });\n    return Promise.all([cartP, discP]).then(function (res) {\n      var cart = res[0];\n      var liquidDiscounts = res[1];\n      cdLastLiquidDiscounts = liquidDiscounts;\n      var engravingItems = cart.items.filter(isEngravingItem);\n      var visibleItems   = cart.items.filter(function (i) { return !isEngravingItem(i); });\n\n        // Auto-cleanup orphaned engraving SKUs (safety net \u2014 catches any removal failure)\n        var visibleCustIds = {};\n        visibleItems.forEach(function (i) {\n          var id = (i.properties || {})['_cust_id'];\n          if (id) visibleCustIds[id] = true;\n        });\n        var orphans = engravingItems.filter(function (e) {\n          var id = (e.properties || {})['_cust_id'];\n          return !id || !visibleCustIds[id];\n        });\n        if (!optimistic && orphans.length > 0) {\n          var orphanUpdates = {};\n          orphans.forEach(function (e) { orphanUpdates[e.key] = 0; });\n          return fetch('/cart/update.js', {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ updates: orphanUpdates })\n          }).then(function (r) { return r.json(); }).then(function (c) { return render(c); });\n        }\n\n        // AOV gift tiers: reconcile before painting \u2014 a cart mutation re-renders\n        // with the fresh cart (sync is a no-op on the second pass). Optimistic\n        // paints NEVER write to the cart: gift sync waits for the reconcile\n        // render after the debounced update lands.\n        var giftP = optimistic ? Promise.resolve(null) : syncGiftTiers(cart).then(function (gc) { return gc || syncPairGift(cart); }).then(function (gc) { return gc || syncJugKit(cart); }).then(function (gc) { return gc || syncDuo(cart); }).then(function (gc) { return gc || syncCooler(cart); });\n        return giftP.then(function (giftCart) {\n        if (giftCart) return render(giftCart);\n        cdLastCart = cart;\n\n        var count = visibleItems.reduce(function (n, i) { return n + i.quantity; }, 0);\n\n        // Badge\n        var badge = document.getElementById('cd-cart-count-badge');\n        if (badge) badge.textContent = count;\n\n        // Wholesale MOQ warning: live, on every render (add/remove/qty change),\n        // not just at checkout-click \u2014 so \"add N more\" always reflects what's\n        // actually in the cart right now instead of going stale after the\n        // shopper adds units without re-opening checkout.\n        if (window.b2bIsWholesale) {\n          var cdCheckoutEl = document.getElementById('cd-cart-checkout');\n          if (cdCheckoutEl) cdShowMoqWarning(cdCheckoutEl, cdComputeMoqShortfalls(cart.items));\n        }\n\n        // \u2500\u2500 Discount code handling (user-applied codes only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n        var priceEl       = document.getElementById('cd-total-price');\n        var origPriceEl   = document.getElementById('cd-original-price');\n        // Prefer Liquid section data (campaign names for Scripts cart-level codes).\n        // Fall back to AJAX data when section fetch fails.\n        var discounts = liquidDiscounts.length > 0\n          ? liquidDiscounts\n          : (cart.cart_level_discount_applications || []);\n        var discountSubline   = document.getElementById('cd-discount-subline');\n        var discountInputRow  = document.getElementById('cd-discount-input-row');\n        var discountCodeLabel = document.getElementById('cd-discount-code-label');\n        var discountSavings   = document.getElementById('cd-discount-savings');\n\n        if (discounts.length > 0) {\n          var disc    = discounts[0];\n          var savings = disc.total_allocated_amount || 0;\n          if (priceEl)     priceEl.textContent    = money(cart.total_price);\n          if (origPriceEl) {\n            origPriceEl.textContent   = money(cart.original_total_price);\n            origPriceEl.style.display = 'inline';\n          }\n          if (discountCodeLabel) discountCodeLabel.textContent = disc.title;\n          if (discountSavings)   discountSavings.textContent   = '-' + money(savings);\n          if (discountSubline)   discountSubline.style.display  = '';\n          if (discountInputRow)  discountInputRow.style.display = 'none';\n        } else {\n          if (priceEl) priceEl.textContent = money(cart.total_price);\n          // Show strikethrough on total when campaign discounts are reducing it\n          // (no code active, but Scripts/automatic have lowered line prices)\n          if (origPriceEl) {\n            if (cart.original_total_price > cart.total_price) {\n              origPriceEl.textContent   = money(cart.original_total_price);\n              origPriceEl.style.display = 'inline';\n            } else {\n              origPriceEl.style.display = 'none';\n            }\n          }\n          if (discountSubline)  discountSubline.style.display  = 'none';\n          if (discountInputRow) discountInputRow.style.display = '';\n          showDiscountMsg('', '');\n        }\n\n        // Say the saving out loud. Runs for code discounts and for automatic/Function\n        // ones alike, since both land in original_total_price vs total_price.\n        var totalSaveEl = document.getElementById('cd-total-save');\n        if (totalSaveEl) {\n          var totalSaved = (cart.original_total_price || 0) - (cart.total_price || 0);\n          if (totalSaved > 0) {\n            totalSaveEl.textContent = 'You save ' + money(totalSaved);\n            totalSaveEl.classList.add('is-on');\n          } else {\n            totalSaveEl.classList.remove('is-on');\n          }\n        }\n        // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        // Sync external cart count badges\n        document.querySelectorAll('.cart-count').forEach(function (el) {\n          el.textContent = count;\n        });\n\n        // Build item HTML\n        // engravingMap: keyed by _cust_id so each visible item can find its linked\n        // engraving SKU. Arrays: automatic discounts (e.g. first-engraving-free)\n        // can SPLIT one surcharge line into a discounted line + a full-price line\n        // sharing the same _cust_id.\n        var engravingMap = {};\n        engravingItems.forEach(function (e) {\n          var id = (e.properties || {})['_cust_id'];\n          if (id) (engravingMap[id] = engravingMap[id] || []).push(e);\n        });\n\n        var PROP_LABELS = {\n          'FRONT GALLERY IMAGE NAME': 'Design',\n          'BACK GALLERY IMAGE NAME': 'Back design',\n          'FRONT NAME': 'Text',\n          'BACK NAME': 'Back text',\n          'B2B FRONT FINISH': 'Finish',\n          'B2B BACK FINISH': 'Back finish',\n          'B2B TOP FINISH': 'Top finish',\n          'B2B POCKET FINISH': 'Pocket finish',\n          'B2B FRONT IMAGE': 'Front design',\n          'B2B BACK IMAGE': 'Back design',\n          'B2B TOP IMAGE': 'Top design',\n          'B2B POCKET IMAGE': 'Pocket design',\n          'B2B FRONT NAME': 'Text',\n          'B2B BACK NAME': 'Back text',\n          'B2B TOP NAME': 'Text',\n          'B2B POCKET NAME': 'Text',\n          'Design preview, front': 'Preview',\n          'Design preview, back': 'Back preview',\n          'Design preview, top': 'Preview',\n          'Design preview, pocket': 'Preview',\n          'B2B FRONT NAMES': 'Names',\n          'B2B BACK NAMES': 'Back names',\n          'B2B TOP NAMES': 'Top names',\n          'B2B POCKET NAMES': 'Pocket names'\n        };\n\n        // GIFT LINES RENDER LAST (Kegan 21 Aug 2026, from Cheryl's Instagram DM:\n        // \"I can't see what ive added to the cart cause of this promo\" /\n        // \"it keeps adding stuff i never added.\")\n        //\n        // Shopify returns the auto-added gift ABOVE the customer's own lines, and the\n        // items pane is a flex:1 child with overflow:hidden, so on a phone it gets\n        // whatever height is left over. Reproduced on live at 430x700 with her exact\n        // cart (2 x 1L, $138): the free stubby row was 179px tall and 90% visible,\n        // her two bottles were 129px and 0% visible. The only line she could see was\n        // the one she never chose - which is both of her complaints in one screen.\n        //\n        // Moving gifts to the bottom took her bottles to 100% visible with nothing\n        // else changed. DISPLAY ORDER ONLY: this is a separate array, deliberately not\n        // a sort of visibleItems or cart.items, because /cart-page removal reads a\n        // 1-based line= index off cart.items and must not be reordered under it. The\n        // qty and remove controls here address lines by item.key, never by index.\n        // Pair gifts too (4 Oct 2026): V's Value Pack is four free lines (tray, holder, two grips), which pushed a\n        // 2-bottle cart's bottles below the fold at 375, the same complaint as above; J's holder and L's grips likewise.\n        var isAnyGift = function (i) { var pr = i.properties || {}; return !!(pr[GIFT_PROP] || pr[PAIR_GIFT_PROP] || pr[COOLER_PROP]); };\n        var displayItems = visibleItems.filter(function (i) {\n          return !isAnyGift(i);\n        }).concat(visibleItems.filter(function (i) {\n          return !!((i.properties || {})[GIFT_PROP]);\n        })).concat(visibleItems.filter(function (i) {\n          return !((i.properties || {})[GIFT_PROP]) && !!((i.properties || {})[PAIR_GIFT_PROP]);\n        })).concat(visibleItems.filter(function (i) {\n          var pr = i.properties || {}; return !pr[GIFT_PROP] && !pr[PAIR_GIFT_PROP] && !!pr[COOLER_PROP];\n        }));\n\n        var html;\n        if (visibleItems.length === 0) {\n          html =\n            '<div id=\"cd-cart-empty\">' +\n              '<div id=\"cd-cart-empty-icon\">&#x1F6D2;</div>' +\n              '<p>Your cart is empty</p>' +\n            '</div>';\n        } else {\n          html = displayItems.map(function (item) {\n            var imgHtml = (item.featured_image && item.featured_image.url)\n              ? '<img src=\"' + item.featured_image.url + '\" alt=\"' + (item.product_title || '').replace(/\"/g, '&quot;') + '\" width=\"80\" height=\"80\">'\n              : '<span class=\"cd-item-thumb-placeholder\">&#x1F6D2;</span>';\n\n            var props = item.properties || {};\n            // Co-brand lines show the finished design (product + logo + names) the\n            // customer saw on Review, saved by cobrand-popup.js as _B2B <ZONE> PREVIEW.\n            var _pvKey = Object.keys(props).filter(function (k) { return /^_B2B [A-Z]+ PREVIEW$/.test(k) && /^https:\\/\\//.test(String(props[k] || '')); })[0];\n            if (_pvKey) {\n              var _pv = String(props[_pvKey]);\n              imgHtml = '<img src=\"' + _pv.replace(/\"/g, '&quot;') + (_pv.indexOf('?') === -1 ? '?' : '&') + 'width=200\" alt=\"' + (item.product_title || '').replace(/\"/g, '&quot;') + ' with your design\" width=\"80\" height=\"80\" style=\"object-fit:contain\">';\n            }\n            var isGift = !!props[GIFT_PROP];\n            // A co-brand line with a names list (B2B <ZONE> NAMES, cobrand-popup.js) has one\n            // name per item: + would add an item with no name and - would drop a name the\n            // fee line still charges for, so its quantity is set in the customiser only.\n            var hasNamesList = Object.keys(props).some(function (k) { return /^B2B [A-Z]+ NAMES$/.test(k) && String(props[k] || '').trim() !== ''; });\n            var isFixedLine = !isGift && !!(props[PAIR_GIFT_PROP] || props[JUG_KIT_PROP] || props[DUO_PROP] || props[COOLER_PROP] || hasNamesList);\n            // a free gift in colours (V / L grips, lids, the cooler's 1L): ONE colour picker PER UNIT (Kegan 22 Oct: \"you can only pick one\n            // colour?\"). Each swaps one unit (swapGiftVariant moves data-qty units), so 2 grips can be 2 colours; the gift rules count by handle\n            // an engraved cooler 1L has its colour set, so no picker\n            var pairPick = isFixedLine && !!(props[PAIR_GIFT_PROP] || props[COOLER_PROP]) && !(props[COOLER_PROP] && props['_cust_id']) && !!item.variant_title && item.variant_title !== 'Default Title';\n            var pickOne = function (q) {\n              return '<div class=\"cd-gift-variants\" data-key=\"' + item.key + '\" data-handle=\"' + item.handle + '\" data-prop=\"' + (props[COOLER_PROP] ? COOLER_PROP : PAIR_GIFT_PROP) + '\" data-qty=\"' + q + '\" data-target=\"yes\"' + (Object.prototype.hasOwnProperty.call(SECRET_SETS, props[SECRET_SET_PROP]) ? ' data-set=\"' + props[SECRET_SET_PROP] + '\"' : '') + ' data-current=\"' + item.variant_id + '\"></div>';\n            };\n            var unitWord = item.handle === PAIR_KIT_GRIP['1l'] || item.handle === PAIR_KIT_GRIP['2l'] ? 'Grip' : item.handle === PAIR_KIT_LID ? 'Lid' : 'Bottle';\n            var pickers = '';\n            if (pairPick) {\n              if (item.quantity > 1) { for (var pu = 1; pu <= item.quantity; pu++) pickers += '<div class=\"cd-gift-unit\"><span class=\"cd-gift-unit-n\">' + unitWord + ' ' + pu + '</span>' + pickOne(1) + '</div>'; }\n              else pickers = pickOne(1);\n            }\n\n            // Only show properties that have a friendly label\n            var propHtml = Object.keys(props).filter(function (k) {\n              return PROP_LABELS[k] && props[k];\n            }).map(function (k) {\n              return '<div class=\"cd-item-prop\"><span class=\"cd-prop-key\">' + PROP_LABELS[k] + ':</span> <span>' + formatPropVal(props[k]) + '</span></div>';\n            }).join('');\n\n            // Look up this item's linked engraving SKU lines via shared _cust_id (for paired removal)\n            var custId = props['_cust_id'];\n            var linked = custId ? engravingMap[custId] : null;\n            var engravingKey = linked ? linked.map(function (e) { return e.key; }).join(',') : '';\n            var personalisationHtml = '', engTitles = [];\n            if (linked) {\n              var engFinal = 0, engOrig = 0;\n              linked.forEach(function (e) {\n                engFinal += (e.final_line_price !== undefined ? e.final_line_price : e.line_price) || 0;\n                engOrig  += (e.original_line_price !== undefined ? e.original_line_price : e.line_price) || 0;\n                // the surcharge lines are not drawn, so a discount the Function put on one (N's \"FREE NAME ENGRAVING\n                // (2 or more bottles)\") is said on its bottle's row instead\n                (e.discounts || []).forEach(function (d) { if (d && d.title && engTitles.indexOf(d.title) < 0) engTitles.push(d.title); });\n              });\n              personalisationHtml =\n                '<div class=\"cd-item-personalisation\">' +\n                  '<span class=\"cd-personalisation-chevron\"></span>' +\n                  'Personalisation: ' +\n                  (engOrig > engFinal ? '<s style=\"opacity:.55;margin-right:2px\">' + money(engOrig) + '</s> ' : '') +\n                  (engFinal === 0 ? 'Free' : money(engFinal)) +\n                '</div>';\n            }\n\n            // Campaign discounts on this specific item (Shopify Scripts / automatic)\n            var itemDiscounts = item.discounts || [];\n            var hasItemDiscount = itemDiscounts.length > 0 &&\n                                  item.original_line_price > item.line_price;\n            var isFree = item.line_price === 0;\n            var chipTitles = hasItemDiscount ? itemDiscounts.map(function (d) { return d.title; }) : [];\n            // a discount on both the bottle and its surcharge (a product code, say) is one chip, not two\n            chipTitles = chipTitles.concat(engTitles.filter(function (t) { return chipTitles.indexOf(t) < 0; }));\n            var campaignChipsHtml = chipTitles.length\n              ? '<div class=\"cd-item-campaigns\">' +\n                  chipTitles.map(function (title) {\n                    /* \"20% OFF EVERYTHING\" reads \"20% OFF\" in the row so the chip and Personalise share a line (Kegan 28 Sep) */\n                    return '<span class=\"cd-campaign-name\">&#10003; ' + String(title).replace(/\\s+everything$/i, '') + '</span>';\n                  }).join('') +\n                '</div>'\n              : '';\n            // Gift lines always show a gift chip (even before the discount kicks in)\n            if (isGift && !hasItemDiscount) {\n              campaignChipsHtml = '<div class=\"cd-item-campaigns\"><span class=\"cd-campaign-name\">&#127873; Free gift &middot; unlocked with your order</span></div>';\n            }\n\n            // MOQ floor: prefer _moq property (set by customizer tool);\n            // fall back to window.b2bMoq when the item matches the current PDP variant\n            // (covers native PDP ATC which doesn't attach _moq)\n            var itemMoq = parseInt(props['_moq']) || 1;\n            if (itemMoq <= 1 && window.b2bMoq > 1 &&\n                item.variant_id === parseInt(window._vcInitialVariantId || '0')) {\n              itemMoq = parseInt(window.b2bMoq);\n            }\n            // Wholesale: MOQ is an aggregate across colours of the same size, checked\n            // at the checkout gate below \u2014 not a per-line floor, so any single colour\n            // can drop as low as 1 here.\n            var minusAtFloor = !window.b2bIsWholesale && itemMoq > 1 && item.quantity <= itemMoq;\n            var minusDisabled = minusAtFloor ? ' disabled' : '';\n            var minusClass = ' class=\"cd-qty' + (minusAtFloor ? ' cd-qty--floor' : '') + '\"';\n            var logoAttr = isLogoLine(props) ? ' data-logo=\"1\"' : '';\n\n            return '<div class=\"cd-cart-item\">' +\n              '<div class=\"cd-item-thumb\">' + imgHtml + '</div>' +\n              '<div class=\"cd-item-info\">' +\n                '<div class=\"cd-item-title-row\">' +\n                  '<div class=\"cd-item-title\">' + (item.product_title || item.title) + '</div>' +\n                '</div>' +\n                '<div class=\"cd-item-pricerow\">' +\n                  (hasItemDiscount ? '<span class=\"cd-item-orig-price\">' + money(item.original_line_price) + '</span>' : '') +\n                  '<span class=\"cd-item-price\">' + (isFree ? 'Free' : money(item.line_price)) + '</span>' +\n                '</div>' +\n                (item.variant_title && item.variant_title !== 'Default Title'\n                  ? '<div class=\"cd-item-variant\">' + item.variant_title + '</div>'\n                  : '') +\n              '</div>' +\n              '<div class=\"cd-item-side\">' +\n                (isGift || isFixedLine ? '' :\n                  '<div class=\"cd-qty-wrap\">' +\n                    '<button' + minusClass + minusDisabled + logoAttr + ' data-key=\"' + item.key + '\" data-qty=\"' + (item.quantity - 1) + '\" aria-label=\"Decrease quantity\">&#x2212;</button>' +\n                    '<span class=\"cd-item-qty\">' + item.quantity + '</span>' +\n                    '<button class=\"cd-qty cd-qty-plus\"' + logoAttr + ' data-key=\"' + item.key + '\" data-qty=\"' + (item.quantity + 1) + '\" data-variant-id=\"' + item.variant_id + '\" data-is-customised=\"' + (item.properties && item.properties['_cust_id'] ? '1' : '') + '\" aria-label=\"Increase quantity\">+</button>' +\n                  '</div>') +\n                '<button class=\"cd-remove\" data-key=\"' + item.key + '\" data-engraving-key=\"' + engravingKey + '\"' + (isGift ? ' data-gift-target=\"' + props[GIFT_PROP] + '\"' : props[COOLER_PROP] ? ' data-gift-target=\"cooler\"' : '') + ' aria-label=\"Remove item\">Remove</button>' +\n              '</div>' +\n              '<div class=\"cd-item-rest\">' +\n                campaignChipsHtml +\n                personalisationHtml +\n                (propHtml && personalisationHtml\n                  ? '<div class=\"cd-item-props\">' + propHtml + '</div>'\n                  : propHtml\n                  ? '<div class=\"cd-item-props cd-props-open\">' + propHtml + '</div>'\n                  : '') +\n                '<div class=\"cd-item-actions' + (isGift && !custId && PAIR_BOTTLE_HANDLES[item.handle] && !window.b2bCompanyName ? ' cd-item-actions--gift' : '') + (pairPick ? ' cd-item-actions--pick' : '') + '\">' +\n                  (isGift\n                    // Gift lines: fixed qty 1 \u2014 colour swatches instead of qty controls. A free 1L / 2L can be\n                    // personalised (Kegan, 21 Oct 2026): the pair box runs the pop-up on it alone and only the\n                    // engraving is paid. Once engraved its colour is set, so no swatches.\n                    ? (custId ? '' : giftSizeSwitch(item, props) + '<div class=\"cd-gift-variants\" data-key=\"' + item.key + '\" data-handle=\"' + item.handle + '\" data-target=\"' + props[GIFT_PROP] + '\" data-current=\"' + item.variant_id + '\"></div>' +\n                      (PAIR_BOTTLE_HANDLES[item.handle] && !window.b2bCompanyName\n                        ? '<button type=\"button\" class=\"cd-personalise\" data-personalise data-gift=\"1\" data-variant-id=\"' + item.variant_id + '\" data-handle=\"' + item.handle + '\" data-key=\"' + item.key + '\">Personalise &middot; ' + cdEngChip(cart) + '</button>'\n                        : ''))\n                    : isFixedLine\n                    // Pair gifts and jug-kit lines: quantity follows the bottles / jugs, so no stepper.\n                    // A pair gift that comes in colours (bucket F grips and lids, set grips) gets the\n                    // same collapsed colour picker the tier gifts have.\n                    ? '<div class=\"cd-fixed-qty\">' + item.quantity + ' &times; <span>' + (props[PAIR_GIFT_PROP] ? (cdSecretActive(cart) ? (cdSetLine(item, cart) ? 'Free with your pair' : '') : pairGiftMode() === 'kit' ? 'Free with your pair' : pairGiftMode() === 'valuePack' ? 'Free in your Value Pack' : pairGiftMode() === 'twoLooks' && (item.handle === PAIR_KIT_GRIP['1l'] || item.handle === PAIR_KIT_GRIP['2l']) ? 'Free 2nd look, one per bottle' : pairGiftMode() === 'trayOnce' || isOneGiftMode(pairGiftMode()) ? 'Free with 2 or more bottles' : 'One per pair of bottles') : props[DUO_PROP] ? 'In your Duo Pack' : props[COOLER_PROP] ? 'Free with your cooler bag' : hasNamesList ? 'one name each, change in the customiser' : 'matched to your jug') + '</span></div>' +\n                      pickers +\n                      // Cooler Bag Week's free 1L can be personalised too (3 Nov 2026): the pair box's gift run with its own tag (?eg=c)\n                      (props[COOLER_PROP] && !props['_cust_id'] && item.handle === '1l' && !window.b2bCompanyName\n                        ? '<button type=\"button\" class=\"cd-personalise\" data-personalise data-gift=\"c\" data-variant-id=\"' + item.variant_id + '\" data-handle=\"' + item.handle + '\" data-key=\"' + item.key + '\">Personalise &middot; ' + cdEngChip(cart) + '</button>'\n                        : '')\n                    : '' +\n                      // Personalise from the cart (Kegan, 19 Sep 2026): a plain 1L / 2L bottle line\n                      // can be engraved here. Opens the customiser for this variant; on approve the\n                      // engraved bottle arrives with its own lines and one plain unit is removed.\n                      (custId && !isEngravingItem(item) && props['_customised_product'] && typeof window.apEditEngraving === 'function' && (window.apEditEngraving.handles || []).indexOf(item.handle) >= 0\n                        ? '<button type=\"button\" class=\"cd-personalise\" data-edit-eng data-cust-id=\"' + custId + '\">Edit Engraving</button>'\n                        : '') +\n                      (PAIR_BOTTLE_HANDLES[item.handle] && !custId && !window.b2bCompanyName\n                        ? '<button type=\"button\" class=\"cd-personalise\" data-personalise data-variant-id=\"' + item.variant_id + '\" data-handle=\"' + item.handle + '\" data-key=\"' + item.key + '\">Personalise &middot; ' + ((pairGiftMode() === 'engrave' || pairGiftMode() === 'names') && !pairCartBlocked(cart) && pairBottleUnits(cart).units >= 2 ? 'FREE' : cdEngChip(cart)) + '</button>'\n                        : '')) +\n                '</div>' +\n              '</div>' +\n            '</div>';\n          }).join('');\n        }\n\n        var itemsEl = document.getElementById('cd-cart-items');\n        if (itemsEl) {\n          itemsEl.innerHTML = html;\n        }\n        showItemsLoading(false);\n\n        updateShipBar(cart);\n        loadUpsell(cart);\n        populateGiftSwatches();\n        }); // end syncGiftTiers().then\n      });\n  }\n\n  // \u2500\u2500\u2500 OPTIMISTIC CART \u2014 the drawer never makes the shopper wait \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // Taps update the screen instantly from local state; the real Shopify write\n  // happens in the background, debounced so +++ becomes ONE call. The response\n  // cart is repainted silently as truth. Failures roll back to Shopify's state\n  // with a small inline note. Checkout is held until any pending sync lands.\n  var cdLastCart = null;            // cart as last painted (base for local mutations)\n  var cdLastLiquidDiscounts = [];   // cached section discounts for optimistic paints\n  var cdPendingUpdates = {};        // line key -> desired qty, awaiting flush\n  var cdFlushTimer = null;\n  var cdSyncPromise = null;         // in-flight background write (checkout guard awaits)\n\n  function cdHasPending() {\n    for (var k in cdPendingUpdates) if (cdPendingUpdates.hasOwnProperty(k)) return true;\n    return false;\n  }\n\n  function optimisticChange(key, qty, engravingKey) {\n    if (!cdLastCart) { cartChange(key, qty, engravingKey, null); return; } // no local state yet \u2014 old path\n    var updates = {};\n    updates[key] = qty;\n    if (qty === 0 && engravingKey) {\n      engravingKey.split(',').forEach(function (k) { updates[k] = 0; });\n    }\n    optimisticApply(updates);\n  }\n\n  // Logo lines: the bottle line and its fee line(s) move together, in one write\n  function logoQtyChange(key, qty) {\n    if (cdLastCart) {\n      var updates = logoLineUpdates(cdLastCart, key, qty);\n      if (updates) optimisticApply(updates); else render();\n      return;\n    }\n    // No painted cart yet: read it, then write the whole set at once\n    showItemsLoading(true);\n    cdFetchCart()\n      .then(function (r) { return r.json(); })\n      .then(function (cart) {\n        var u = logoLineUpdates(cart, key, qty);\n        if (!u) return render(cart);\n        return fetch('/cart/update.js', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ updates: u })\n        }).then(function () { return render(); });\n      })\n      .catch(function () { cdShowError(\"Couldn't update your cart, try again\"); render(); });\n  }\n\n  function optimisticApply(updates) {\n    Object.keys(updates).forEach(function (k) { cdPendingUpdates[k] = updates[k]; });\n    // Mutate the local cart and repaint instantly (no network on this path)\n    var count = 0, total = 0;\n    cdLastCart.items = cdLastCart.items.filter(function (i) {\n      if (cdPendingUpdates.hasOwnProperty(i.key)) {\n        var q = cdPendingUpdates[i.key];\n        if (q === 0) return false;\n        i.quantity = q;\n        i.line_price = (i.price || 0) * q;\n        i.original_line_price = (i.original_price || i.price || 0) * q;\n        i.final_line_price = (i.final_price || i.price || 0) * q;\n      }\n      return true;\n    });\n    // original_total_price moves with the lines too: the \"was\" strike and the \"You save\" pill read it against\n    // total_price, so a stale original showed \"$69, was $207, YOU SAVE $138\" for ~3 s after a tap (11 Oct 2026)\n    var orig = 0;\n    cdLastCart.items.forEach(function (i) { count += i.quantity; total += (i.final_line_price || 0); orig += (i.original_line_price || i.final_line_price || 0); });\n    cdLastCart.item_count = count;\n    cdLastCart.total_price = total;\n    cdLastCart.original_total_price = orig;\n    render(cdLastCart, { optimistic: true });\n    if (cdFlushTimer) clearTimeout(cdFlushTimer);\n    cdFlushTimer = setTimeout(flushCartUpdates, 400);\n  }\n\n  function flushCartUpdates() {\n    if (cdFlushTimer) { clearTimeout(cdFlushTimer); cdFlushTimer = null; }\n    if (!cdHasPending()) return cdSyncPromise || Promise.resolve();\n    var updates = cdPendingUpdates;\n    cdPendingUpdates = {};\n    // Serialise behind any in-flight write \u2014 parallel cart writes corrupt each other\n    var base = cdSyncPromise || Promise.resolve();\n    var p = base.then(function () {\n      return fetch('/cart/update.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ updates: updates })\n      });\n    })\n      .then(function (r) { if (!r.ok) throw new Error('cart update failed'); return cdFetchCart(); })\n      .then(function (r) { return r.json(); })\n      .then(function (cart) {\n        // If more taps queued while we were in flight, their flush will repaint \u2014\n        // skip painting this already-stale cart.\n        if (!cdHasPending()) return render(cart);\n      })\n      .catch(function () {\n        // Roll back to Shopify's truth and tell the shopper, quietly\n        return cdFetchCart()\n          .then(function (r) { return r.json(); })\n          .then(function (cart) { cdShowError(\"Couldn't update your cart \u2014 try again\"); return render(cart); })\n          .catch(function () {});\n      })\n      .then(function () { if (cdSyncPromise === p) cdSyncPromise = null; });\n    cdSyncPromise = p;\n    return p;\n  }\n\n  function settleCartSync() {\n    var inflight = cdSyncPromise || Promise.resolve();\n    return inflight.then(function () {\n      if (cdHasPending()) return flushCartUpdates();\n    });\n  }\n\n  function cdShowError(msg) {\n    var itemsEl = document.getElementById('cd-cart-items');\n    if (!itemsEl) return;\n    var note = document.getElementById('cd-cart-error');\n    if (!note) {\n      note = document.createElement('div');\n      note.id = 'cd-cart-error';\n      note.setAttribute('style', 'margin:8px 0;padding:9px 12px;border-radius:8px;background:#FDECEA;color:#8C2B22;font-size:13px;text-align:center');\n      itemsEl.parentNode.insertBefore(note, itemsEl);\n    }\n    note.textContent = msg;\n    note.style.display = '';\n    setTimeout(function () { note.style.display = 'none'; }, 4000);\n  }\n\n  // Back/forward cache: a page restored via the back button comes back with a\n  // STALE drawer (old quantities, dead line keys) \u2014 taps from that state sync\n  // wrong numbers to Shopify. Dump all local state and repaint from truth.\n  window.addEventListener('pageshow', function (e) {\n    if (!e.persisted) return;\n    cdPendingUpdates = {};\n    if (cdFlushTimer) { clearTimeout(cdFlushTimer); cdFlushTimer = null; }\n    cdSyncPromise = null;\n    cdLastCart = null;\n    render();\n  });\n\n  // Wholesale MOQ is an aggregate across colours of the same size (product) \u2014\n  // any colour mix that sums to the product's MOQ satisfies it. \"Size\" is the\n  // product, unless a non-colour option also varies on it (e.g. a bundle's own\n  // \"Bottle Size\"), in which case those values join the key too so different\n  // physical sizes bundled under one product don't get merged together.\n  function cdSizeKey(item) {\n    var others = (item.options_with_values || [])\n      .filter(function (o) { return o.name !== 'Color' && o.name !== 'Colour'; })\n      .map(function (o) { return o.value; })\n      .sort();\n    return item.product_id + '|' + others.join(',');\n  }\n\n  // Sums quantity per size across every cart line carrying a _moq property\n  // (stamped by the Studio, the PDP customiser, and every other add-to-cart\n  // surface \u2014 see cobrand-wholesale-moq-input/-value). Returns a list of\n  // \"Product (got of need, add N more)\" strings for any size short of its\n  // MOQ \u2014 empty when everything clears. Pure function of the cart items\n  // already in hand \u2014 no network call, so it's safe to run on every render.\n  function cdComputeMoqShortfalls(items) {\n    var groups = {};\n    (items || []).forEach(function (item) {\n      var moq = parseInt((item.properties || {})._moq) || 0;\n      if (!moq) return;\n      var key = cdSizeKey(item);\n      if (!groups[key]) groups[key] = { qty: 0, moq: moq, title: item.product_title };\n      groups[key].qty += item.quantity;\n    });\n    var shortfalls = [];\n    Object.keys(groups).forEach(function (k) {\n      var g = groups[k];\n      if (g.qty < g.moq) {\n        shortfalls.push(g.title + ' (' + g.qty + ' of ' + g.moq + ' \u2014 add ' + (g.moq - g.qty) + ' more)');\n      }\n    });\n    return shortfalls;\n  }\n\n  // Checkout-click version: re-fetches the cart fresh (no-store \u2014 this is\n  // the final gate before navigation, so it must never read a cached copy)\n  // rather than trusting whatever the drawer last rendered, in case the\n  // shopper changed something through a path the drawer didn't observe.\n  function cdWholesaleMoqShortfalls(callback) {\n    fetch('/cart.js', { cache: 'no-store' })\n      .then(function (r) { return r.json(); })\n      .then(function (cart) { callback(cdComputeMoqShortfalls(cart.items)); })\n      .catch(function () { callback([]); }); // fail-open on a network hiccup \u2014 don't trap the shopper\n  }\n\n  // One warning element per checkout entry point, created on first use and\n  // reused after that (inserted immediately before the button/link it warns for).\n  function cdShowMoqWarning(chk, shortfalls) {\n    var warnEl = chk.__cdMoqWarningEl;\n    if (!warnEl) {\n      warnEl = document.createElement('div');\n      warnEl.className = 'cd-moq-warning';\n      chk.parentNode.insertBefore(warnEl, chk);\n      chk.__cdMoqWarningEl = warnEl;\n    }\n    if (shortfalls.length) {\n      warnEl.textContent = 'Wholesale minimum not reached \u2014 mix any colours to get there: ' + shortfalls.join('; ') + '.';\n      warnEl.hidden = false;\n    } else {\n      warnEl.hidden = true;\n    }\n  }\n\n  // Checkout guard: never send the shopper to checkout with an unsynced cart,\n  // or \u2014 for wholesale \u2014 short of the per-size MOQ aggregate. With nothing to\n  // check, this does nothing and the link/button proceeds as normal.\n  document.addEventListener('click', function (e) {\n    var chk = e.target.closest('#cd-cart-checkout, button[name=\"checkout\"]');\n    if (!chk) return;\n\n    function proceed() {\n      if (chk.id === 'cd-cart-checkout') {\n        if (!cdSyncPromise && !cdFlushTimer && !cdHasPending()) { window.location.href = '/checkout'; return; }\n        showItemsLoading(true);\n        settleCartSync()\n          .then(function () { window.location.href = '/checkout'; })\n          .catch(function () { window.location.href = '/checkout'; });\n      } else {\n        // Native cart-page form submit button \u2014 form.submit() bypasses this\n        // click listener (unlike calling .click() again, which would re-enter it).\n        var form = chk.closest('form');\n        if (form) form.submit();\n      }\n    }\n\n    if (window.b2bIsWholesale) {\n      e.preventDefault();\n      cdWholesaleMoqShortfalls(function (shortfalls) {\n        cdShowMoqWarning(chk, shortfalls);\n        if (!shortfalls.length) proceed();\n      });\n      return;\n    }\n\n    if (!cdSyncPromise && !cdFlushTimer && !cdHasPending()) return;\n    e.preventDefault();\n    showItemsLoading(true);\n    settleCartSync()\n      .then(function () { window.location.href = '/checkout'; })\n      .catch(function () { window.location.href = '/checkout'; });\n  }, true);\n\n  function cartChange(key, qty, engravingKey, rowEl) {\n    showItemsLoading(true);\n    // Disable buttons in the affected row only to prevent double-click during update\n    var disableScope = rowEl || document.getElementById('cd-cart-items');\n    if (disableScope) {\n      disableScope.querySelectorAll('.cd-qty, .cd-remove').forEach(function (b) {\n        b.disabled = true;\n        b.style.opacity = '0.5';\n      });\n    }\n    var responsePromise;\n    if (qty === 0 && engravingKey) {\n      // Atomically remove both the main product and its linked engraving SKU line(s)\n      var updates = {};\n      updates[key] = 0;\n      engravingKey.split(',').forEach(function (k) { updates[k] = 0; });\n      responsePromise = fetch('/cart/update.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ updates: updates })\n      });\n    } else {\n      responsePromise = fetch('/cart/change.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ id: key, quantity: qty })\n      });\n    }\n    responsePromise\n      .then(function (r) { return r.json(); })\n      .then(function (cart) {\n        var discounts = cart.cart_level_discount_applications || [];\n        if (discounts.length > 0) {\n          // change/update response returns before discount amounts are recalculated \u2014 fetch fresh\n          return cdFetchCart().then(function (r) { return r.json(); }).then(function (c) { return render(c); });\n        }\n        return render(cart);\n      });\n  }\n\n  // The theme's stock component-ajax-cart.js crashes in cartCallback \u2014 it reads\n  // #CartDrawer, which was removed along with the old drawer \u2014 so its\n  // loadingState.destroy never runs and the ADD TO CART button is left disabled\n  // with a spinner. Clear that state whenever a cart add completes, and again on\n  // bfcache restores (browser back re-shows the page with the stuck state baked in).\n  function resetAtcButtons() {\n    document.querySelectorAll('button.btn-loading, input.btn-loading').forEach(function (b) {\n      b.classList.remove('btn-loading');\n      b.disabled = false;\n    });\n  }\n  window.addEventListener('pageshow', function (e) {\n    if (e.persisted) resetAtcButtons();\n  });\n\n  function onCartAdded() {\n    // the bottle page's personalise chain (window.apEngraveLine) adds the bundle, then the\n    // engraved bottles one by one; it holds the drawer shut until the last bottle is done\n    if (window.cdHoldDrawerUntil && Date.now() < window.cdHoldDrawerUntil) { resetAtcButtons(); setTimeout(resetAtcButtons, 1200); return; }\n    openDrawer();\n    resetAtcButtons();\n    // the stock script flips the button back to loading while it rebuilds the old\n    // drawer markup; sweep once more after it has crashed out\n    setTimeout(resetAtcButtons, 1200);\n  }\n\n  // Intercept /cart/add at network level \u2014 open drawer on any successful cart add\n  (function patchCartAdd() {\n    var _xhrOpen = XMLHttpRequest.prototype.open;\n    XMLHttpRequest.prototype.open = function (method, url) {\n      if (typeof url === 'string' && url.indexOf('/cart/add') !== -1) {\n        this.addEventListener('load', function () {\n          if (this.status >= 200 && this.status < 300) {\n            setTimeout(onCartAdded, 50);\n          }\n        });\n      }\n      return _xhrOpen.apply(this, arguments);\n    };\n    if (window.fetch) {\n      var _fetch = window.fetch;\n      window.fetch = function () {\n        var url = typeof arguments[0] === 'string'\n          ? arguments[0]\n          : ((arguments[0] && arguments[0].url) || '');\n        var p = _fetch.apply(this, arguments);\n        if (url.indexOf('/cart/add') !== -1) {\n          p.then(function (r) {\n            if (r.ok) setTimeout(onCartAdded, 50);\n          }).catch(function () {});\n        }\n        return p;\n      };\n    }\n  })();\n\n  // Intercept collection grid quick-add clicks \u2014 prevent Debutify redirect to /cart\n  // Variant ID lives on data-id of the inner <span>, no form involved\n  (function patchGridATC() {\n    document.addEventListener('click', function (e) {\n      var btn = e.target.closest('.add_to_cart.product-grid-item');\n      if (!btn) return;\n      var span = btn.querySelector('[data-id]');\n      if (!span) return;\n      var variantId = span.getAttribute('data-id');\n      if (!variantId) return;\n\n      e.preventDefault();\n      e.stopImmediatePropagation();\n\n      var fd = new FormData();\n      fd.append('id', variantId);\n      fd.append('quantity', 1);\n\n      fetch('/cart/add.js', { method: 'POST', body: fd })\n        .then(function (r) { if (r.ok) setTimeout(openDrawer, 50); })\n        .catch(function () {});\n    }, true); // capture phase \u2014 fires before Debutify's bubble handlers\n  })();\n\n  // Backstop \u2014 if Debutify adds js-drawer-open-right to body, intercept it.\n  // Cleanup (unlockScroll) always runs regardless of cdJustClosed.\n  // openDrawer() is skipped only during the post-close grace period.\n  (function watchOldDrawer() {\n    new MutationObserver(function (mutations) {\n      for (var i = 0; i < mutations.length; i++) {\n        if (mutations[i].attributeName === 'class' &&\n            document.body.classList.contains('js-drawer-open-right')) {\n          unlockScroll();\n          var old = document.getElementById('CartDrawer');\n          if (old) { old.classList.remove('js-drawer-open'); old.removeAttribute('style'); }\n          if (!cdJustClosed && !(window.cdHoldDrawerUntil && Date.now() < window.cdHoldDrawerUntil)) {\n            openDrawer();\n          }\n          break;\n        }\n      }\n    }).observe(document.body, { attributes: true, attributeFilter: ['class'] });\n  })();\n\n  // Layer 3: watch html element directly for any scroll lock Debutify sets\n  // outside of the body class change path (e.g. direct style.overflow writes or\n  // class additions on html). Runs continuously; no-ops when our drawer is open.\n  (function watchHtmlScrollLock() {\n    new MutationObserver(function () {\n      var drawer = document.getElementById(DRAWER_ID);\n      if (drawer && drawer.classList.contains('open')) return;\n      // Our drawer is closed \u2014 clear any overflow lock on html.\n      // Check for 'hidden' specifically \u2014 'auto' is the value we deliberately set and must not be cleared.\n      if (document.documentElement.style.overflow === 'hidden' ||\n          document.documentElement.style.overflowY === 'hidden' ||\n          document.documentElement.classList.contains('js-drawer-open') ||\n          document.documentElement.classList.contains('js-drawer-open-right')) {\n        unlockScroll();\n      }\n    }).observe(document.documentElement, { attributes: true, attributeFilter: ['style', 'class'] });\n  })();\n\n  // Inject styles immediately on script load\n  injectStyles();\n\n  // Route any URL/cookie discount code on page load, then reconcile gift tiers\n  // against the discounted totals immediately \u2014 the customer may head straight\n  // to checkout without ever opening the drawer, and a gift the code no longer\n  // covers must not travel with them.\n  routeUrlDiscount().then(function (cart) {\n    if (!cart) return;\n    return syncGiftTiers(cart).then(function (giftCart) {\n      var c = giftCart || cart;\n      var count = c.items.filter(function (i) { return !isEngravingItem(i); })\n        .reduce(function (n, i) { return n + i.quantity; }, 0);\n      document.querySelectorAll('.cart-count').forEach(function (el) { el.textContent = count; });\n      var drawer = document.getElementById(DRAWER_ID);\n      if (drawer && drawer.classList.contains('open')) render();\n    });\n  });\n\n  // The visitor's offer arm changed on this page view (snippets/offer-test-bucket.liquid wrote the new arm to the\n  // cart and fired this with the cart it read): take the old arm's gifts out now, not when the drawer next opens.\n  // The snippet also leaves it in window.apOfferArmPending, in case it fired before this deferred file ran.\n  function cdOnOfferArm() {\n    window.apOfferArmPending = null;\n    cdDropOldArmGifts().then(function (c) {\n      if (!c || !c.items) return;\n      var count = c.items.filter(function (i) { return !isEngravingItem(i); })\n        .reduce(function (n, i) { return n + i.quantity; }, 0);\n      document.querySelectorAll('.cart-count').forEach(function (el) { el.textContent = count; });\n      var drawer = document.getElementById(DRAWER_ID);\n      if (drawer && drawer.classList.contains('open')) render();\n    }).catch(function () {});\n  }\n  document.addEventListener('ap:offerarm', cdOnOfferArm);\n  if (window.apOfferArmPending) cdOnOfferArm();\n  // Trade logins (17 Oct 2026): a cart built while logged out keeps its pair / tier gift lines when the shopper signs\n  // in to a company, and the gift Function charges them on a B2B cart (Kegan's own trade cart carried a V Value Pack\n  // set at wholesale price). The B2B drawer never runs the gift sync and Buy-now skips it, so sweep once per page\n  // view: the same removals-only pass as an arm change (pairGiftStripAll takes every pair gift off a B2B cart).\n  else if (window.b2bCompanyName) cdOnOfferArm();\n\n  // Sync cart count badge on page load\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', function () {\n      cdFetchCart().then(function (r) { return r.json(); }).then(function (cart) {\n        var count = cart.items.filter(function (i) { return !isEngravingItem(i); })\n          .reduce(function (n, i) { return n + i.quantity; }, 0);\n        document.querySelectorAll('.cart-count').forEach(function (el) { el.textContent = count; });\n      });\n    });\n  } else {\n    cdFetchCart().then(function (r) { return r.json(); }).then(function (cart) {\n      var count = cart.items.filter(function (i) { return !isEngravingItem(i); })\n        .reduce(function (n, i) { return n + i.quantity; }, 0);\n      document.querySelectorAll('.cart-count').forEach(function (el) { el.textContent = count; });\n    });\n  }\n  document.addEventListener('theme:cart:loaded', function () {\n    cdFetchCart().then(function (r) { return r.json(); }).then(function (cart) {\n      var count = cart.items.filter(function (i) { return !isEngravingItem(i); })\n        .reduce(function (n, i) { return n + i.quantity; }, 0);\n      document.querySelectorAll('.cart-count').forEach(function (el) { el.textContent = count; });\n    });\n  });\n\n  // Expose for customizer ATC callbacks\n  window.openCartDrawer = openDrawer;\n\n  // Discount apply / remove\n  document.addEventListener('click', function (e) {\n    if (e.target && e.target.id === 'cd-discount-btn') applyDiscount();\n    if (e.target && e.target.id === 'cd-discount-remove-btn') removeDiscount();\n  });\n  document.addEventListener('keydown', function (e) {\n    if (e.key === 'Enter' && e.target && e.target.id === 'cd-discount-input') applyDiscount();\n  });\n\n  // Intercept cart icon clicks\n  document.addEventListener('click', function (e) {\n    if (\n      e.target.closest('.js-drawer-open-button-right') ||\n      e.target.closest('.js-cart-icon') ||\n      e.target.closest('[aria-controls=\"CartDrawer\"]')\n    ) {\n      e.preventDefault();\n      e.stopImmediatePropagation();\n      // the customiser app clicks the cart icon for the customer after an approve; during the\n      // bottle-by-bottle personalise chain that synthetic click stays shut (a real tap still opens)\n      if (!e.isTrusted && window.cdHoldDrawerUntil && Date.now() < window.cdHoldDrawerUntil) return;\n      openDrawer();\n    }\n  }, true);\n\n})();\n\n"],
  "mappings": "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,8UAIA,yMAGA,+IACA,qCACA,sKACA,8EACA,0JACA,6KACA,wCACA,0EACA,qOACA,0EAEA,sKACA,+CACA,kIACA,0KACA,8DACA,2DACA,uDACA,0DACA,wGACA,uFACA,wFAEA,uIACA,iHAEA,4EACA,sLACA,0EACA,wJACA,mOACA,6FAEA,gGACA,iDACA,yFACA,kEACA,yDACA,yEACA,iDAEA,oEACA,qHACA,4NACA,iEACA,4DACA,0GACA,wOACA,uCACA,yGACA,mDACA,kIAEA,2SACA,4CACA,uCACA,iDAGA,2GACA,sDACA,0DACA,wIACA,sDACA,2FACA,iDACA,oCACA,yCACA,iCACA,mEACA,iGACA,mEACA,sEACA,uDACA,mCACA,uCACA,gGACA,2FACA,6EACA,sEACA,yFACA,8JACA,gDACA,iCAEA,qOACA,wFAEA,oEACA,oEACA,4CACA,6EAEA,+FACA,6DAEA,qFACA,qHACA,iHAEA,4JAEA,gDAEA,+EACA,oDACA,qEACA,6DACA,6GACA,6DACA,mFAEA,qDACA,0EACA,6IACA,iEACA,mDACA,0HACA,uEACA,wFACA,uCAEA,mJACA,gMACA,kFACA,kDAEA,qHACA,gEACA,yFACA,2IAEA,sCACA,iFACA,qEACA,kFACA,sHACA,qEAEA,uaACA,6CACA,kGAEA,qIACA,sHACA,iKACA,2DACA,2EAEA,6DACA,uKACA,4CACA,0JACA,mDAEA,iIACA,yEACA,sKACA,iDACA,uMACA,oDACA,8DACA,gEACA,+CACA,iDAEA,qIACA,wIACA,kEACA,8GACA,gEACA,uGACA,2HACA,sHACA,mFAEA,+EACA,yCAIA,4DACA,4EACA,oDACA,2CACA,2IACA,kDACA,4BACA,oDACA,2CAGA,uCACA,6FACA,qDACA,gFACA,uCACA,kDACA,+CACA,6CACA,0EACA,mDACA,iEACA,kDACA,8EAEA,mEACA,sFACA,wNACA,wCACA,iFACA,wEACA,6FACA,yRACA,gEACA,8FACA,+FACA,gEACA,2FACA,sOACA,6CACA,wDACA,4GACA,wDACA,yEACA,oEACA,+GACA,qCACA,0GACA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",
  "names": ["v"]
}
