{
  "version": 3,
  "sources": ["/cdn/shop/t/26/assets/tdhq-cart-drawer.js?b=20260923d"],
  "sourcesContent": ["/* ONE NOTICE (23 Oct 2026; restyled the same day, owner: the dark panels \"look AI made\", match our design, with an\n   icon). Every add message is a house panel - the Click & Collect panel's shape (32px round icon tile, bold title,\n   13px text) in the HQ Rewards bar's yellow for a stock limit, red when something failed, green when added (CSS\n   .tdhq-note in tdhq-core.css). TdhqNote.fill() dresses any element that way; TdhqNote.show() puts one over the\n   bottom of a product's picture (cards, quick view) and fades it after a few seconds, so nothing moves. The product\n   page's side notification (tdhq-pdp.js) is filled by the same builder. role=alert so it is announced. */\n(function () {\n  'use strict';\n  if (window.TdhqNote) return;\n  var ERR = /sold out|could not|couldn.t|try again|not available|unavailable|went wrong|error/i;\n  var LIMIT = /in your basket|in stock|we have/i;\n  function kindOf(message, kind) {\n    if (kind) { return kind; }\n    if (LIMIT.test(message) && !/sold out/i.test(message)) { return 'limit'; }\n    return ERR.test(message) ? 'error' : 'limit';\n  }\n  function titleOf(message, kind) {\n    if (kind === 'ok') { return 'Added to your basket'; }\n    if (kind === 'limit') { return 'Stock limit reached'; }\n    return /sold out/i.test(message) ? 'Sold out' : 'Could not add to basket';\n  }\n  function fill(el, message, kind, title) {\n    /* Shopify's own wording, said plainly: \"The product 'X - 1L' is already sold out.\" -> \"X - 1L is sold out.\" */\n    message = String(message).replace(/^The product '(.+)' is already sold out\\.?$/, '$1 is sold out.');\n    kind = kindOf(message, kind);\n    var icon = kind === 'ok' ? 'check' : kind === 'limit' ? 'basket' : 'alert';\n    el.setAttribute('data-kind', kind);\n    el.innerHTML = '<span class=\"tdhq-note__icon\"><svg class=\"tdhq-icon tdhq-g--' + icon + '\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\"></svg></span>' +\n      '<span class=\"tdhq-note__body\"><strong class=\"tdhq-note__title\"></strong><span class=\"tdhq-note__text\"></span></span>';\n    el.querySelector('.tdhq-note__title').textContent = title || titleOf(message, kind);\n    el.querySelector('.tdhq-note__text').textContent = message;\n    return el;\n  }\n  function hide(box) {\n    window.clearTimeout(box._t);\n    box.classList.remove('is-open');\n    box._t = window.setTimeout(function () { if (box.parentNode && !box.classList.contains('is-open')) { box.remove(); } }, 400);\n  }\n  window.TdhqNote = {\n    fill: fill,\n    show: function (host, message, ms, kind) {\n      if (!host || !message) { return; }\n      var box = null;\n      for (var i = 0; i < host.children.length; i++) { if (host.children[i].classList.contains('tdhq-note')) { box = host.children[i]; } }\n      if (!box) {\n        box = document.createElement('div');\n        box.className = 'tdhq-note';\n        box.setAttribute('role', 'alert');\n        host.appendChild(box);\n      }\n      fill(box, message, kind);\n      box.classList.remove('is-open');\n      void box.offsetWidth;\n      box.classList.add('is-open');\n      window.clearTimeout(box._t);\n      box._t = window.setTimeout(function () { hide(box); }, ms || 5000);\n    },\n    clear: function (host) {\n      if (!host) { return; }\n      for (var i = 0; i < host.children.length; i++) { if (host.children[i].classList.contains('tdhq-note')) { hide(host.children[i]); } }\n    }\n  };\n})();\n/* STUCK BASKET RECOVERY (23 Oct 2026, owner: signed in, every add answered \"The product '...' is already sold\n   out.\" although the item was in stock; signed out it worked). Measured: a bare /cart/add.js to that basket gave 422\n   for an item with 4 available, and a NEW basket for the same signed-in customer took it (200). A basket can be left\n   bound to a country we do not sell to (only the United Kingdom market is active; the EU and International markets\n   are drafts), and signing in brings the customer's saved basket back. Every add on the site goes through fetch, so\n   one guard covers the PDP, quick view, cards, kits and gift cards: when an add answers 422 \"sold out\", the basket is\n   set back to the United Kingdom and the add is sent again; if it still fails, a throwaway basket (no cookies) is\n   asked for the same item: when it takes it, the item is in stock and the shopper's basket is the problem, so its\n   lines (note, attributes and codes too) move to a fresh basket and the add is sent once more. A genuinely sold-out\n   item fails in the throwaway basket too and shows the same message, with the shopper's basket untouched. */\n(function () {\n  'use strict';\n  if (window.__tdhqAddGuard || !window.fetch) return;\n  window.__tdhqAddGuard = true;\n  var nativeFetch = window.fetch.bind(window);\n  var JSON_H = { 'Content-Type': 'application/json', 'Accept': 'application/json' };\n  function isAdd(input, init) {\n    var u = typeof input === 'string' ? input : (input && input.url) || '';\n    return /\\/cart\\/add(\\.js)?(\\?|$)/.test(u) && !!init && String(init.method || 'GET').toUpperCase() === 'POST';\n  }\n  function soldOut(res) {\n    if (!res || res.status !== 422) return Promise.resolve(false);\n    return res.clone().json().then(function (j) {\n      return /sold out/i.test((j && (j.description || j.message)) || '');\n    }, function () { return false; });\n  }\n  function toUK() {\n    var fd = new FormData();\n    fd.append('form_type', 'localization');\n    fd.append('utf8', '\\u2713');\n    fd.append('country_code', 'GB');\n    fd.append('return_to', '/cart.js');\n    return nativeFetch('/localization', { method: 'POST', body: fd, redirect: 'manual', credentials: 'same-origin' }).catch(function () {});\n  }\n  function variantId(init) {\n    var b = init && init.body;\n    try {\n      if (b && typeof b.get === 'function') return b.get('id') || b.get('items[][id]');\n      if (typeof b === 'string') {\n        if (b.charAt(0) === '{') { var j = JSON.parse(b); return j.id || (j.items && j.items[0] && j.items[0].id); }\n        return new URLSearchParams(b).get('id');\n      }\n    } catch (e) {}\n    return null;\n  }\n  function wantedQty(init) {\n    var b = init && init.body, q = 1;\n    try {\n      if (b && typeof b.get === 'function') q = b.get('quantity') || 1;\n      else if (typeof b === 'string' && b.charAt(0) === '{') { var j = JSON.parse(b); q = j.quantity || (j.items && j.items[0] && j.items[0].quantity) || 1; }\n      else if (typeof b === 'string') q = new URLSearchParams(b).get('quantity') || 1;\n    } catch (e) {}\n    return Math.max(1, parseInt(q, 10) || 1);\n  }\n  /* true only when the shopper's basket holds NONE of this item: a refusal while it holds some is the stock limit\n     (the last units are already in the basket), never a stuck basket (23 Oct 2026: a 1-in-stock coating reached 5) */\n  function basketLacks(init) {\n    var id = variantId(init);\n    if (!id) return Promise.resolve(false);\n    return nativeFetch('/cart.js', { headers: { 'Accept': 'application/json' }, credentials: 'same-origin' })\n      .then(function (r) { return r.json(); })\n      .then(function (c) { return !(c.items || []).some(function (it) { return String(it.variant_id) === String(id); }); }, function () { return false; });\n  }\n  /* true when a basket with no history (no cookies) takes the quantity asked for, i.e. that much really is in stock */\n  function inStockElsewhere(init) {\n    var id = variantId(init);\n    if (!id) return Promise.resolve(false);\n    return nativeFetch('/cart/add.js', { method: 'POST', headers: JSON_H, body: JSON.stringify({ items: [{ id: Number(id), quantity: wantedQty(init) }] }), credentials: 'omit' })\n      .then(function (r) { return r.ok; }, function () { return false; });\n  }\n  function freshBasket() {\n    return nativeFetch('/cart.js', { headers: { 'Accept': 'application/json' }, credentials: 'same-origin' })\n      .then(function (r) { return r.json(); })\n      .then(function (old) {\n        var past = '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';\n        document.cookie = 'cart' + past;\n        document.cookie = 'cart' + past + '; domain=.' + location.hostname.replace(/^www\\./, '');\n        var lines = (old.items || []).map(function (it) {\n          var l = { id: it.variant_id, quantity: it.quantity };\n          if (it.properties && Object.keys(it.properties).length) l.properties = it.properties;\n          if (it.selling_plan_allocation && it.selling_plan_allocation.selling_plan) l.selling_plan = it.selling_plan_allocation.selling_plan.id;\n          return l;\n        });\n        function addLines(list) {\n          return nativeFetch('/cart/add.js', { method: 'POST', headers: JSON_H, body: JSON.stringify({ items: list }), credentials: 'same-origin' });\n        }\n        var restore = !lines.length ? Promise.resolve() : addLines(lines).then(function (r) {\n          if (r.ok) return;\n          /* one line the fresh basket cannot take must not lose the others */\n          return lines.reduce(function (p, l) { return p.then(function () { return addLines([l]).catch(function () {}); }); }, Promise.resolve());\n        });\n        return restore.then(function () {\n          var upd = {};\n          if (old.note) upd.note = old.note;\n          if (old.attributes && Object.keys(old.attributes).length) upd.attributes = old.attributes;\n          var codes = (old.discount_codes || []).filter(function (d) { return d.applicable; }).map(function (d) { return d.code; });\n          if (codes.length) upd.discount = codes.join(',');\n          if (!Object.keys(upd).length) return;\n          return nativeFetch('/cart/update.js', { method: 'POST', headers: JSON_H, body: JSON.stringify(upd), credentials: 'same-origin' }).catch(function () {});\n        });\n      });\n  }\n  /* THE STOCK GATE (23 Oct 2026, owner: 5 of a 1-in-stock coating went in from the product page). Shopify takes every\n     oversell on this shop, so before ANY add is sent the basket is read and TdhqQty (tdhq-qty.js) is asked how many\n     may still go in; over that, nothing is sent and the add answers 422 with the plain reason ('The only one we have\n     is already in your basket.'), which the product page, cards and quick view already show. One line items only:\n     a kit's parts are checked by its own code. */\n  function oneLine(init) {\n    var b = init && init.body;\n    if (typeof b === 'string' && b.charAt(0) === '{') {\n      try { var j = JSON.parse(b); return !(j.items && j.items.length > 1); } catch (e) { return false; }\n    }\n    return true;\n  }\n  function overStock(init) {\n    var Q = window.TdhqQty, id = variantId(init);\n    if (!Q || !Q.readBasket || !Q.headroom || !id || !oneLine(init)) return Promise.resolve('');\n    return Q.readBasket().then(function () {\n      var room = Q.headroom(String(id));\n      if (room === null || room === undefined || wantedQty(init) <= room) return '';\n      return (Q.reason && Q.reason(String(id), 'add')) || 'We do not have any more of this in stock.';\n    }, function () { return ''; });\n  }\n  function refuse(msg) {\n    return new Response(JSON.stringify({ status: 422, message: msg, description: msg }), { status: 422, headers: { 'Content-Type': 'application/json' } });\n  }\n  window.fetch = function (input, init) {\n    if (!isAdd(input, init)) return nativeFetch(input, init);\n    return overStock(init).then(function (why) {\n      if (why) return refuse(why);\n      return send(input, init);\n    });\n  };\n  function send(input, init) {\n    return nativeFetch(input, init).then(function (res) {\n      return soldOut(res).then(function (stuck) {\n        if (!stuck) return res;\n        return toUK()\n          .then(function () { return nativeFetch(input, init); })\n          .then(function (res2) {\n            return soldOut(res2).then(function (still) {\n              if (!still) return res2;\n              return basketLacks(init).then(function (lacks) {\n                if (!lacks) return res2;\n                return inStockElsewhere(init);\n              }).then(function (real) {\n                if (real !== true) return res2;\n                return freshBasket().then(function () { return nativeFetch(input, init); }, function () { return res2; });\n              });\n            });\n          }, function () { return res; });\n      });\n    });\n  }\n})();\n\n/* ============================================================\n   TDHQ CART DRAWER - assets/tdhq-cart-drawer.js\n\n   Owns the slide-over basket: opening, closing, re-rendering, line\n   quantity and removal, the free-delivery meter and the cross-sell rail.\n\n   INTEGRATION NOTE. This script deliberately does NOT intercept\n   /cart/add submissions itself. Two other places already do that with\n   their own validation, busy states and failure fallbacks:\n\n     - assets/tdhq-quickadd.js  (quick add from a product card)\n     - sections/dtc-product-main.liquid  (the PDP buy form)\n\n   A third interceptor would either double-post the line or fight them for\n   preventDefault. Instead both of those dispatch `tdhq:cart:added` on\n   document after a confirmed add, and this script listens. One owner per\n   job: they own adding, this owns showing.\n   ============================================================ */\n(function () {\n  'use strict';\n\n  /* Shopify's JSON endpoints hand back UNSIZED originals (1500-2000px). The CDN\n     resizes on a `width` query parameter, so ask for what the box needs. Any\n     width already on the URL is replaced rather than duplicated. */\n  /* the site's one sized-picture helper (TdhqImg, layout head) */\n  function sizedImage(url, w) { return window.TdhqImg.sized(url, w); }\n\n  /* WALLETS FOR THE DEVICE (22 Oct 2026, owner: no Google Pay on an iPhone). Shopify lists the shop's wallets in\n     the wallet-configs attribute of its accelerated-checkout element and builds the buttons from that list, so on\n     an iPhone or iPad Google Pay - and its loading placeholder - is taken out before the element is put on the\n     page. Hiding a built button is not enough: Shopify sizes the row for every wallet it was given. Apple Pay is\n     only ever listed where the device has it. Anything unexpected leaves Shopify's markup as it came. */\n  var appleDevice = /iPhone|iPad|iPod/.test(navigator.userAgent || '') ||\n    (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);\n  function walletsForDevice(html) {\n    if (!appleDevice || !html) { return html; }\n    try {\n      var tpl = document.createElement('template');\n      tpl.innerHTML = html;\n      var host = tpl.content.querySelector('shopify-accelerated-checkout-cart');\n      if (!host) { return html; }\n      var list = JSON.parse(host.getAttribute('wallet-configs') || '[]');\n      var kept = list.filter(function (w) { return !w || w.name !== 'google_pay'; });\n      if (!kept.length || kept.length === list.length) { return html; }\n      host.setAttribute('wallet-configs', JSON.stringify(kept));\n      var cells = tpl.content.querySelectorAll('.wallet-cart-grid--skeleton > li');\n      if (cells.length === list.length) { cells[cells.length - 1].parentNode.removeChild(cells[cells.length - 1]); }\n      return tpl.innerHTML;\n    } catch (e) { return html; }\n  }\n  /* The basket page ships its wallets inert in a template (sections/dtc-cart.liquid); they go on the page here, and\n     again after every re-render of that section (its init() calls TdhqWallets.expand - Codex cartsheet-1022). */\n  function expandWallets(scope) {\n    var tpls = (scope || document).querySelectorAll('template[data-tdhq-wallets]');\n    for (var ti = 0; ti < tpls.length; ti++) {\n      var walletTpl = tpls[ti];\n      if (!walletTpl.parentNode) { continue; }\n      var walletBox = document.createElement('div');\n      walletBox.innerHTML = walletsForDevice(walletTpl.innerHTML);\n      while (walletBox.firstChild) { walletTpl.parentNode.insertBefore(walletBox.firstChild, walletTpl); }\n      walletTpl.parentNode.removeChild(walletTpl);\n    }\n  }\n  window.TdhqWallets = { expand: expandWallets };\n  expandWallets(document);\n\n  var root = document.querySelector('[data-tdhq-cart-drawer]');\n  if (!root || !('fetch' in window)) { return; }\n  /* U.42 (9 Oct): the sheet joins the header section, as the menu and Saved sheets do. The header section is\n     its own stacking context (sticky, z-index 900); while the sheet is up it is lifted to the sheet's old\n     level (html.tdhq-cd-up, tdhq-header.css) and the phone tab bar - outside the section since 21 Oct - is\n     lifted one above it, so the bar and the basket count riding above its edge stay in front. Moved while\n     still hidden. */\n  var hdrSec = document.querySelector('.tdhq-header-section');\n  if (hdrSec && root.parentNode !== hdrSec) { hdrSec.appendChild(root); }\n  /* Theme editor only: a header re-render throws the old section away with the sheet inside it. Park the sheet on\n     <body> as the old section goes and move it into the new one (21 Oct, Codex tabbar-body-1021). */\n  document.addEventListener('shopify:section:unload', function (e) {\n    if (e.target && e.target.contains && e.target.contains(root)) { document.body.appendChild(root); }\n  });\n  document.addEventListener('shopify:section:load', function () {\n    var hs = document.querySelector('.tdhq-header-section');\n    if (hs && root.parentNode !== hs) { hs.appendChild(root); }\n  });\n\n  var panel      = root.querySelector('[data-cd-panel]');\n  var itemsEl    = root.querySelector('[data-cd-items]');\n  var emptyEl    = root.querySelector('[data-cd-empty]');\n  var footEl     = root.querySelector('[data-cd-foot]');\n  var countEl    = root.querySelector('[data-cd-count]');\n  var subtotalEl = root.querySelector('[data-cd-subtotal]');\n  var shipEl     = root.querySelector('[data-cd-ship]');\n  var shipMsgEl  = root.querySelector('[data-cd-shipmsg]');\n  var shipFillEl = root.querySelector('[data-cd-shipfill]');\n  var recsEl     = root.querySelector('[data-cd-recs]');\n  var recsListEl = root.querySelector('[data-cd-recslist]');\n\n  var moneyFormat = root.getAttribute('data-cd-money') || '&pound;{{amount}}';\n  var lastFocused = null;\n  var lastCart = null;\n  var recsLoadedFor = null;\n  var lastAddedProductId = null;\n\n  /* ---------------------------------------------------------------\n     Money. Shopify returns cents; the shop's own money_format string\n     decides separators and decimals, so honour it rather than hard-coding\n     a pound sign \u2014 this theme is a white-label fork and gets reused.\n     --------------------------------------------------------------- */\n  function formatMoney(cents) {\n    var value = (cents || 0) / 100;\n\n    function withDelims(num, thousands, decimal, places) {\n      var fixed = num.toFixed(places);\n      var parts = fixed.split('.');\n      var whole = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, thousands);\n      return places > 0 && parts[1] ? whole + decimal + parts[1] : whole;\n    }\n\n    return moneyFormat.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, function (_, name) {\n      switch (name) {\n        case 'amount':                                   return withDelims(value, ',', '.', 2);\n        case 'amount_no_decimals':                       return withDelims(value, ',', '.', 0);\n        case 'amount_with_comma_separator':              return withDelims(value, '.', ',', 2);\n        case 'amount_no_decimals_with_comma_separator':  return withDelims(value, '.', ',', 0);\n        case 'amount_with_apostrophe_separator':         return withDelims(value, \"'\", '.', 2);\n        case 'amount_with_space_separator':              return withDelims(value, ' ', ',', 2);\n        case 'amount_no_decimals_with_space_separator':  return withDelims(value, ' ', ',', 0);\n        default:                                         return withDelims(value, ',', '.', 2);\n      }\n    });\n  }\n\n  /* Money format strings legitimately contain entities such as &pound;, and some\n     product titles come back HTML-escaped. Everything this script renders is\n     assigned with textContent, so the ONLY job here is turning an entity into the\n     character it denotes.\n\n     Deliberately not the usual `el.innerHTML = str; return el.value` textarea\n     trick. That is safe in itself \u2014 textarea content is RCDATA, so no elements\n     are constructed and nothing executes \u2014 but it puts an innerHTML assignment\n     fed by server data into a file people will copy from, and the next person to\n     reach for it may not be assigning into a textarea. An explicit table costs\n     nothing and cannot be misused. */\n  var ENTITIES = {\n    amp: '&', lt: '<', gt: '>', quot: '\"', apos: \"'\", nbsp: '\u00A0',\n    pound: '\u00A3', euro: '\u20AC', yen: '\u00A5', cent: '\u00A2',\n    reg: '\u00AE', copy: '\u00A9', trade: '\u2122',\n    hellip: '\u2026', mdash: '\u2014', ndash: '\u2013',\n    lsquo: '\u2018', rsquo: '\u2019', ldquo: '\u201C', rdquo: '\u201D',\n    deg: '\u00B0', times: '\u00D7', minus: '\u2212'\n  };\n\n  /* OPTION LABELS - the rules of snippets/tdhq-option-label.liquid, for the\n     lines this script draws itself (added items, recommendations). Keep the\n     two in step: display only, the posted values are never changed. */\n  var SIZE_CODES = {\n    xsmall: 'XS', xs: 'XS', extrasmall: 'XS', small: 'S', s: 'S', medium: 'M', m: 'M',\n    large: 'L', l: 'L', xlarge: 'XL', xl: 'XL', extralarge: 'XL',\n    xxlarge: '2XL', xxl: '2XL', '2xl': '2XL', '2xlarge': '2XL',\n    xxxlarge: '3XL', xxxl: '3XL', '3xl': '3XL', '3xlarge': '3XL',\n    '4xl': '4XL', '4xlarge': '4XL', xxxxl: '4XL', '5xl': '5XL', '5xlarge': '5XL'\n  };\n  function optKey(name) {\n    var n = String(name || '').trim().toLowerCase().replace(/color/g, 'colour')\n      .split(' (ml)').join('').split('(ml)').join('').split(' (clothing)').join('').split(' (mm/inch)').join('').trim();\n    if (n === 'sze' || n === 'bottle size' || n === 'bottle' || n === 'volume' || n === 'size (l)' || n === 'bottle size (ml)') { return 'size'; }\n    return n;\n  }\n  function optName(name) {\n    var n = optKey(name);\n    return n.charAt(0).toUpperCase() + n.slice(1);\n  }\n  /* Title case word by word; a word with a digit in it (\"205L\", \"0-3\") stays\n     as typed, the same rule as the Liquid snippet. */\n  function titleWords(v) {\n    return v.split(' ').map(function (w) {\n      return /[0-9]/.test(w) ? w : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n    }).join(' ');\n  }\n  function optValue(name, value) {\n    var n = optKey(name);\n    var v = String(value == null ? '' : value).trim();\n    var k = v.toLowerCase().replace(/[ .\\-]/g, '');\n    var k2 = v.toLowerCase().replace(/ /g, '');\n    if (n.indexOf('size') !== -1) {\n      if (SIZE_CODES[k]) { return SIZE_CODES[k]; }\n      if (/^[0-9]/.test(v) && /ml$/.test(k)) { return v.toLowerCase(); }\n      if (/^[0-9]/.test(v)) {\n        var lit = k2.match(/^(.*?)(litres|litre|ltr)$/);\n        if (lit) { return lit[1] + 'L'; }\n      }\n      if (v.length > 3 && v === v.toUpperCase() && v !== v.toLowerCase()) { return titleWords(v); }\n      return v;\n    }\n    if (k === 'mattblack') { v = 'Matt Black'; } else if (k === 'mattwhite') { v = 'Matt White'; }\n    if ((v.length > 3 && v === v.toUpperCase()) || v === v.toLowerCase() ||\n        (n.indexOf('colour') !== -1 && v === v.toUpperCase() && v !== v.toLowerCase())) {\n      return titleWords(v);\n    }\n    return v;\n  }\n  /* Titles as the server prints them: no en/em dashes (the client's copy\n     rule; the same chain as the Liquid title outputs). */\n  function cleanTitle(s) {\n    /* the site's one naming rule first (snippets/tdhq-name-js) */\n    if (window.tdhqName) { s = window.tdhqName(s); }\n    return String(s || '').split(' \\u2013 ').join(' - ').split(' \\u2014 ').join(' - ').split('\\u2014').join(' - ').split('\\u2013').join('-');\n  }\n\n  function optLine(pairs) {\n    return (pairs || []).filter(function (o) {\n      return o && o.name && o.value != null && !(o.name === 'Title' && /^Default/.test(String(o.value)));\n    }).map(function (o) { return optName(o.name) + ': ' + optValue(o.name, o.value); }).join(' \\u00B7 ');\n  }\n  function decodeEntities(str) {\n    if (str == null) { return ''; }\n    str = String(str);\n    if (str.indexOf('&') === -1) { return str; }\n    return str.replace(/&(#x?[0-9a-f]+|\\w+);/gi, function (whole, body) {\n      if (body.charAt(0) === '#') {\n        var hex = body.charAt(1) === 'x' || body.charAt(1) === 'X';\n        var code = parseInt(hex ? body.slice(2) : body.slice(1), hex ? 16 : 10);\n        /* Reject anything outside the Unicode range or in the surrogate block;\n           String.fromCodePoint throws on those and a title is not worth an\n           exception that empties the whole drawer. */\n        if (!isFinite(code) || code < 0 || code > 0x10FFFF || (code >= 0xD800 && code <= 0xDFFF)) {\n          return whole;\n        }\n        return String.fromCodePoint(code);\n      }\n      var named = ENTITIES[body.toLowerCase()];\n      return named === undefined ? whole : named;\n    });\n  }\n\n  function money(cents) { return decodeEntities(formatMoney(cents)); }\n\n  /* Published for the basket PAGE, which needs the same shop money_format to\n     paint figures straight from a /cart/change.js payload. One implementation,\n     one set of separator rules, so the drawer and the page can never disagree\n     about how a price is written. */\n  window.tdhqFormatMoney = money;\n\n  /* THE PAYABLE FIGURE (requirement CART-01). Once the basket page's delivery\n     estimator has asked Shopify for rates, every /cart/change.js answer carries\n     a total_price that INCLUDES the first delivery rate (measured 2026-09-23:\n     goods 540, total_price 935 with Express at 3.95) while /cart.js says 540.\n     The drawer painted that figure as the Estimated total, so a quantity change\n     after an estimate showed the delivery twice over. The payable figure is\n     rebuilt from the parts every answer agrees on: the goods after line\n     discounts, less the basket-level discounts. Published for the basket page,\n     so both baskets use one rule. */\n  function payable(cart) {\n    if (!cart) { return 0; }\n    var cut = (cart.cart_level_discount_applications || []).reduce(function (a, d) {\n      return a + (d.total_allocated_amount || 0);\n    }, 0);\n    return (cart.items_subtotal_price != null ? cart.items_subtotal_price : cart.total_price) - cut;\n  }\n  window.tdhqCartPayable = payable;\n\n  function reduceMotion() {\n    return window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n  }\n\n  /* A figure that moved gets the basket page's highlight, a wash behind the\n     number (MOT-07): the drawer used to rebuild every line with no sign of\n     which number had changed. Restarted if it is already running. */\n  function setFigure(el, text) {\n    if (!el || el.textContent.trim() === String(text).trim()) { return; }\n    el.textContent = text;\n    if (!isOpen()) { return; }\n    el.classList.remove('is-changed');\n    void el.offsetWidth;\n    el.classList.add('is-changed');\n    window.setTimeout(function () { el.classList.remove('is-changed'); }, 700);\n  }\n\n  /* COMPARE-AT PRICES (audit UNI-17). A sale line shows the old price struck\n     through over the price in the sale red, as the card and the product page\n     do. /cart.js carries no compare-at price, so the drawer learns it the way\n     it learns stock ceilings: from Liquid (each server-rendered line states\n     its variant's compare-at price), and for a line added later from the\n     product's own .js, which does carry it. Kept for the session. */\n  var WAS_KEY = 'tdhq:was';\n  var wasMap = {};\n  var wasAsked = {};\n  try { wasMap = JSON.parse(window.sessionStorage.getItem(WAS_KEY) || '{}') || {}; } catch (e) { wasMap = {}; }\n  function keepWas() {\n    try { window.sessionStorage.setItem(WAS_KEY, JSON.stringify(wasMap)); } catch (e) {}\n  }\n  function seedWas(scope) {\n    var lines = (scope || document).querySelectorAll('[data-cd-item][data-cd-was]');\n    for (var i = 0; i < lines.length; i++) {\n      var k = (lines[i].getAttribute('data-key') || '').split(':')[0];\n      if (k) { wasMap[k] = parseInt(lines[i].getAttribute('data-cd-was'), 10) || 0; }\n    }\n    keepWas();\n  }\n  function wasOf(item) {\n    var id = String(item.id);\n    if (Object.prototype.hasOwnProperty.call(wasMap, id)) { return wasMap[id] || 0; }\n    askWas(item.handle);\n    return 0;\n  }\n  function askWas(handle) {\n    if (!handle || wasAsked[handle]) { return; }\n    wasAsked[handle] = true;\n    fetch('/products/' + encodeURIComponent(handle) + '.js', { headers: { 'Accept': 'application/json' } })\n      .then(function (r) { return r.ok ? r.json() : null; })\n      .then(function (p) {\n        if (!p || !p.variants) { return; }\n        p.variants.forEach(function (v) { wasMap[String(v.id)] = v.compare_at_price || 0; });\n        keepWas();\n        if (lastCart && itemsEl) {\n          lastCart.items.forEach(function (item) {\n            var li = itemsEl.querySelector('[data-cd-item][data-key=\"' + esc(item.key) + '\"]');\n            if (li) { paintWas(li.querySelector('.tdhq-cd__money'), item); }\n          });\n        }\n      })\n      .catch(function () {});\n  }\n  function paintWas(box, item) {\n    if (!box) { return; }\n    var price = box.querySelector('.tdhq-cd__price');\n    var s = box.querySelector('.tdhq-cd__was');\n    /* struck: the compare-at price on a sale, or the price before an automatic\n       discount (the kit's Buy X get Y), whichever is larger */\n    var unit = wasOf(item);\n    var wasLine = unit > (item.original_price || item.price || 0) ? unit * item.quantity : 0;\n    if ((item.original_line_price || 0) > (item.final_line_price || 0) && item.original_line_price > wasLine) { wasLine = item.original_line_price; }\n    if (wasLine > (item.final_line_price || 0)) {\n      if (!s) {\n        s = document.createElement('s');\n        s.className = 'tdhq-cd__was';\n        var sr = document.createElement('span');\n        sr.className = 'tdhq-visually-hidden';\n        sr.textContent = 'Was ';\n        s.appendChild(sr);\n        var v = document.createElement('span');\n        v.setAttribute('data-cd-was-val', '');\n        s.appendChild(v);\n        box.insertBefore(s, price);\n      }\n      s.querySelector('[data-cd-was-val]').textContent = money(wasLine);\n      if (price) { price.classList.add('tdhq-cd__price--sale'); }\n    } else {\n      if (s) { s.remove(); }\n      if (price) { price.classList.remove('tdhq-cd__price--sale'); }\n    }\n  }\n\n  /* The last product the shopper looked at, from the recently viewed list the\n     product page keeps. Seeds the suggestions when the basket is empty. */\n  function recentProductId() {\n    try {\n      var list = JSON.parse(window.localStorage.getItem('dtc_recent_v1')) || [];\n      for (var i = 0; i < list.length; i++) { if (list[i] && list[i].id) { return list[i].id; } }\n    } catch (e) {}\n    return null;\n  }\n\n  /* ---------------------------------------------------------------\n     Open / close\n     --------------------------------------------------------------- */\n  function isOpen() { return root.classList.contains('is-open'); }\n\n  /* The header basket is a real <a href=\"/cart\">, and it stays one: with no\n     JavaScript it must still go to the cart page. But WITH this script it does\n     not navigate - it opens a modal - and it was announcing itself as a plain\n     link to /cart, giving no hint that a dialog was about to appear and no way\n     to know whether it was already open.\n\n     The promise is made HERE rather than in the Liquid, because this file is\n     what keeps it: markup that claims aria-haspopup=\"dialog\" while the script\n     that opens the dialog failed to load is a worse lie than the plain link. */\n  function cartLinks() {\n    return document.querySelectorAll('[data-tdhq-cart-link]');\n  }\n\n  function announceDrawerControl(expanded) {\n    var links = cartLinks();\n    for (var i = 0; i < links.length; i++) {\n      links[i].setAttribute('aria-haspopup', 'dialog');\n      links[i].setAttribute('aria-controls', 'tdhqCartDrawerPanel');\n      links[i].setAttribute('aria-expanded', expanded ? 'true' : 'false');\n    }\n  }\n  announceDrawerControl(false);\n\n  /* The basket link lives in the HEADER section. When the theme editor\n     re-renders that section the link is a brand new element with none of the\n     dialog semantics on it, and this file - which lives in the layout, not the\n     section - never notices. One line to re-apply them. */\n  document.addEventListener('shopify:section:load', function () {\n    announceDrawerControl(isOpen());\n  });\n\n  function open() {\n    if (isOpen()) { return; }\n    lastFocused = document.activeElement;\n    root.hidden = false;\n    document.documentElement.classList.add('tdhq-cd-up');\n    /* The panel must be laid out in its CLOSED state before `is-open` flips it,\n       or the browser has no \"from\" value and the transform snaps into place\n       instead of sliding. Reading offsetHeight forces that layout synchronously,\n       which is deterministic - the double requestAnimationFrame this replaced\n       was not: rAF does not run in a background tab, and this function has\n       already put `tdhq-cd-open` on <html>, so a callback that never arrives\n       left the page scroll-locked behind a drawer that never appeared. */\n    void root.offsetHeight;\n    root.classList.add('is-open');\n    document.documentElement.classList.add('tdhq-cd-open');\n    document.body.classList.add('tdhq-cd-open');\n    var closeBtn = root.querySelector('[data-cd-close]:not(.tdhq-cd__scrim)');\n    if (closeBtn && closeBtn.focus) { closeBtn.focus(); }\n    announceDrawerControl(true);\n    express(lastCart ? lastCart.item_count : Number((countEl && countEl.textContent) || 0));\n  }\n\n  /* EXPRESS CHECKOUT (21 Oct 2026): Shop Pay / PayPal / Apple Pay / Google Pay, the block the basket page shows.\n     It carries Shopify's wallet set-up and wakes the wallets' scripts, so it is fetched once, through the Section\n     Rendering API, the first time the drawer is open with something in it, and then kept. Shopify's buttons read\n     the basket when pressed, so later changes need no refetch; an empty basket only hides them. */\n  var expressEl = root.querySelector('[data-cd-express]');\n  var expressSlot = root.querySelector('[data-cd-express-slot]');\n  var expressState = 0; /* 0 not asked, 1 asking, 2 shown, 3 shop has none */\n  function express(count) {\n    if (!expressEl || !expressSlot) { return; }\n    if (!count) { expressEl.hidden = true; return; }\n    if (expressState === 2) { expressEl.hidden = false; return; }\n    if (expressState !== 0 || !isOpen()) { return; }\n    expressState = 1;\n    /* the basket route, and no JSON Accept header: '/?sections=' sent as JSON came back without the buttons */\n    var base = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/';\n    fetch(base + 'cart?sections=tdhq-express-checkout')\n      .then(function (r) { return r.ok ? r.json() : null; })\n      .then(function (d) {\n        var html = d && d['tdhq-express-checkout'];\n        if (!html || html.indexOf('accelerated-checkout') === -1) { expressState = 3; return; }\n        expressSlot.innerHTML = walletsForDevice(html);\n        expressState = 2;\n        expressEl.hidden = !(lastCart ? lastCart.item_count : count);\n      })\n      .catch(function () { expressState = 0; });\n  }\n\n  function close() {\n    if (!isOpen()) { return; }\n    root.classList.remove('is-open');\n    document.documentElement.classList.remove('tdhq-cd-open');\n    document.body.classList.remove('tdhq-cd-open');\n    /* keep it in the tree until the slide-out finishes, then hide it from\n       assistive tech and tab order */\n    window.setTimeout(function () {\n      if (!isOpen()) { root.hidden = true; document.documentElement.classList.remove('tdhq-cd-up'); }\n    }, window.TdhqMotion && window.TdhqMotion.calm() ? 0 : 340);\n    if (lastFocused && lastFocused.focus) { lastFocused.focus(); }\n    lastFocused = null;\n    announceDrawerControl(false);\n  }\n\n  /* ---------------------------------------------------------------\n     Rendering\n     --------------------------------------------------------------- */\n  /* Lines Liquid told us cannot be shipped. Seeded from the server-rendered\n     drawer on boot and re-applied on every re-render, because /cart.js does not\n     report availability and asking per variant would cost a request per line.\n     A line added during the session is one the shopper just added successfully,\n     so this set never needs to grow on its own. */\n  var goneKeys = {};\n  Array.prototype.forEach.call(\n    (root && root.querySelectorAll('[data-cd-item][data-cd-gone]')) || [],\n    function (el) { goneKeys[el.getAttribute('data-key')] = true; }\n  );\n\n  function lineNode(item) {\n    var li = document.createElement('li');\n    li.className = 'tdhq-cd__item';\n    li.setAttribute('data-cd-item', '');\n    li.setAttribute('data-key', item.key);\n    if (goneKeys[item.key]) {\n      li.className += ' tdhq-cd__item--gone';\n      li.setAttribute('data-cd-gone', '');\n    }\n\n    var thumb = document.createElement('a');\n    thumb.className = 'tdhq-cd__thumb';\n    thumb.href = item.url;\n    thumb.tabIndex = -1;\n    thumb.setAttribute('aria-hidden', 'true');\n    if (item.image) {\n      var img = document.createElement('img');\n      /* the line's box is 62px on a phone and 74px from 600px: the browser\n         takes the file its screen needs (240 covers the phone at 3x) */\n      img.sizes = '(max-width: 599px) 62px, 74px';\n      img.srcset = sizedImage(item.image, 80) + ' 80w, ' + sizedImage(item.image, 160) + ' 160w, ' + sizedImage(item.image, 240) + ' 240w';\n      img.src = sizedImage(item.image, 240);\n      img.alt = '';\n      img.loading = 'lazy';\n      img.setAttribute('data-tdhq-fit', 'thumb');\n      thumb.appendChild(img);\n    }\n    li.appendChild(thumb);\n\n    var info = document.createElement('div');\n    info.className = 'tdhq-cd__info';\n\n    var name = document.createElement('a');\n    name.className = 'tdhq-cd__name';\n    name.href = item.url;\n    name.textContent = cleanTitle(decodeEntities(item.product_title || item.title));\n    info.appendChild(name);\n\n    /* The options as the product page prints them (\"Size: 500ml\"), from the\n       line's own options_with_values; the raw variant title only if a\n       response ever lacks them. */\n    var vTitle = optLine(item.options_with_values || []) ||\n      ((item.variant_title && item.variant_title.indexOf('Default') === -1) ? item.variant_title : '');\n    if (vTitle) {\n      var v = document.createElement('p');\n      v.className = 'tdhq-cd__variant';\n      v.textContent = decodeEntities(vTitle);\n      info.appendChild(v);\n    }\n\n    /* A line on a plan (the monthly Trade Membership) names the plan, as the\n       Liquid render and checkout do, and keeps its quantity: one membership\n       per account, so it gets the quantity box without - and +. */\n    var onPlan = !!(item.selling_plan_allocation && item.selling_plan_allocation.selling_plan);\n    if (onPlan) {\n      var sp = document.createElement('p');\n      sp.className = 'tdhq-cd__variant';\n      sp.textContent = decodeEntities(item.selling_plan_allocation.selling_plan.name || '');\n      info.appendChild(sp);\n    }\n\n    /* The line's own properties, as snippets/tdhq-line-props prints them (U.50): a gift card's recipient,\n       send date and message. Keys starting with \"_\" are Shopify's own. */\n    var props = item.properties || {};\n    Object.keys(props).forEach(function (k) {\n      var val = props[k] == null ? '' : String(props[k]).trim();\n      if (!k || k.charAt(0) === '_' || !val) { return; }\n      if (k === 'Send on' && /^\\d{4}-\\d{2}-\\d{2}$/.test(val)) {\n        var dp = val.split('-');\n        val = parseInt(dp[2], 10) + ' ' + ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][parseInt(dp[1], 10) - 1] + ' ' + dp[0];\n      }\n      var pp = document.createElement('p');\n      pp.className = 'tdhq-cd__variant tdhq-lineprop';\n      var pk = document.createElement('span');\n      pk.className = 'tdhq-lineprop__k';\n      pk.textContent = k + ':';\n      pp.appendChild(pk);\n      pp.appendChild(document.createTextNode(' ' + val));\n      info.appendChild(pp);\n    });\n\n    /* Price per litre or kilo, as the Liquid render writes it with\n       unit_price_with_measurement: price, \"/\", the reference amount when it\n       is not 1, the unit (\"\u00A32.19/100ml\", \"\u00A321.90/L\"). */\n    var um = item.unit_price_measurement;\n    if (um && item.unit_price != null && um.reference_unit) {\n      var up = document.createElement('p');\n      up.className = 'tdhq-cd__unit';\n      var upSr = document.createElement('span');\n      upSr.className = 'tdhq-visually-hidden';\n      upSr.textContent = 'Unit price ';\n      up.appendChild(upSr);\n      var unitName = um.reference_unit === 'l' ? 'L' : um.reference_unit;\n      up.appendChild(document.createTextNode(money(item.unit_price) + '/' + (um.reference_value && um.reference_value !== 1 ? um.reference_value : '') + unitName));\n      info.appendChild(up);\n    }\n\n    var row = document.createElement('div');\n    row.className = 'tdhq-cd__row';\n\n    /* Carry the ceiling onto the rebuilt row. The server's <li> states it,\n       and this row replaces that <li> - without this the attribute exists only\n       until the first render and the line becomes unjudgeable. */\n    if (window.TdhqQty) {\n      var lineCap = window.TdhqQty.stock(String(item.id));\n      li.setAttribute('data-cd-max', lineCap === null ? '0' : String(lineCap));\n    }\n\n    var qty = document.createElement('div');\n    qty.className = 'tdhq-cd__qty' + (onPlan ? ' tdhq-cd__qty--plan' : '');\n    qty.setAttribute('data-cd-qty', '');\n    if (!onPlan) { qty.appendChild(stepBtn('-1', 'Decrease quantity of ' + cleanTitle(decodeEntities(item.product_title || item.title)))); }\n    var val = document.createElement('span');\n    val.className = 'tdhq-cd__qtyval';\n    val.setAttribute('data-cd-qtyval', '');\n    val.textContent = item.quantity;\n    qty.appendChild(val);\n    if (!onPlan) { qty.appendChild(stepBtn('1', 'Increase quantity of ' + cleanTitle(decodeEntities(item.product_title || item.title)))); }\n    row.appendChild(qty);\n\n    var box = document.createElement('span');\n    box.className = 'tdhq-cd__money';\n    var price = document.createElement('span');\n    price.className = 'tdhq-cd__price';\n    price.textContent = money(item.final_line_price);\n    box.appendChild(price);\n    paintWas(box, item);\n    row.appendChild(box);\n    info.appendChild(row);\n\n    if (goneKeys[item.key]) {\n      var goneNote = document.createElement('p');\n      goneNote.className = 'tdhq-cd__gone';\n      goneNote.setAttribute('role', 'status');\n      goneNote.textContent = 'Out of stock. Remove to continue';\n      info.appendChild(goneNote);\n    }\n\n    var rm = document.createElement('button');\n    rm.type = 'button';\n    rm.className = 'tdhq-cd__remove';\n    rm.setAttribute('data-cd-remove', '');\n    rm.setAttribute('aria-label', 'Remove ' + cleanTitle(decodeEntities(item.product_title || item.title)) + ' from basket');\n    rm.textContent = 'Remove';\n    info.appendChild(rm);\n\n    li.appendChild(info);\n    /* The ceiling is known by now (seeded above from the server's lines or\n       from a product page earlier in the session), so the \"+\" and the stock\n       note are drawn in their correct state rather than going dead on the\n       first press. Here, once the line is complete, and NOT on a timer: a\n       timer let the rebuilt list paint one frame without the note, so every\n       line under a line at its ceiling jumped 33px up and back down when\n       another line was removed (measured at 390). */\n    paintLineCap(li);\n    return li;\n  }\n\n  /* The +/- glyphs are inline SVG in the server-rendered markup; rebuilding\n     them here would duplicate the icon set in JS. A character is indistinguishable\n     at 14px and the accessible name lives on the button's aria-label. */\n  function stepBtn(delta, label) {\n    var b = document.createElement('button');\n    b.type = 'button';\n    b.className = 'tdhq-cd__step';\n    b.setAttribute('data-cd-step', delta);\n    b.setAttribute('aria-label', label);\n    b.textContent = delta === '1' ? '+' : '\u2212';\n    return b;\n  }\n\n  function render(cart) {\n    if (!cart) { return; }\n\n    /* The line list is rebuilt from scratch on every change, so whatever the\n       shopper had focused is destroyed - a keyboard or screen-reader user was\n       thrown to the top of the document on every single + or -. Remember the\n       control by its line key and role, and put focus back on the equivalent\n       control in the new markup. */\n    var wasFocused = null;\n    var active = document.activeElement;\n    if (active && root.contains(active)) {\n      var owner = active.closest('[data-cd-item]');\n      if (owner) {\n        wasFocused = {\n          key: owner.getAttribute('data-key'),\n          step: active.getAttribute('data-cd-step'),\n          remove: active.hasAttribute('data-cd-remove')\n        };\n      }\n    }\n\n    lastCart = cart;\n    var due = payable(cart);\n    if (countEl) { countEl.textContent = cart.item_count; }\n    setFigure(subtotalEl, money(due));\n\n    /* Saving row, printed hidden by Liquid in the footer and shown here the\n       moment a saving appears (audit cart-07). */\n    var savingEl = root.querySelector('[data-cd-saving]');\n    var saved = (cart.original_total_price || due) - due;\n    if (savingEl) {\n      if (saved > 0) { savingEl.textContent = 'You save ' + money(saved); savingEl.hidden = false; }\n      else { savingEl.hidden = true; }\n    }\n\n    var empty = cart.item_count === 0;\n    express(cart.item_count);\n    if (emptyEl) {\n      var emptyWas = emptyEl.hidden;\n      emptyEl.hidden = !empty;\n      /* the empty-basket message arrives the way content does (APPEAR values), after the last line has closed */\n      if (emptyWas && empty && isOpen() && window.TdhqMotion) { window.TdhqMotion.rise(emptyEl, 0); }\n    }\n    if (itemsEl) { itemsEl.hidden = empty; }\n    if (footEl) { footEl.hidden = empty; }\n    if (shipEl) { shipEl.hidden = empty; }\n\n    /* SAME LINES, UPDATED IN PLACE (audit cart-10, MOT-07). Every change used\n       to empty the list and rebuild every line, image and button from /cart.js:\n       the line the shopper was pressing was replaced mid-gesture, it snapped\n       from its busy dim straight back to full, and nothing said which figure\n       had moved. When the basket holds the same lines in the same order, only\n       the digits and prices are written, the moved price is highlighted, and\n       the line fades back up. A different set of lines is rebuilt as before. */\n    if (itemsEl) {\n      var have = Array.prototype.filter.call(itemsEl.children, function (li) { return li.hasAttribute('data-cd-item'); });\n      var same = have.length === cart.items.length && cart.items.every(function (item, i) {\n        return have[i].getAttribute('data-key') === item.key;\n      });\n      if (same) {\n        cart.items.forEach(function (item, i) { updateLine(have[i], item); });\n      } else {\n        /* A DIFFERENT SET OF LINES (21 Oct, owner: an add \"just appears\" while a removal closes). Lines still in\n           the basket are updated in place - rebuilding them re-loaded every picture and the whole list blinked on\n           each add. A new line is built and opens in; a line no longer in the basket closes where it is. All of it\n           through TdhqMotion, the site's one motion system, and only while the drawer is open. */\n        var M = window.TdhqMotion, moving = !!M && isOpen();\n        var byKey = {}, wanted = {};\n        have.forEach(function (li) { byKey[li.getAttribute('data-key')] = li; });\n        cart.items.forEach(function (item) { wanted[item.key] = true; });\n        have.forEach(function (li) {\n          if (wanted[li.getAttribute('data-key')]) { return; }\n          li.removeAttribute('data-cd-item');\n          if (moving) { M.exit(li, function () { li.remove(); }); } else { li.remove(); }\n        });\n        var prev = null;\n        cart.items.forEach(function (item) {\n          var li = byKey[item.key], fresh = !li;\n          if (fresh) {\n            li = lineNode(item);\n            /* A line with a newer tap still on its way keeps the number the\n               shopper asked for, and stays dimmed until that tap settles. */\n            if (cdTargets[item.key] !== undefined) {\n              var qv = li.querySelector('[data-cd-qtyval]');\n              /* a pending removal keeps the basket's number, as queueLine does */\n              if (qv && cdTargets[item.key] > 0) { qv.textContent = cdTargets[item.key]; paintLineCap(li); }\n              li.classList.add('is-busy');\n            }\n          } else {\n            updateLine(li, item);\n          }\n          var at = prev ? prev.nextSibling : itemsEl.firstChild;\n          if (li !== at) { itemsEl.insertBefore(li, at); }\n          prev = li;\n          if (fresh && moving) { M.enter(li); }\n        });\n      }\n    }\n\n    renderShip(cart);\n    renderPartner(cart);\n    syncHeader(cart);\n\n    /* An empty basket offers products too (audit cart-23): the rail is seeded\n       from the last product the shopper viewed, and hides only when there is\n       none. The heading reads \"You may also like\" here, not \"need\". */\n    var recsTitle = recsEl && recsEl.querySelector('.tdhq-cd__recstitle');\n    if (recsTitle) { recsTitle.textContent = empty ? 'You may also like' : 'You may also need'; }\n    if (recsEl) { recsEl.setAttribute('aria-label', empty ? 'You may also like' : 'You may also need'); }\n    if (empty) {\n      var seen = recentProductId();\n      if (seen) { loadRecs(seen); }\n      else {\n        if (recsEl) { recsEl.hidden = true; }\n        recsLoadedFor = null;\n      }\n    } else {\n      /* Seeded from the product the shopper just added, not from whatever\n         happens to sit first in the basket - `cart.items[0]` is the OLDEST line,\n         so the rail recommended things to go with something added days ago.\n         The add sites pass the product id in the event detail; the newest line\n         is the fallback when they cannot. */\n      var seedId = lastAddedProductId ||\n        (cart.items.length ? cart.items[cart.items.length - 1].product_id : null);\n      loadRecs(seedId);\n    }\n\n    if (wasFocused && wasFocused.key) {\n      var line = root.querySelector('[data-cd-item][data-key=\"' + (window.CSS && CSS.escape ? CSS.escape(wasFocused.key) : wasFocused.key) + '\"]');\n      var target = null;\n      if (line) {\n        target = wasFocused.remove\n          ? line.querySelector('[data-cd-remove]')\n          : line.querySelector('[data-cd-step=\"' + wasFocused.step + '\"]');\n      }\n      /* The line may be gone (quantity taken to zero). Fall back to the panel\n         itself rather than letting focus fall out of the drawer entirely. */\n      if (!target) { target = root.querySelector('[data-cd-close]:not(.tdhq-cd__scrim)'); }\n      if (target && target.focus) { target.focus({ preventScroll: true }); }\n    }\n  }\n\n  function updateLine(li, item) {\n    var pending = cdTargets[item.key] !== undefined;\n    var valEl = li.querySelector('[data-cd-qtyval]');\n    if (valEl && !pending) { valEl.textContent = item.quantity; }\n    setFigure(li.querySelector('.tdhq-cd__price'), money(item.final_line_price));\n    paintWas(li.querySelector('.tdhq-cd__money'), item);\n    if (window.TdhqQty) {\n      var lineCap = window.TdhqQty.stock(String(item.id));\n      li.setAttribute('data-cd-max', lineCap === null ? '0' : String(lineCap));\n    }\n    /* The request succeeded, so whatever the line was last told off for no\n       longer applies (a refused change re-writes its message after this). */\n    var err = li.querySelector('.tdhq-cd__lineerr');\n    if (err) { err.remove(); }\n    if (!pending) {\n      li.classList.remove('is-busy');\n      li.removeAttribute('aria-busy');\n    }\n    paintLineCap(li);\n  }\n\n  function renderShip(cart) {\n    if (!shipEl || !shipMsgEl || !shipFillEl) { return; }\n    var threshold = parseInt(shipEl.getAttribute('data-cd-threshold'), 10);\n    if (!threshold || threshold <= 0) { shipEl.hidden = true; return; }\n\n    /* U.50: Shopify does not count its own gift card products towards a price-based free delivery rate,\n       and a digital card is never posted. The meter measures the rest of the basket, and says nothing at\n       all when nothing in the basket needs posting. */\n    var cdItems = (cart && cart.items) || [];\n    var noPost = cdItems.length > 0 && !cdItems.some(function (i) { return i.requires_shipping; });\n    if (noPost) { shipEl.hidden = true; shipEl.setAttribute('data-cd-nopost', '1'); return; }\n    if (shipEl.hasAttribute('data-cd-nopost')) { shipEl.hidden = false; shipEl.removeAttribute('data-cd-nopost'); }\n    var gcLines = cdItems.reduce(function (a, i) { return a + (i.gift_card ? (i.final_line_price || 0) : 0); }, 0);\n    var total = payable(cart) - gcLines;\n    var remaining = threshold - total;\n    var pct = Math.max(0, Math.min(100, (total / threshold) * 100));\n\n    shipFillEl.style.width = pct + '%';\n    shipMsgEl.textContent = '';\n\n    if (remaining <= 0) {\n      /* the moment the basket crosses the line, once (not on the first paint) */\n      if (!shipEl.classList.contains('is-met') && shipEl.getAttribute('data-cd-painted') === '1' &&\n          !(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches)) {\n        shipEl.classList.add('is-just-met');\n        window.setTimeout(function () { shipEl.classList.remove('is-just-met'); }, 900);\n      }\n      shipEl.classList.add('is-met');\n      var met = document.createElement('strong');\n      met.textContent = 'You get free Royal Mail Tracked\u00A024 delivery.';\n      shipMsgEl.appendChild(met);\n    } else {\n      shipEl.classList.remove('is-met');\n      shipMsgEl.appendChild(document.createTextNode('Spend '));\n      var amt = document.createElement('strong');\n      amt.textContent = money(remaining);\n      shipMsgEl.appendChild(amt);\n      shipMsgEl.appendChild(document.createTextNode(' more for free Tracked\u00A024 delivery.'));\n    }\n    shipEl.setAttribute('data-cd-painted', '1');\n  }\n\n  /* PARTNER BRAND NOTE. /cart.js carries no tags, so a line's Shopify Collective tag is read once from the product's\n     own .js (tags included) and remembered for the session; Liquid seeds the first paint. */\n  var partnerTag = {};\n  var partnerCart = null;\n  function renderPartner(cart) {\n    var el = root.querySelector('[data-cd-partner]');\n    if (!el || !cart) { return; }\n    partnerCart = cart;\n    var handles = (cart.items || []).map(function (it) { return it.handle; });\n    el.hidden = !handles.some(function (h) { return partnerTag[h] === true; });\n    handles.forEach(function (h) {\n      if (h in partnerTag) { return; }\n      partnerTag[h] = null;\n      fetch('/products/' + encodeURIComponent(h) + '.js', { headers: { Accept: 'application/json' } })\n        .then(function (r) { return r.ok ? r.json() : null; })\n        .then(function (p) {\n          partnerTag[h] = !!(p && (p.tags || []).indexOf('Shopify Collective') > -1);\n          if (partnerTag[h] && partnerCart) { renderPartner(partnerCart); }\n        })\n        .catch(function () { partnerTag[h] = false; });\n    });\n  }\n\n  /* The header badge is server-rendered on load; after an Ajax change it is the\n     only part of the page outside the drawer that is now stale. */\n  function syncHeader(cart) {\n    document.querySelectorAll('[data-tdhq-cart-count]').forEach(function (el) {\n      var sr = el.querySelector('.tdhq-visually-hidden, .visually-hidden');\n      el.textContent = cart.item_count;\n      if (sr) {\n        sr.textContent = cart.item_count === 1 ? 'item in basket' : 'items in basket';\n        el.appendChild(sr);\n      }\n      el.classList.toggle('tdhq-hidden', cart.item_count === 0);\n    });\n    document.querySelectorAll('[data-tdhq-cart-total]').forEach(function (el) {\n      el.textContent = money(payable(cart));\n    });\n  }\n\n  /* ---------------------------------------------------------------\n     Cross-sell. Shopify's own recommendation endpoint, so it stays\n     relevant without anyone maintaining a list.\n     --------------------------------------------------------------- */\n  function loadRecs(productId) {\n    if (!recsEl || !recsListEl || !productId) { return; }\n    if (recsLoadedFor === productId) { return; }\n    recsLoadedFor = productId;\n\n    /* `complementary` is the better rail - it is the merchant's own \"goes with\n       this\" list - but it only returns anything once complementary products\n       have been set up in Shopify's Search & Discovery app, and on this store\n       nothing has been: the endpoint answers 200 with an empty list for every\n       product, so the rail was always hidden and the drawer never offered\n       anything. `related` is Shopify's automatic fallback and does return\n       products, so it is used whenever complementary comes back empty. That\n       ordering means the rail improves by itself the moment the merchant\n       configures complementary products - no code change needed. */\n    function ask(intent) {\n      return fetch('/recommendations/products.json?product_id=' + productId + '&limit=3&intent=' + intent, {\n        headers: { 'Accept': 'application/json' }\n      })\n        .then(function (r) { return r.ok ? r.json() : null; })\n        .then(function (data) { return (data && data.products) || []; })\n        .catch(function () { return []; });\n    }\n\n    function paint(products) {\n      recsListEl.textContent = '';\n      products.forEach(function (p) {\n        if (!p.available) { return; }\n        /* a battery kit built from its parts is added from its own page, as its parts */\n        var tg = p.tags || [];\n        if (typeof tg === 'string') { tg = tg.split(/,\\s*/); }\n        if (tg.indexOf('kit-from-parts') > -1) { return; }\n        recsListEl.appendChild(recNode(p));\n      });\n      recsEl.hidden = recsListEl.children.length === 0;\n      /* suggestions arrive like any other list content */\n      if (!recsEl.hidden && isOpen() && window.TdhqMotion) { window.TdhqMotion.reveal(recsListEl.children); }\n    }\n\n    /* An empty complementary answer is remembered for the session: the next\n       time this product is the newest line, related is asked straight away. */\n    var none = false;\n    try { none = !!window.sessionStorage.getItem('tdhq:comp0:' + productId); } catch (e) { none = false; }\n    if (none) { ask('related').then(paint); return; }\n    ask('complementary').then(function (products) {\n      if (products.length) { paint(products); return; }\n      try { window.sessionStorage.setItem('tdhq:comp0:' + productId, '1'); } catch (e) { /* private mode */ }\n      ask('related').then(paint);\n    });\n  }\n\n  function recNode(p) {\n    var li = document.createElement('li');\n    li.className = 'tdhq-cd__rec';\n\n    var imgWrap = document.createElement('div');\n    imgWrap.className = 'tdhq-cd__recimg';\n    if (p.featured_image) {\n      var im = document.createElement('img');\n      /* 52px tile, sized for the screen's density. The recommendations\n         endpoint returns the 2000px original, which cost ~40 KB a tile. */\n      im.sizes = '52px';\n      im.srcset = sizedImage(p.featured_image, 54) + ' 54w, ' + sizedImage(p.featured_image, 108) + ' 108w, ' + sizedImage(p.featured_image, 162) + ' 162w';\n      im.src = sizedImage(p.featured_image, 162);\n      im.width = 162; im.height = 162;\n      im.alt = '';\n      im.loading = 'lazy';\n      im.setAttribute('data-tdhq-fit', 'thumb');\n      imgWrap.appendChild(im);\n    }\n    li.appendChild(imgWrap);\n\n    var mid = document.createElement('div');\n    var a = document.createElement('a');\n    a.className = 'tdhq-cd__recname';\n    a.href = p.url;\n    a.textContent = cleanTitle(decodeEntities(p.title));\n    mid.appendChild(a);\n    /* first available variant: these cards have no variant picker, and adding an\n       unavailable variant would fail at the API for no visible reason */\n    var variant = null;\n    for (var i = 0; i < (p.variants || []).length; i++) {\n      if (p.variants[i].available) { variant = p.variants[i]; break; }\n    }\n    var variantId = variant ? variant.id : null;\n\n    var pr = document.createElement('span');\n    pr.className = 'tdhq-cd__recprice';\n    /* `p.price` is the PRODUCT minimum across all variants, but the button adds\n       the first AVAILABLE variant - which is often not the cheapest one, because\n       the cheapest is frequently the one that sold out. So the card advertised\n       one price and the basket jumped by another. Price the card from the\n       variant it is actually going to add. */\n    pr.textContent = money(variant ? variant.price : p.price);\n    mid.appendChild(pr);\n\n    /* Say WHICH variant, when there is more than one to choose between. */\n    if (variant && (p.variants || []).length > 1 && variant.title && variant.title !== 'Default Title') {\n      var vt = document.createElement('span');\n      vt.className = 'tdhq-cd__recvariant';\n      var recPairs = (p.options || []).map(function (o, i) {\n        return { name: typeof o === 'string' ? o : (o && o.name), value: (variant.options || [])[i] };\n      });\n      vt.textContent = decodeEntities(optLine(recPairs) || variant.title);\n      mid.appendChild(vt);\n    }\n    li.appendChild(mid);\n\n    var add = document.createElement('button');\n    add.type = 'button';\n    add.className = 'tdhq-cd__recadd';\n    add.textContent = 'Add';\n    if (!variantId) { add.disabled = true; }\n    add.addEventListener('click', function () {\n      if (!variantId || add.disabled) { return; }\n      add.disabled = true;\n      fetch('/cart/add.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },\n        body: JSON.stringify({ id: variantId, quantity: 1 })\n      })\n        .then(function (r) {\n          /* Shopify explains its own refusals - \"All 3 \u2026 are in your cart\" -\n             and that sentence is the only thing that tells the shopper why\n             the button did nothing. Throwing the body away left the button\n             silently re-enabled, which reads as broken. */\n          if (!r.ok) {\n            return r.json()\n              .catch(function () { throw new Error('Could not add this item. Please try again.'); })\n              .then(function (e) { throw new Error(e.description || e.message || 'Could not add this item.'); });\n          }\n          return r.json();\n        })\n        .then(function (added) { recsLoadedFor = null; return showAdded(added); })\n        .catch(function (err) {\n          add.disabled = false;\n          announce((err && err.message) || 'Could not add this item.');\n        });\n    });\n    li.appendChild(add);\n    return li;\n  }\n\n  /* ---------------------------------------------------------------\n     Mutations\n     --------------------------------------------------------------- */\n  function refresh() {\n    /* the site's one basket read (TdhqCart, layout head): no HTTP cache, retried on a refusal */\n    return window.TdhqCart.get()\n      .then(function (cart) { render(cart); return cart; })\n      .catch(function () { return null; });\n  }\n\n  /* The basket as the add itself answered it: the line(s) Shopify returned from /cart/add.js, merged into the last\n     basket drawn. Used only when the basket cannot be read after an add, so the drawer and the header count never\n     stay one add behind (owner 21 Oct). */\n  function fromAdd(added, base) {\n    base = base || lastCart;\n    if (!base || !added) { return null; }\n    var lines = added.items || [added];\n    if (!lines.length || !lines[0].key) { return null; }\n    var cart = JSON.parse(JSON.stringify(base));\n    lines.forEach(function (line) {\n      var at = -1;\n      cart.items.forEach(function (it, i) { if (it.key === line.key) { at = i; } });\n      if (at > -1) { cart.items[at] = line; } else { cart.items.unshift(line); }\n    });\n    var sum = function (f) { return cart.items.reduce(function (a, it) { return a + (it[f] || 0); }, 0); };\n    cart.item_count = sum('quantity');\n    cart.items_subtotal_price = sum('final_line_price');\n    cart.total_price = cart.items_subtotal_price;\n    cart.original_total_price = sum('original_line_price');\n    return cart;\n  }\n\n  /* Does this basket hold what /cart/add.js just answered? Every added line, at least at that quantity. */\n  function holds(cart, added) {\n    if (!cart || !added) { return !!cart; }\n    var lines = added.items || [added];\n    return lines.every(function (line) {\n      return !line.key || cart.items.some(function (it) { return it.key === line.key && it.quantity >= (line.quantity || 1); });\n    });\n  }\n\n  /* AFTER AN ADD (21 Oct): draw the basket only once it is known to hold the add. A read that does not hold it is\n     drawn with the add merged in straight away, then read again after 0.3 / 0.8 / 1.6 s until the real basket\n     holds it; a read that fails entirely leaves the merged basket and reads once more after 5 s. */\n  function showAdded(added) {\n    var waits = [300, 800, 1600];\n    function attempt(n) {\n      return window.TdhqCart.get().then(function (cart) {\n        if (holds(cart, added)) { render(cart); publishCartChange(cart); return cart; }\n        var merged = fromAdd(added, cart);\n        if (merged) { render(merged); }\n        if (n >= waits.length) { if (merged) { publishCartChange(merged); } return merged || cart; }\n        return new Promise(function (ok) { window.setTimeout(ok, waits[n]); }).then(function () { return attempt(n + 1); });\n      }, function () {\n        var merged = fromAdd(added);\n        if (merged) { render(merged); publishCartChange(merged); }\n        window.setTimeout(function () { refresh().then(function (c) { if (c) { publishCartChange(c); } }); }, 5000);\n        return merged;\n      });\n    }\n    return attempt(0);\n  }\n\n  /* A message beside the control the shopper just used, the same shape the\n     basket page uses. Shopify answers an over-quantity request with 422 and a\n     plain-English description (\"You can only add 3 of this item to your cart\"),\n     which is exactly what the shopper needs to see. */\n  /* One place selectors escape a cart line key, which contains a colon. */\n  function esc(key) { return (window.CSS && CSS.escape) ? CSS.escape(key) : key; }\n\n  /* THE BASKET PAGE IS ALSO A BASKET. On /cart the header link opens this\n     drawer instead of navigating, and the page underneath keeps its rendered\n     quantities in `updates[]` - so its Checkout re-posted them and undid\n     whatever was done in here. Saying what happened lets that page re-render\n     itself; everywhere else nothing is listening and this costs one event. */\n  /* Everything Liquid rendered into this drawer, handed to the shared store\n     so the \"+\" can be judged after the drawer has redrawn itself from\n     /cart.js - which carries no stock. Runs again after each server render. */\n  function seedCeilings(scope) {\n    if (!window.TdhqQty) { return; }\n    var lines = (scope || document).querySelectorAll('[data-cd-item][data-cd-max]');\n    for (var i = 0; i < lines.length; i++) {\n      var k = lines[i].getAttribute('data-key') || '';\n      if (k) { window.TdhqQty.remember(k.split(':')[0], lines[i].getAttribute('data-cd-max')); }\n    }\n  }\n\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', function () { seedCeilings(root); });\n  } else { seedCeilings(root); }\n  seedWas(root);\n\n  function publishCartChange(cart) {\n    document.dispatchEvent(new CustomEvent('tdhq:cart:changed', { detail: { cart: cart || null } }));\n  }\n\n  function showLineError(lineEl, msg) {\n    if (!lineEl || !msg) { return; }\n    var box = lineEl.querySelector('.tdhq-cd__lineerr');\n    if (!box) {\n      box = document.createElement('p');\n      box.className = 'tdhq-cd__lineerr';\n      box.setAttribute('role', 'alert');\n      lineEl.appendChild(box);\n    }\n    box.textContent = msg;\n    if (window.TdhqMotion) { window.TdhqMotion.show(box); }\n  }\n\n  /* Say what just happened. Blanking first and setting on the next frame is\n     what makes a REPEATED string fire: pressing \"+\" three times writes the same\n     shape of sentence each time, and a live region whose text is assigned the\n     identical value announces nothing. Same trick as tdhq-quickadd.js. */\n  function announce(message) {\n    var live = root.querySelector('[data-cd-live]');\n    if (!live || !message) { return; }\n    live.textContent = '';\n    /* A TIMER, not requestAnimationFrame. rAF is paused while the tab is in the\n       background, so an announcement scheduled that way can simply never\n       arrive. A timer is throttled there, not cancelled. */\n    window.setTimeout(function () { live.textContent = message; }, 30);\n  }\n\n  /* ONE REQUEST IN FLIGHT, EVERY TAP REMEMBERED.\n\n     The cart API is not transactional, so two concurrent /cart/change.js posts\n     can race and lose an update - but a tap must never be dropped either. Each\n     line keeps the quantity it was last asked for; taps update that target (and\n     the digit) immediately, and when the in-flight request settles the newest\n     target goes if it still differs from what was sent. Same shape as the\n     basket page. */\n  var cdTargets = {};\n  var cdBusy = false;\n\n  /* The \"+\" goes dead at the stock ceiling, the way every other stepper on\n     the site does. Called wherever a line's digit is written. */\n  function paintLineCap(lineEl) {\n    if (!lineEl || !window.TdhqQty) { return; }\n    var key = lineEl.getAttribute('data-key') || '';\n    var cap = window.TdhqQty.stock(key.split(':')[0]);\n    var plus = null;\n    var btns = lineEl.querySelectorAll('[data-cd-step]');\n    for (var i = 0; i < btns.length; i++) {\n      if (btns[i].getAttribute('data-cd-step') === '1') { plus = btns[i]; break; }\n    }\n    if (!plus) { return; }\n    var valEl = lineEl.querySelector('[data-cd-qtyval]');\n    var now = parseInt(valEl && valEl.textContent, 10) || 0;\n    var atCap = cap !== null && now >= cap;\n    plus.disabled = atCap;\n\n    /* Say why, in the same words and the same quiet style the product page\n       uses. Not the line-error box: nothing has gone wrong, there is simply\n       no more stock. */\n    var note = lineEl.querySelector('[data-qty-note]');\n    if (!atCap) {\n      if (note) { note.textContent = ''; note.hidden = true; }\n      return;\n    }\n    if (!note) {\n      note = document.createElement('p');\n      note.className = 'tdhq-qtynote';\n      note.setAttribute('data-qty-note', '');\n      note.setAttribute('role', 'status');\n      /* beside Remove, on its row (client: \"close to remove button to save space\") */\n      var rmBtn = lineEl.querySelector('.tdhq-cd__remove');\n      if (rmBtn && rmBtn.parentNode) { rmBtn.parentNode.insertBefore(note, rmBtn.nextSibling); }\n      else { lineEl.appendChild(note); }\n    }\n    note.hidden = false;\n    var msg = window.TdhqQty.reason(key.split(':')[0], 'line');\n    if (note.textContent !== msg) { note.textContent = msg; }\n  }\n\n  function queueLine(key, quantity, lineEl) {\n    cdTargets[key] = quantity;\n    /* Optimistic: the number the shopper asked for appears in the same frame.\n       Waiting for the round trip before moving the digit is what reads as a\n       dead control.\n\n       EXCEPT A REMOVAL. Writing 0 took the line off its stock ceiling, so\n       paintLineCap hid the \"Only 1 in stock.\" note at once: the list dropped\n       32px in the first frame after the tap, 3ms in, and only then did the\n       line start to close (measured at 390 and 1440). The stepper also read\n       0 for the whole close, which the basket page never shows. A line on\n       its way out keeps its digit and its note, dims like any busy line, and\n       closes as one piece. */\n    if (quantity > 0) {\n      var valEl = lineEl && lineEl.querySelector('[data-cd-qtyval]');\n      if (valEl) { valEl.textContent = quantity; }\n      paintLineCap(lineEl);\n    } else if (lineEl) {\n      lineEl.classList.add('is-busy');\n      lineEl.setAttribute('aria-busy', 'true');\n    }\n    if (cdBusy) { return; }\n    drainLine();\n  }\n\n  function drainLine() {\n    for (var k in cdTargets) {\n      if (!Object.prototype.hasOwnProperty.call(cdTargets, k)) { continue; }\n      var q = cdTargets[k];\n      var el = root.querySelector('[data-cd-item][data-key=\"' + esc(k) + '\"]');\n      cdBusy = true;\n      changeLine(k, q, el);\n      return true;\n    }\n    cdBusy = false;\n    return false;\n  }\n\n  function settleLine(key, sent) {\n    /* Only clear the target this request actually satisfied: a newer tap that\n       arrived mid-flight has to survive and be sent. */\n    if (cdTargets[key] === sent) { delete cdTargets[key]; }\n    cdBusy = false;\n    window.setTimeout(drainLine, 0);\n  }\n\n  function changeLine(key, quantity, lineEl) {\n    if (lineEl) { lineEl.classList.add('is-busy'); lineEl.setAttribute('aria-busy', 'true'); }\n    /* Read the title BEFORE the request: render() destroys the line node, and\n       a removal has no line left to name afterwards. */\n    var titleEl = lineEl && lineEl.querySelector('.tdhq-cd__name');\n    var title = (titleEl && titleEl.textContent.trim()) || 'Item';\n    return fetch('/cart/change.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },\n      body: JSON.stringify({ id: key, quantity: quantity })\n    })\n      .then(function (r) {\n        /* `r.ok ? r.json() : null` swallowed every failure: the line kept its\n           busy dim for ever, no message appeared, and the basket had already\n           changed underneath. A rejected request now says why. */\n        if (!r.ok) {\n          return r.json()\n            .catch(function () { throw new Error('Could not update your basket. Please try again.'); })\n            .then(function (e) {\n              var err = new Error(e.description || e.message || 'Could not update your basket.');\n              /* 400 \"no valid id or line parameter\": this line is no longer in the basket (changed in another tab or\n                 on another device). Not the shopper's error to read - the basket is simply redrawn as it is. */\n              err.stale = r.status === 400 && /no valid id|line parameter/i.test(err.message);\n              throw err;\n            });\n        }\n        return r.json();\n      })\n      .then(function (cart) {\n        /* the removed line's product may have been the recommendation seed;\n           a quantity change leaves the seed, and the rail, as they are */\n        if (quantity === 0) { recsLoadedFor = null; }\n        function finish() {\n          settleLine(key, quantity);\n          render(cart);\n          publishCartChange(cart);\n          announce(\n            (quantity === 0\n              ? title + ' removed from your basket. '\n              : title + ', quantity ' + quantity + '. ') +\n            (cart.item_count === 0\n              ? 'Your basket is now empty.'\n              : cart.item_count + (cart.item_count === 1 ? ' item' : ' items') +\n                ' in your basket, total ' + money(payable(cart)) + '.')\n          );\n        }\n        /* A REMOVED LINE CLOSES (audit cart-10), the way it does on the basket\n           page, instead of vanishing and snapping the list up. Its measured\n           height is the starting point and 0px the end. The queue is settled\n           and the new basket drawn together, when the line has gone, so a tap\n           queued meanwhile can never be answered by an older basket. */\n        var line = lineEl && lineEl.isConnected ? lineEl : null;\n        if (quantity === 0 && line && window.TdhqMotion) {\n          window.TdhqMotion.exit(line, finish);\n        } else {\n          finish();\n        }\n      })\n      .catch(function (err) {\n        if (lineEl) { lineEl.classList.remove('is-busy'); lineEl.removeAttribute('aria-busy'); }\n        /* RE-SYNC FIRST, THEN SPEAK. render() empties the list and rebuilds\n           every line, so a message written before this ran was destroyed a\n           frame later - the shopper saw the digit twitch back with no\n           explanation at all. The line that comes back is a different element,\n           so it is found again by key. */\n        var msg = err && !err.stale ? err.message : null;\n        /* A refused line clears its own target - the server has told us what it\n           will accept - but the other lines the shopper touched are not this\n           line's fault and still go. */\n        delete cdTargets[key];\n        cdBusy = false;\n        window.setTimeout(drainLine, 0);\n        return refresh().then(function (cart) {\n          publishCartChange(cart);\n          var fresh = root.querySelector('[data-cd-item][data-key=\"' + esc(key) + '\"]');\n          showLineError(fresh, msg);\n          if (msg) { announce(msg); }\n        });\n      });\n  }\n\n  /* ---------------------------------------------------------------\n     Events\n     --------------------------------------------------------------- */\n  root.addEventListener('click', function (e) {\n    var closer = e.target.closest('[data-cd-close]');\n    if (closer) { e.preventDefault(); close(); return; }\n\n    var line = e.target.closest('[data-cd-item]');\n    if (!line) { return; }\n    var key = line.getAttribute('data-key');\n\n    var step = e.target.closest('[data-cd-step]');\n    if (step) {\n      /* Read the TARGET, not the DOM. The digit is now moved optimistically, so\n         the DOM is already the right base - but a pending target is righter\n         still when a burst of taps is in progress. */\n      var valEl = line.querySelector('[data-cd-qtyval]');\n      var current = (cdTargets[key] !== undefined)\n        ? cdTargets[key]\n        : (parseInt(valEl && valEl.textContent, 10) || 0);\n      var next = current + parseInt(step.getAttribute('data-cd-step'), 10);\n      if (next < 0) { next = 0; }\n      /* THE STOCK CEILING. The line key's first segment is the variant id, and\n         the shared store holds what Liquid rendered for it. Refusing here is\n         what the client asked for: the shopper is told at the control, not at\n         the checkout.\n\n         AND THERE IS NOTHING BEHIND THIS. Measured 2026-09-23 on five\n         products: /cart/add.js accepted 21 units of a variant with 1 in\n         stock, and every other oversell tried, all HTTP 200. Shopify is not\n         refusing anything on this shop, so this clamp is the only guard,\n         not a nicety in front of a server-side one. */\n      if (window.TdhqQty && next > current) {\n        var cap = window.TdhqQty.stock(key.split(':')[0]);\n        if (cap !== null && next > cap) {\n          showLineError(line, window.TdhqQty.reason(key.split(':')[0], 'line'));\n          return;\n        }\n      }\n      showLineError(line, '');\n      queueLine(key, next, line);\n      return;\n    }\n\n    if (e.target.closest('[data-cd-remove]')) {\n      queueLine(key, 0, line);\n    }\n  });\n\n  document.addEventListener('keydown', function (e) {\n    if (!isOpen()) { return; }\n    if (e.key === 'Escape') { e.preventDefault(); close(); return; }\n    if (e.key !== 'Tab' || !panel) { return; }\n\n    /* Focus trap. A modal that lets Tab wander onto the page behind it is a\n       keyboard dead end: the shopper cannot see where focus went. */\n    var focusables = panel.querySelectorAll(\n      'a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n    );\n    /* The empty-state block and the footer are hidden with `hidden` when the\n       basket has items (and the reverse when it does not), but their buttons\n       still match the focusable selector - so `first` or `last` could be an\n       element nobody can see, and Tab escaped the drawer. Only visible controls\n       count. */\n    var visible = Array.prototype.filter.call(focusables, function (el) {\n      return el.offsetParent !== null || el === document.activeElement;\n    });\n    if (!visible.length) { return; }\n    var first = visible[0];\n    var last = visible[visible.length - 1];\n    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n  });\n\n  /* The header basket link becomes the drawer trigger, but stays a real <a> to\n     /cart so it still works with JS off, opens in a new tab on middle-click, and\n     is announced as a link to the basket. */\n  document.addEventListener('click', function (e) {\n    var link = e.target.closest('[data-tdhq-cart-link]');\n    if (!link) { return; }\n    if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) { return; }\n    e.preventDefault();\n    open();\n    refresh();\n  });\n\n  /* Fired by tdhq-quickadd.js and by the PDP buy form once an add is confirmed. */\n  document.addEventListener('tdhq:cart:added', function (e) {\n    recsLoadedFor = null;\n    lastAddedProductId = (e && e.detail && e.detail.productId) || null;\n    /* The drawer opens on whatever it last rendered, and the refresh lands a\n       moment later - so the FIRST add on an empty basket flashed \"Your basket is\n       empty\" as its confirmation. Suppress the empty state for the length of the\n       in-flight refresh: something has just been added, so empty is known to be\n       wrong even before the new cart arrives. */\n    if (emptyEl) { emptyEl.hidden = true; }\n    if (itemsEl) { itemsEl.hidden = false; }\n    root.classList.add('is-loading');\n    /* On the basket page the basket is already on screen (owner 21 Oct): the drawer stays shut and the page itself\n       takes the new line (sections/dtc-cart redraws on tdhq:cart:changed, which showAdded publishes). */\n    if (!document.querySelector('[data-dtc-cart]')) { open(); }\n    var added = e && e.detail && e.detail.item;\n    showAdded(added).then(function () { root.classList.remove('is-loading'); }, function () { root.classList.remove('is-loading'); });\n  });\n\n  /* Nothing is asked for until the basket is wanted (audit cart-16). The\n     lines are drawn by the server with the page; the drawer refreshes - its\n     recommendations, and any change made in another tab - as the shopper\n     reaches for the basket link, so it is ready when it opens, and again on\n     open. The delivery meter is the one part the server leaves empty, so a\n     basket with the meter switched on is still filled in at once. */\n  var warmed = false;\n  function warm(e) {\n    if (warmed || !e.target || !e.target.closest || !e.target.closest('[data-tdhq-cart-link]')) { return; }\n    warmed = true;\n    if (root.querySelector('[data-cd-item]')) { refresh(); }\n  }\n  document.addEventListener('pointerover', warm, { passive: true });\n  document.addEventListener('focusin', warm);\n  if (shipEl && root.querySelector('[data-cd-item]')) { refresh(); }\n\n  window.tdhqCartDrawer = { open: open, close: close, refresh: refresh };\n})();\n"],
  "mappings": "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",
  "names": ["val", "i"]
}
