{
  "version": 3,
  "sources": ["/cdn/shop/t/175/assets/mini-cart-drawer.js?caf_v=20261009-review-1"],
  "sourcesContent": ["/*\n * CAF mini-cart drawer runtime (desktop \u2265799px; phones go to /cart). Owner: cart pass.\n *\n * Markup: snippets/cart-drawer.liquid (first paint, rendered from sections/header.liquid). This file\n * re-renders lines / perks / rows / codes on every refresh, so BOTH paths must emit the same DOM\n * (pages/cart.md \"Render paths\"). The header can hold up to 3 copies of the drawer (desktop header,\n * Headhesive sticky clone, sections.js clone into #header) \u2014 every update targets all of them.\n *\n * Public API (window.CAFMiniCartDrawer):\n *   canOpen()                     desktop drawer available?\n *   open() / close()\n *   showAdding()                  open immediately in the \"Adding\u2026\" skeleton (no-op \u2192 false when !canOpen()).\n *                                 Call right when Add to cart starts; fetchRefreshAndOpen() replaces it.\n *   fetchRefreshAndOpen(opts)     fetch /cart.js, render, open. opts.reason: 'added' (default \u2014 both ATC\n *                                 callers; shows the skeleton while fetching + \"\u2713 Added\"), 'updated'\n *                                 (after the TeeInBlue editor saved), 'edit' / 'refresh' (plain reopen).\n *                                 Resolves true when the drawer is open, false on failure (callers fall\n *                                 back to /cart).\n *   refresh(cart)                 render a cart.js payload.\n *\n * Owner decisions honoured here (2026-10-04): gift cards never count toward free shipping; typed-text\n * line \"Text: \u2026\" (settings.cart_show_personalization_details \u2192 form[data-show-details], 2026-10-09); reservation timer\n * kept (one calm sentence + expired state); no express checkout / no \"Make it a set\".\n * Owner 2026-10-12: one perk row for Buy 3 + free shipping (getComboState); split test \"ship\" arm b = shipping\n * estimate + \"Estimated total\" in the footer (getShipEstimate \u2014 both versions are rendered, caf-rd-cart.css shows\n * one from html.caf-exp-ship-b + form[data-ship-estimate]). The estimate is only for a cart whose shippable lines\n * are all in ONE shipping profile (getShipZone; zone tags from form[data-ship-zones]) \u2014 any other cart keeps\n * today's footer.\n */\n(() => {\n  const selectors = {\n    drawer: '.cart_content',\n    cartForm: '[data-cart-form]',\n    miniCartForm: '[data-cart-form=\"mini-cart\"]',\n    items: '.js-cart_items',\n    perks: '[data-mini-cart-perks]',\n    freeShipping: '[data-mini-cart-free-shipping]',\n    bundle: '[data-mini-cart-bundle]',\n    combo: '[data-mini-cart-combo]',\n    ship: '[data-mini-cart-ship]',\n    rows: '[data-mini-cart-rows]',\n    codes: '[data-mini-cart-codes]',\n    count: '[data-mini-cart-count]',\n    status: '[data-mini-cart-status]',\n    removed: '[data-mini-cart-removed]',\n    urgency: '[data-mini-cart-urgency]',\n    total: '.js-cart_subtotal',\n    checkout: '[data-minicart-checkout-button]',\n    discount: '[data-caf-mini-cart-discount]',\n    discountInput: '[data-caf-mini-cart-discount-input]',\n    discountApply: '[data-caf-mini-cart-discount-apply]',\n    discountError: '[data-caf-mini-cart-discount-error]',\n    codeRemove: '[data-mini-cart-code-remove]',\n    quantityInput: '[data-cart-quantity-input=\"mini-cart\"]',\n    quantityButton: '.js-change-quantity',\n    previewTrigger: '[data-mini-cart-preview]',\n    previewModal: '[data-mini-cart-preview-modal]',\n    previewClose: '[data-mini-cart-preview-close]',\n    previewEdit: '[data-mini-cart-preview-edit]',\n    removeTrigger: '[data-remove-item=\"mini-cart\"]',\n    removeConfirm: '[data-mini-cart-remove-confirm]',\n    removeConfirmClose: '[data-mini-cart-remove-confirm-close]',\n    removeConfirmRemove: '[data-mini-cart-remove-confirm-remove]',\n    removeConfirmImage: '[data-mini-cart-remove-confirm-image]',\n  };\n\n  // Icons share stroke=\"currentColor\" so CSS colours them (the Liquid copies come from snippets/svg-icons\n  // and are recoloured to currentColor in caf-rd-cart.css \u00A77).\n  const svg = (name, paths) =>\n    `<svg class=\"caf-icon caf-icon--${name}\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n  const icons = {\n    minus: svg('minus', '<path d=\"M5 12h14\"></path>'),\n    plus: svg('plus', '<path d=\"M12 5v14M5 12h14\"></path>'),\n    trash: svg('trash', '<path d=\"M4 7h16M9 7V5h6v2M7 7l1 14h8l1-14\"></path><path d=\"M10 11v6M14 11v6\"></path>'),\n    eye: svg('eye', '<path d=\"M3 12s3.3-6 9-6 9 6 9 6-3.3 6-9 6-9-6-9-6z\"></path><circle cx=\"12\" cy=\"12\" r=\"2.5\"></circle>'),\n    edit: svg('edit', '<path d=\"M4 20h4l11-11a2.1 2.1 0 0 0-3-3L5 17l-1 3z\"></path><path d=\"M14 8l2 2\"></path>'),\n    close: svg('close', '<path d=\"M6 6l12 12M18 6L6 18\"></path>'),\n    check: svg('check', '<path d=\"M4 12.5l5 5L20 6.5\"></path>'),\n    tag: svg('tag', '<path d=\"M4 12V5h7l9 9-7 7-9-9z\"></path><circle cx=\"8\" cy=\"8\" r=\"1.4\"></circle>'),\n    alert: svg('alert', '<circle cx=\"12\" cy=\"12\" r=\"8.5\"></circle><path d=\"M12 7.5v5.5M12 16.2h.01\"></path>'),\n  };\n  const spinner = '<span class=\"caf-spin\" aria-hidden=\"true\"></span>';\n\n  const escapeHtml = (value) =>\n    String(value ?? '')\n      .replace(/&/g, '&amp;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&#39;');\n\n  // Guarded DOM writes (THEME-PERFORMANCE-GUIDE \u00A711): the same value is never written again, so a refresh that\n  // changes nothing leaves no mutation records. Compared against the live node (app.js may have rewritten it).\n  const setHtml = (node, html) => {\n    if (node && node.innerHTML !== html) node.innerHTML = html;\n  };\n  const setHidden = (node, hidden) => {\n    if (node && node.hidden !== hidden) node.hidden = hidden;\n  };\n  const setClass = (node, name, on) => {\n    if (node && node.classList.contains(name) !== on) node.classList.toggle(name, on);\n  };\n\n  const closestElement = (target, selector) => {\n    const element = target instanceof Element ? target : target?.parentElement;\n    return element?.closest(selector) || null;\n  };\n\n  const closestFromEvent = (event, selector) =>\n    event\n      .composedPath?.()\n      .find((node) => node instanceof Element && node.matches(selector)) || closestElement(event.target, selector);\n\n  const suppressMiniCartOutsideClose = (duration = 900) => {\n    window.CAFSuppressMiniCartOutsideCloseUntil = Date.now() + duration;\n  };\n\n  const getRoot = () => {\n    const root = window.Shopify?.routes?.root || '/';\n    return root.endsWith('/') ? root : `${root}/`;\n  };\n\n  const getForms = () => Array.from(document.querySelectorAll(selectors.miniCartForm));\n\n  // form[data-ship-tiers] = snippets/caf-ship-estimate.liquid output: \"20000:698,40000:898,\u2026,*:1698\"\n  // (bound in 1/10,000 lb : cents; \"*\" = anything heavier). Empty = no estimate (setting empty / mistyped,\n  // non-U.S. storefront) \u2192 the footer stays as it is today in both arms.\n  const parseShipTiers = (value) =>\n    String(value || '')\n      .split(',')\n      .map((part) => part.split(':'))\n      .filter((pair) => pair.length === 2)\n      .map(([bound, cents]) => [bound === '*' ? Infinity : Number(bound), Number(cents)])\n      .filter(([bound, cents]) => bound > 0 && cents > 0);\n\n  const getConfig = () => {\n    const data = getForms()[0]?.dataset || {};\n    return {\n      showDetails: data.showDetails !== 'false',\n      freeMin: Number(data.freeShippingMinimum || 0),\n      bundleEnabled: data.bundleEnabled === 'true',\n      bundleTag: String(data.bundleTag || '').trim().toLowerCase(),\n      bundleMin: Number(data.bundleMin || 3),\n      bundleTitle: data.bundleTitle || 'Buy 3 ornaments, get 15% off',\n      bundleTitleApplied: data.bundleTitleApplied || 'Buy 3 ornaments, 15% off',\n      bundleNoun: data.bundleNoun || 'ornament',\n      bundleNouns: data.bundleNouns || 'ornaments',\n      bundlePercent: Number(data.bundlePercent || 0),\n      shopCurrency: String(data.shopCurrency || ''),\n      shipTiers: parseShipTiers(data.shipTiers),\n      // snippets/caf-ship-zone.liquid: the product tags that name a shipping profile (\"zone01,zone02,zone03\")\n      shipZones: String(data.shipZones || '')\n        .split(',')\n        .map((tag) => tag.trim().toLowerCase())\n        .filter(Boolean),\n    };\n  };\n\n  const formatMoney = (cents) => {\n    const moneyFormat = document.body?.dataset?.moneyFormat || getForms()[0]?.dataset.moneyFormat || '${{amount}}';\n\n    if (window.Shopify && typeof window.Shopify.formatMoney === 'function') {\n      return window.Shopify.formatMoney(cents, moneyFormat);\n    }\n\n    return `$${(Number(cents || 0) / 100).toFixed(2)}`;\n  };\n\n  const itemsLabel = (count) => `${count} ${count === 1 ? 'item' : 'items'}`;\n\n  const getMiniCartTotalLabel = () => window.PXUTheme?.translation?.cart_total_text || 'Total';\n\n  /* ------------------------------------------------------------------ line data */\n\n  const getLinePriceState = (item) => {\n    const current = Number(item?.final_line_price);\n    const original = Number(item?.original_line_price);\n    const fallbackCurrent = Number(item?.final_price);\n    const fallbackOriginal = Number(item?.original_price);\n\n    return {\n      current: Number.isFinite(current) ? current : Number.isFinite(fallbackCurrent) ? fallbackCurrent : 0,\n      original:\n        Number.isFinite(original) && original > 0\n          ? original\n          : Number.isFinite(fallbackOriginal) && fallbackOriginal > 0\n            ? fallbackOriginal\n            : 0,\n    };\n  };\n\n  const getCustomizationId = (item) => {\n    const properties = item?.properties || {};\n\n    if (properties._customization_id) return properties._customization_id;\n\n    return (\n      Object.entries(properties).find(([key, value]) => {\n        const normalizedKey = String(key || '').toLowerCase();\n        return value && normalizedKey.includes('customization') && normalizedKey.includes('id');\n      })?.[1] || ''\n    );\n  };\n\n  const isGiftCardLine = (item) => Boolean(item?.gift_card);\n\n  /*\n   * Typed-text line \"Text: Jason \u00B7 Lily\" \u2014 SAME rules as snippets/cart-line-details.liquid (keep in sync):\n   * skip blank / \"_\" keys / keys with \"customization\" or \"preview\" / \"on\" / URL + image values;\n   * \"Enter \u2026\" keys are shown, \"Choose \u2026\" keys hidden; other keys only when they contain a text word and no\n   * choice word (TeeInBlue choice names like \"1\" / \"skin baby\" stay out). `forName` = first two shown values\n   * whose key contains \"name\".\n   */\n  const TEXT_WORDS = ['name', 'date', 'year', 'message', 'text', 'quote', 'initial', 'wording', 'title', 'birthday'];\n  const CHOICE_WORDS = ['color', 'colour', 'font', 'tone', 'style', 'skin', 'hair'];\n\n  const getLineText = (item) => {\n    const values = [];\n    const names = [];\n\n    Object.entries(item?.properties || {}).forEach(([rawKey, rawValue]) => {\n      const key = String(rawKey ?? '').trim();\n      const value = String(rawValue ?? '').trim();\n      if (!key || !value || key.startsWith('_')) return;\n\n      const keyLower = key.toLowerCase();\n      if (keyLower.includes('customization') || keyLower.includes('preview')) return;\n\n      const valueLower = value.toLowerCase();\n      if (\n        valueLower === 'on' ||\n        valueLower.startsWith('//') ||\n        valueLower.includes('://') ||\n        valueLower.includes('data:image') ||\n        valueLower.includes('/uploads/')\n      ) {\n        return;\n      }\n\n      const isText = keyLower.startsWith('enter ')\n        ? true\n        : !keyLower.startsWith('choose ') &&\n          TEXT_WORDS.some((word) => keyLower.includes(word)) &&\n          !CHOICE_WORDS.some((word) => keyLower.includes(word));\n      if (!isText) return;\n\n      values.push(value);\n      if (keyLower.includes('name') && names.length < 2) names.push(value);\n    });\n\n    return { values, forName: names.join(' ') };\n  };\n\n  const renderLineText = (text, context = 'drawer') => {\n    if (!text || !text.values.length) return '';\n\n    const values = text.values\n      .map((value) => `<span class=\"caf-text-line__value\">${escapeHtml(value)}</span>`)\n      .join('<span class=\"caf-text-line__sep\" aria-hidden=\"true\">&nbsp;\u00B7</span> '); // \"\u00B7\" stays with the value before it\n\n    return `<p class=\"caf-text-line caf-text-line--${context}\" data-caf-text-line${\n      text.forName ? ` data-caf-details-for=\"${escapeHtml(text.forName)}\"` : ''\n    }><span class=\"caf-text-line__label\">Text:</span> ${values}</p>`;\n  };\n\n  /* ------------------------------------------------------------------ images (TeeInBlue design preview) */\n\n  const normalizeCartImageUrl = (url) => {\n    if (!url) return '';\n    let value = String(url).trim();\n    if (!value) return '';\n\n    if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n      value = value.slice(1, -1);\n    }\n\n    value = value.replace(/\\\\\\//g, '/').replace(/^https:\\\\\\//i, 'https://').replace(/^http:\\\\\\//i, 'http://');\n    if (value.startsWith('\\\\/')) value = value.slice(1);\n\n    if (/%[0-9A-Fa-f]{2}/.test(value)) {\n      try {\n        value = decodeURIComponent(value);\n      } catch (error) {\n        // Keep the original cart payload value if it is not valid URI text.\n      }\n    }\n\n    if (value.startsWith('//')) return `${window.location.protocol}${value}`;\n    return value;\n  };\n\n  const isLikelyCartImageUrl = (value) => {\n    if (!value) return false;\n    const text = String(value).trim();\n    if (!text) return false;\n    if (/^data:image\\//i.test(text)) return true;\n    if (/^blob:/i.test(text)) return true;\n    if (!/^https?:|^\\/\\/|^\\//i.test(text)) return false;\n    if (/\\.(avif|gif|jpe?g|png|svg|webp)(\\?|$)/i.test(text)) return true;\n    return /(cdn|cloudfront|shopify|teeinblue|image|preview|mockup|thumbnail|render)/i.test(text);\n  };\n\n  const extractCartImageFromString = (input, depth = 0) => {\n    if (!input || depth > 2) return '';\n\n    const text = String(input).trim();\n    if (!text) return '';\n\n    const normalized = normalizeCartImageUrl(text);\n    if (isLikelyCartImageUrl(normalized)) return normalized;\n\n    if ((text.startsWith('{') && text.endsWith('}')) || (text.startsWith('[') && text.endsWith(']'))) {\n      try {\n        const parsed = JSON.parse(text);\n        const parsedFound = findCartImageUrlInObject(parsed, 0);\n        if (parsedFound) return parsedFound;\n      } catch (error) {\n        // Not every TeeInBlue property is JSON.\n      }\n    }\n\n    if (/%[0-9A-Fa-f]{2}/.test(text)) {\n      try {\n        const decodedFound = extractCartImageFromString(decodeURIComponent(text), depth + 1);\n        if (decodedFound) return decodedFound;\n      } catch (error) {\n        // Keep scanning the raw text.\n      }\n    }\n\n    const dataImageMatch = text.match(/data:image\\/[a-zA-Z0-9+.-]+;base64,[a-zA-Z0-9+/=]+/);\n    if (dataImageMatch?.[0]) return dataImageMatch[0];\n\n    const urlMatch = text.match(/https?:\\/\\/[^\\s\"'<>]+/i);\n    if (urlMatch?.[0]) {\n      const url = normalizeCartImageUrl(urlMatch[0]);\n      if (isLikelyCartImageUrl(url)) return url;\n    }\n\n    return '';\n  };\n\n  function findCartImageUrlInObject(source, depth = 0) {\n    if (!source || depth > 4) return '';\n\n    if (typeof source === 'string') {\n      return extractCartImageFromString(source) || '';\n    }\n\n    if (Array.isArray(source)) {\n      for (const item of source) {\n        const found = findCartImageUrlInObject(item, depth + 1);\n        if (found) return found;\n      }\n      return '';\n    }\n\n    if (typeof source !== 'object') return '';\n\n    const prioritizedKeys = [\n      '_customization_image',\n      '_customization_preview',\n      '_customization',\n      '_preview',\n      '_preview_image',\n      '_preview_url',\n      '_tb_preview',\n      '_tb_image',\n      'customization_image',\n      'customizationImage',\n      'customizationPreview',\n      'customization_preview',\n      'preview',\n      'preview_image',\n      'previewImage',\n      'preview_url',\n      'previewUrl',\n      'mockup_image',\n      'mockupImage',\n      'thumbnail',\n      'image',\n      'src',\n      'url',\n    ];\n\n    for (const key of prioritizedKeys) {\n      if (!(key in source)) continue;\n      const found = findCartImageUrlInObject(source[key], depth + 1);\n      if (found) return found;\n    }\n\n    const entries = Object.entries(source);\n\n    for (const [key, value] of entries) {\n      if (!/(image|preview|thumbnail|mockup|render)/i.test(key)) continue;\n      const found = findCartImageUrlInObject(value, depth + 1);\n      if (found) return found;\n    }\n\n    for (const [, value] of entries) {\n      const found = findCartImageUrlInObject(value, depth + 1);\n      if (found) return found;\n    }\n\n    return '';\n  }\n\n  const uniqueCartImageUrls = (values) => {\n    const seen = new Set();\n    return values\n      .map((value) => normalizeCartImageUrl(value))\n      .filter((value) => {\n        if (!value || seen.has(value)) return false;\n        seen.add(value);\n        return true;\n      });\n  };\n\n  const getImageUrl = (item) => {\n    const propertyImage = findCartImageUrlInObject(item?.properties || {});\n    const featuredImage = normalizeCartImageUrl(item?.featured_image?.url || item?.featured_image?.src || '');\n    const lineImage = normalizeCartImageUrl(item?.image || item?.featured_image || '');\n    return uniqueCartImageUrls([propertyImage, featuredImage, lineImage]).find(isLikelyCartImageUrl) || '';\n  };\n\n  /* ------------------------------------------------------------------ product-tag cache (\"Buy 3\" + shipping zone) */\n\n  // cart.js has no product tags \u2192 seed from the Liquid first paint (data-bundle-match, data-ship-zone), then fetch\n  // /products/<handle>.js once per new product (cached for the page view).\n  const bundleTagCache = new Map();\n  const bundleTagRequests = new Map();\n  // product id \u2192 the ONE zone tag the product carries (\"zone02\"), or '' when it carries none or more than one\n  // (same verdict as snippets/caf-ship-zone.liquid). A product that is not in the map has not been looked up yet.\n  const shipZoneCache = new Map();\n\n  const getProductShipZone = (tags, zones) => {\n    const hits = zones.filter((zone) => tags.includes(zone));\n    return hits.length === 1 ? hits[0] : '';\n  };\n\n  const seedBundleTagCache = () => {\n    document.querySelectorAll(`${selectors.miniCartForm} [data-cart-item][data-product-id]`).forEach((node) => {\n      const { productId, bundleMatch, shipZone } = node.dataset;\n      if (productId && (bundleMatch === 'true' || bundleMatch === 'false')) {\n        bundleTagCache.set(String(productId), bundleMatch === 'true');\n      }\n      // Markup from before the zone rule has no data-ship-zone \u2192 not seeded, the product is looked up.\n      if (productId && typeof shipZone === 'string') {\n        shipZoneCache.set(String(productId), shipZone.trim().toLowerCase());\n      }\n    });\n\n    // Product page: Liquid already matched THIS product against the same tag for the \"Added to your cart\" sheet\n    // (snippets/tee-popup-confirm-add-to-cart.liquid). Without it the first refresh after an add showed the plain\n    // free-shipping perk and swapped to the Buy-3 row once /products/<handle>.js answered (2026-10-12).\n    const sheet = document.getElementById('caf-added-sheet');\n    const tag = String(getForms()[0]?.dataset.bundleTag || '').trim().toLowerCase();\n    if (sheet && tag && String(sheet.dataset.bundleTag || '').trim().toLowerCase() === tag) {\n      const { productId, bundleMatch } = sheet.dataset;\n      if (productId && !bundleTagCache.has(String(productId)) && (bundleMatch === 'true' || bundleMatch === 'false')) {\n        bundleTagCache.set(String(productId), bundleMatch === 'true');\n      }\n    }\n    // \u2026 and its shipping zone (same snippet, data-ship-zone), so the estimate is right on that first refresh too.\n    if (sheet && sheet.dataset.productId && typeof sheet.dataset.shipZone === 'string') {\n      const id = String(sheet.dataset.productId);\n      if (!shipZoneCache.has(id)) shipZoneCache.set(id, sheet.dataset.shipZone.trim().toLowerCase());\n    }\n  };\n\n  // One request answers both questions: is the product a Buy-3 item, and which shipping zone is it in.\n  const ensureBundleTags = (cart) => {\n    const config = getConfig();\n    const needBundle = Boolean(config.bundleEnabled && config.bundleTag);\n    const needZone = config.shipTiers.length > 0 && config.shipZones.length > 0;\n    if (!needBundle && !needZone) return Promise.resolve(false);\n\n    const pending = [];\n    (cart?.items || []).forEach((item) => {\n      const id = String(item.product_id || '');\n      if (!id || !item.handle) return;\n      if ((!needBundle || bundleTagCache.has(id)) && (!needZone || shipZoneCache.has(id))) return;\n      if (!bundleTagRequests.has(id)) {\n        bundleTagRequests.set(\n          id,\n          window\n            .fetch(`${getRoot()}products/${encodeURIComponent(item.handle)}.js`, { headers: { Accept: 'application/json' } })\n            .then((response) => (response.ok ? response.json() : null))\n            .then((product) => {\n              const list = Array.isArray(product?.tags) ? product.tags : String(product?.tags || '').split(',');\n              const tags = list.map((tag) => String(tag).trim().toLowerCase());\n              if (needBundle) bundleTagCache.set(id, tags.includes(config.bundleTag));\n              // No answer (product gone, request refused) \u2192 zone unknown \u2192 no estimate for a cart with this line.\n              shipZoneCache.set(id, product ? getProductShipZone(tags, config.shipZones) : '');\n            })\n            .catch(() => {\n              if (needBundle) bundleTagCache.set(id, false);\n              shipZoneCache.set(id, '');\n            }),\n        );\n      }\n      pending.push(bundleTagRequests.get(id));\n    });\n\n    return pending.length ? Promise.all(pending).then(() => true) : Promise.resolve(false);\n  };\n\n  /* ------------------------------------------------------------------ cart math */\n\n  // Line-level discounts only (the automatic Buy-3 rule, a code limited to some products) \u2014 what Liquid reads as\n  // item.line_level_discount_allocations. An EMPTY list is an answer: for a code on the whole cart cart.js repeats\n  // the line's share in the legacy `item.discounts`, and falling back to it listed that code twice in the summary\n  // (\"CAF2 \u2212$4.19\" + \"Code CAF2 \u2212$4.19\", on live since v3, fixed 2026-10-12) and read it as an automatic discount.\n  // The legacy list is only for a payload that has no line_level_discount_allocations field at all.\n  const getLineDiscountAllocations = (item) => {\n    if (Array.isArray(item?.line_level_discount_allocations)) {\n      return item.line_level_discount_allocations.map((allocation) => ({\n        amount: Number(allocation.amount || 0),\n        title: String(allocation.discount_application?.title || '').trim(),\n        type: allocation.discount_application?.type || '',\n      }));\n    }\n    return (Array.isArray(item?.discounts) ? item.discounts : []).map((discount) => ({\n      amount: Number(discount.amount || 0),\n      title: String(discount.title || '').trim(),\n      type: '',\n    }));\n  };\n\n  const getCartMath = (cart) => {\n    const config = getConfig();\n    let giftTotal = 0;\n    let hasGift = false;\n    let hasPhysical = false;\n    let itemsOriginal = 0;\n    let bundleQty = 0;\n    let bundleApplied = false;\n    let bundleUnit = 0;\n    let bundleOtherShips = false; // a line that ships and is not a Buy-3 item (a product not looked up yet counts)\n\n    (cart?.items || []).forEach((item) => {\n      itemsOriginal += Number(item.original_line_price || 0);\n      if (isGiftCardLine(item)) {\n        hasGift = true;\n        giftTotal += Number(item.final_line_price || 0);\n      } else {\n        hasPhysical = true;\n      }\n\n      if (config.bundleEnabled && bundleTagCache.get(String(item.product_id)) === true) {\n        bundleQty += Number(item.quantity || 0);\n        const unit = Number(item.final_price || 0);\n        if (!bundleUnit || unit < bundleUnit) bundleUnit = unit;\n        if (getLineDiscountAllocations(item).some((allocation) => allocation.amount > 0 && allocation.type !== 'discount_code')) {\n          bundleApplied = true;\n        }\n      } else if (!isGiftCardLine(item) && item.requires_shipping !== false) {\n        bundleOtherShips = true;\n      }\n    });\n\n    return {\n      hasGift,\n      hasPhysical,\n      itemsOriginal,\n      physicalTotal: Math.max(0, Number(cart?.total_price || 0) - giftTotal),\n      bundleQty,\n      bundleApplied,\n      bundleUnit,\n      bundleOtherShips,\n    };\n  };\n\n  const getDiscountRows = (cart) => {\n    const byTitle = new Map();\n    (cart?.items || []).forEach((item) => {\n      getLineDiscountAllocations(item).forEach((allocation) => {\n        if (!allocation.title || !(allocation.amount > 0)) return;\n        const row = byTitle.get(allocation.title) || { title: allocation.title, type: allocation.type, amount: 0 };\n        row.amount += allocation.amount;\n        byTitle.set(allocation.title, row);\n      });\n    });\n\n    const rows = Array.from(byTitle.values());\n    (Array.isArray(cart?.cart_level_discount_applications) ? cart.cart_level_discount_applications : []).forEach((discount) => {\n      const amount = Number(discount.total_allocated_amount || 0);\n      if (discount.title && amount > 0) rows.push({ title: discount.title, type: discount.type || '', amount });\n    });\n    return rows;\n  };\n\n  const getApplicableCodes = (cart) =>\n    (Array.isArray(cart?.discount_codes) ? cart.discount_codes : [])\n      .filter((discount) => discount?.code && discount.applicable !== false)\n      .map((discount) => discount.code);\n\n  /*\n   * One perk row for Buy 3 + free shipping (owner 2026-10-12) \u2014 SAME rule as `offer_combo` in\n   * sections/cart-template.liquid and `mc_combo` in snippets/cart-drawer.liquid (keep in sync):\n   *   'progress'  under the free-shipping minimum, no discount code, fewer Buy-3 items than the rule needs, and\n   *               that many at the rule's discount clear the minimum on their own (lowest unit price in the cart)\n   *   'done'      the automatic rule is applied and free shipping is reached (no discount code)\n   *   ''          anything else \u2192 the two perks as before\n   * Both states need a cart whose shippable lines are ALL Buy-3 items: one ornament + a $24.99 tumbler is $4.02\n   * from free shipping, a nearer goal than two more ornaments, so a mixed cart keeps the two perks. Gift cards\n   * and other lines that do not ship are left out of this test (the row keeps its gift-card note).\n   * The minimum is an amount in the shop currency (form[data-shop-currency]): a cart in another currency keeps\n   * the two perks. The phone sheet applies the same rule (getBundleOffer in tee-popup-confirm-add-to-cart.js).\n   */\n  const getComboState = (cart, math, config) => {\n    const percent = config.bundlePercent;\n    if (!config.bundleEnabled || !(math.bundleQty > 0) || !math.hasPhysical || !(config.freeMin > 0)) return '';\n    if (math.bundleOtherShips) return '';\n    if (!(percent > 0 && percent < 100)) return '';\n    if (config.shopCurrency && cart?.currency && cart.currency !== config.shopCurrency) return '';\n    if (getApplicableCodes(cart).length || getDiscountRows(cart).some((row) => row.type === 'discount_code')) return '';\n\n    const unlocked = math.physicalTotal >= config.freeMin;\n    if (config.bundleMin - math.bundleQty > 0) {\n      const goal = Math.floor(((100 - percent) * math.bundleUnit * config.bundleMin) / 100);\n      return !unlocked && goal >= config.freeMin ? 'progress' : '';\n    }\n    return math.bundleApplied && unlocked ? 'done' : '';\n  };\n\n  /*\n   * The cart's ONE shipping zone, or '' (2026-10-12). Shopify prices each shipping profile on its own and adds\n   * the rates (an ornament in \"zone 02\" + a tee in \"zone 01\", 2 lb each: $6.98 + $6.98, not the $8.98 of one\n   * table at 4 lb), so the estimate below is right only when every line that ships is in the SAME profile.\n   * Products carry their profile as a tag (zone01 / zone02 / zone03 \u2014 snippets/caf-ship-zone.liquid). '' = mixed\n   * zones, or a line whose zone is unknown: no zone tag, more than one, or not looked up yet (ensureBundleTags).\n   * Lines that do not ship (gift cards, digital) are left out. Twin of the loop in snippets/caf-ship-estimate.liquid.\n   */\n  const getShipZone = (cart) => {\n    let zone = '';\n    for (const item of cart?.items || []) {\n      if (isGiftCardLine(item) || item.requires_shipping === false) continue;\n      const itemZone = shipZoneCache.get(String(item.product_id)) || '';\n      if (!itemZone || (zone && zone !== itemZone)) return '';\n      zone = itemZone;\n    }\n    return zone;\n  };\n\n  /*\n   * Shipping estimate \u2014 split test \"ship\", arm b (owner 2026-10-12). Twin of the 'rate' / 'free' / '' modes in\n   * snippets/cart-drawer.liquid + sections/cart-template.liquid, tiers from snippets/caf-ship-estimate.liquid:\n   *   null                         no estimate \u2192 today's footer: no tiers, nothing ships, gift cards only, no tier\n   *                                for the weight, or the cart is not in one shipping zone (getShipZone) \u2014 never\n   *                                a number the theme cannot stand behind\n   *   { mode: 'free', cents: 0 }   free shipping reached \u2192 \"Free\", estimated total = cart total\n   *   { mode: 'rate', cents }      U.S. rate for the cart weight, compared in 1/10,000 lb (inclusive bounds)\n   */\n  const GRAMS_PER_LB = 453.59237;\n\n  const getShipEstimate = (cart, math, config) => {\n    const ships =\n      typeof cart?.requires_shipping === 'boolean'\n        ? cart.requires_shipping\n        : (cart?.items || []).some((item) => item.requires_shipping !== false && !isGiftCardLine(item));\n    if (!config.shipTiers.length || !math.hasPhysical || !ships) return null;\n    if (!getShipZone(cart)) return null;\n\n    const units = Math.round((Number(cart?.total_weight || 0) * 10000) / GRAMS_PER_LB);\n    const tier = config.shipTiers.find(([bound]) => units <= bound);\n    if (!tier) return null;\n    if (config.freeMin > 0 && math.physicalTotal >= config.freeMin) return { mode: 'free', cents: 0 };\n    return { mode: 'rate', cents: tier[1] };\n  };\n\n  /* ------------------------------------------------------------------ render */\n\n  const renderItemMeta = (item) => {\n    if (isGiftCardLine(item)) {\n      return '<span>Digital gift card</span><span aria-hidden=\"true\"> &middot; </span><span>sent by email</span>';\n    }\n\n    const parts = [];\n    if (Array.isArray(item.options_with_values)) {\n      item.options_with_values.forEach((option) => {\n        if (option.value && option.value !== 'n/a' && option.value !== 'Default Title') {\n          parts.push(escapeHtml(option.value));\n        }\n      });\n    }\n\n    return parts.map((part) => `<span>${part}</span>`).join('<span aria-hidden=\"true\"> &middot; </span>');\n  };\n\n  const renderLinePrice = (item) => {\n    const price = getLinePriceState(item);\n    const quantity = Number(item?.quantity || 0);\n\n    if (price.current > 0) {\n      const onSale = price.original > price.current;\n      return [\n        `<span class=\"money${onSale ? ' sale' : ''}\">${formatMoney(price.current)}</span>`,\n        onSale ? `<span class=\"money was_price\">${formatMoney(price.original)}</span>` : '',\n        quantity > 1 ? `<span class=\"mini-cart__item-each\">${formatMoney(item.final_price)} each</span>` : '',\n      ].join('');\n    }\n\n    return `<span class=\"money\">${escapeHtml(window.PXUTheme?.translation?.cart_free_text || 'Free')}</span>`;\n  };\n\n  const renderUnitPrice = (item) => {\n    if (!item.unit_price_measurement || item.price <= 0) return '';\n\n    const referenceValue =\n      item.unit_price_measurement.reference_value !== 1 ? item.unit_price_measurement.reference_value : '';\n\n    return `<p class=\"mini-cart__unit-price\">${escapeHtml(item.unit_price_measurement.quantity_value)}${escapeHtml(\n      item.unit_price_measurement.quantity_unit,\n    )} | ${formatMoney(item.unit_price)} / ${escapeHtml(referenceValue)}${escapeHtml(\n      item.unit_price_measurement.reference_unit,\n    )}</p>`;\n  };\n\n  const getCartUrl = () => window.PXUTheme?.routes?.cart_url || '/cart';\n\n  const buildCartEditUrl = (customizationId) => {\n    try {\n      const url = new URL(getCartUrl(), window.location.origin);\n      if (customizationId) url.searchParams.set('caf_edit_customization_id', customizationId);\n      return `${url.pathname}${url.search}${url.hash}`;\n    } catch (error) {\n      return '/cart';\n    }\n  };\n\n  const renderMiniCartItems = (cart) => {\n    const config = getConfig();\n\n    return (cart.items || [])\n      .map((item, index) => {\n        const lineID = index + 1;\n        const title = escapeHtml(item.product_title || item.title);\n        const itemUrl = escapeHtml(item.url || '/cart');\n        const imageUrl = getImageUrl(item);\n        const imageWidth = item.featured_image?.width || 320;\n        const imageHeight = item.featured_image?.height || 320;\n        const customizationId = getCustomizationId(item);\n        const quantity = Number(item.quantity || 0);\n        const classes = [\n          'mini-cart__item',\n          customizationId ? 'mini-cart__item--has-customization' : '',\n          isGiftCardLine(item) ? 'mini-cart__item--gift-card' : '',\n        ]\n          .filter(Boolean)\n          .join(' ');\n        const details = customizationId && config.showDetails ? renderLineText(getLineText(item), 'drawer') : '';\n\n        return [\n          `<li class=\"${classes}\" data-cart-item data-line-id=\"${lineID}\" data-line-key=\"${escapeHtml(item.key)}\" data-variant-id=\"${escapeHtml(\n            item.id,\n          )}\" data-product-id=\"${escapeHtml(item.product_id)}\" data-bundle-match=\"${\n            bundleTagCache.get(String(item.product_id)) === true\n          }\" data-ship-zone=\"${escapeHtml(shipZoneCache.get(String(item.product_id)) || '')}\" data-preview-image=\"${escapeHtml(\n            imageUrl,\n          )}\">`,\n          '<div class=\"mini-cart__item-media\">',\n          `<a href=\"${itemUrl}\" title=\"${escapeHtml(item.title)}\">`,\n          imageUrl\n            ? `<div class=\"cart_image mini-cart__item-image\"><img src=\"${escapeHtml(imageUrl)}\" alt=\"${title}\" width=\"${escapeHtml(\n                imageWidth,\n              )}\" height=\"${escapeHtml(imageHeight)}\" loading=\"lazy\" data-caf-cart-preview-src></div>`\n            : '',\n          '</a>',\n          '</div>',\n          '<div class=\"mini-cart__item-content\">',\n          '<div class=\"mini-cart__item-title\">',\n          `<a href=\"${itemUrl}\">${title}</a>`,\n          `<div class=\"mini-cart__item-meta\">${renderItemMeta(item)}</div>`,\n          item.selling_plan_allocation\n            ? `<p class=\"meta\">${escapeHtml(item.selling_plan_allocation.selling_plan.name)}</p>`\n            : '',\n          renderUnitPrice(item),\n          '</div>',\n          '<div class=\"mini-cart__item-buy\">',\n          '<div class=\"product-quantity-box\">',\n          `<button type=\"button\" class=\"ss-icon product-minus js-change-quantity\" data-func=\"minus\" aria-label=\"Decrease quantity\"${\n            quantity <= 1 ? ' disabled' : ''\n          }><span class=\"icon-minus caf-inline-icon\" aria-hidden=\"true\">${icons.minus}</span></button>`,\n          `<input type=\"number\" min=\"0\" size=\"2\" class=\"quantity\" name=\"updates[]\" id=\"updates_${escapeHtml(\n            item.id,\n          )}\" value=\"${escapeHtml(quantity)}\" aria-label=\"Quantity for ${title}\" data-cart-quantity-input=\"mini-cart\">`,\n          `<button type=\"button\" class=\"ss-icon product-plus js-change-quantity\" data-func=\"plus\" aria-label=\"Increase quantity\"><span class=\"icon-plus caf-inline-icon\" aria-hidden=\"true\">${icons.plus}</span></button>`,\n          '</div>',\n          `<div class=\"mini-cart__item-price\">${renderLinePrice(item)}</div>`,\n          '</div>',\n          '</div>',\n          `<a href=\"/cart/change?line=${lineID}&amp;quantity=0\" class=\"js-cart-remove-btn cart__remove-btn\" data-line-id=\"${lineID}\" data-remove-item=\"mini-cart\" aria-label=\"Remove ${title}\"><span class=\"remove-icon caf-inline-icon\" aria-hidden=\"true\">${icons.trash}</span><span class=\"cart__remove-text\">Remove</span></a>`,\n          '<div class=\"mini-cart__item-actions\">',\n          details,\n          '<div class=\"mini-cart__item-buttons\">',\n          '<div class=\"cart__item-image-actions cart__item-preview-source mini-cart__item-preview-source\">',\n          `<div class=\"tee-cart-preview-slot\"${customizationId ? ' aria-busy=\"true\"' : ''}></div>`,\n          '</div>',\n          customizationId\n            ? [\n                `<button type=\"button\" class=\"mini-cart__action-link mini-cart__preview-fallback\" data-mini-cart-preview data-preview-image=\"${escapeHtml(\n                  imageUrl,\n                )}\" data-product-title=\"${title}\"><span class=\"mini-cart__action-icon caf-inline-icon\" aria-hidden=\"true\">${icons.eye}</span><span>Preview</span></button>`,\n                `<a href=\"${escapeHtml(buildCartEditUrl(customizationId))}\" class=\"mini-cart__action-link mini-cart__edit-fallback\" data-mini-cart-edit data-customization-id=\"${escapeHtml(\n                  customizationId,\n                )}\"><span class=\"mini-cart__action-icon caf-inline-icon\" aria-hidden=\"true\">${icons.edit}</span><span>Edit design</span></a>`,\n                `<div class=\"mini-cart__item-edit tee-edit-customization\" data-customization-id=\"${escapeHtml(\n                  customizationId,\n                )}\"></div>`,\n              ].join('')\n            : '',\n          '</div>',\n          '</div>',\n          '</li>',\n        ].join('');\n      })\n      .join('');\n  };\n\n  const renderPerks = (cart) => {\n    const config = getConfig();\n    const math = getCartMath(cart);\n    const showShip = math.hasPhysical && config.freeMin > 0;\n    const remaining = config.freeMin - math.physicalTotal;\n    const unlocked = remaining <= 0;\n    const percentage = unlocked ? 100 : Math.max(4, Math.min(100, Math.floor((math.physicalTotal / config.freeMin) * 100)));\n    const bundleRemaining = config.bundleMin - math.bundleQty;\n    const bundleDone = bundleRemaining <= 0 && math.bundleApplied;\n    const showBundle = config.bundleEnabled && math.bundleQty > 0 && (bundleRemaining > 0 || math.bundleApplied);\n    const combo = getComboState(cart, math, config);\n    const comboCount = combo === 'done' ? config.bundleMin : math.bundleQty;\n    const comboAll = config.bundleMin === 3 ? 'all three' : `all ${config.bundleMin}`;\n    const comboPercent = escapeHtml(config.bundlePercent);\n    const comboHtml =\n      combo === 'done'\n        ? `<strong>${comboPercent}% off your ${escapeHtml(config.bundleNouns)} applied</strong><br>Free shipping unlocked`\n        : combo === 'progress' && bundleRemaining === 1\n          ? `<strong>Add 1 more ${escapeHtml(config.bundleNoun)}</strong><br>${comboPercent}% off ${comboAll} + free shipping`\n          : combo === 'progress'\n            ? `<strong>Add ${bundleRemaining} more ${escapeHtml(config.bundleNouns)}, any&nbsp;designs</strong><br>${comboPercent}% off ${comboAll} + free shipping`\n            : '';\n\n    document.querySelectorAll(selectors.perks).forEach((perks) => {\n      const comboNode = perks.querySelector(selectors.combo);\n      if (comboNode) {\n        setHidden(comboNode, !combo);\n        setClass(comboNode, 'is-done', combo === 'done');\n        setHtml(comboNode.querySelector('[data-mini-cart-combo-message]'), comboHtml);\n        const progress = comboNode.querySelector('[role=\"progressbar\"]');\n        // The bar only moves when the count does (the browser rewrites calc(), so the style can't be compared).\n        if (progress && progress.getAttribute('aria-valuenow') !== String(comboCount)) {\n          progress.setAttribute('aria-valuenow', String(comboCount));\n          progress.setAttribute('aria-valuetext', `${comboCount} of ${config.bundleMin}`);\n          const fill = comboNode.querySelector('.mini-cart__progress-fill');\n          if (fill) fill.style.width = `calc(100% * ${comboCount} / ${config.bundleMin})`;\n        }\n        const count = comboNode.querySelector('[data-mini-cart-combo-count]');\n        setHtml(count, `${comboCount} of ${config.bundleMin}`);\n        setHidden(count, combo !== 'progress');\n        // Gift card + Buy-3 item: the free-shipping perk that carries this note is hidden while the row shows.\n        setHidden(comboNode.querySelector('[data-mini-cart-giftcard-note]'), !(combo === 'progress' && math.hasGift));\n      }\n      // Without the combo node (older markup) the two perks stay as they are.\n      const merged = Boolean(combo && comboNode);\n\n      const ship = perks.querySelector(selectors.freeShipping);\n      if (ship) {\n        ship.hidden = !showShip || merged;\n        ship.classList.toggle('is-done', showShip && unlocked);\n        const message = ship.querySelector('[data-mini-cart-free-shipping-message]');\n        if (message) {\n          message.innerHTML = unlocked\n            ? '<strong>You\u2019ve unlocked free shipping</strong>'\n            : `Add <strong>${formatMoney(Math.max(remaining, 0))}</strong> more for <strong>free shipping</strong>`;\n        }\n        const progress = ship.querySelector('[role=\"progressbar\"]');\n        const fill = ship.querySelector('.mini-cart__progress-fill');\n        if (progress) progress.setAttribute('aria-valuenow', String(percentage));\n        if (fill) fill.style.width = `${percentage}%`;\n        const note = ship.querySelector('[data-mini-cart-giftcard-note]');\n        if (note) note.hidden = !(math.hasGift && math.hasPhysical);\n      }\n\n      const bundle = perks.querySelector(selectors.bundle);\n      if (bundle) {\n        bundle.hidden = !showBundle || merged;\n        bundle.classList.toggle('is-done', bundleDone);\n        const icon = bundle.querySelector('[data-mini-cart-bundle-icon]');\n        if (icon) icon.innerHTML = bundleDone ? icons.check : icons.tag;\n        const message = bundle.querySelector('[data-mini-cart-bundle-message]');\n        if (message) {\n          message.innerHTML = bundleDone\n            ? `<strong>${escapeHtml(config.bundleTitleApplied)}</strong> \u2014 applied`\n            : bundleRemaining > 0\n              ? `<strong>${escapeHtml(config.bundleTitle)}</strong> \u2014 add ${bundleRemaining} more`\n              : '';\n        }\n      }\n\n      perks.hidden = !(showShip || showBundle);\n    });\n\n    // Tax note (only rendered with the hook when taxes aren't included): shipping is settled when\n    // free shipping is reached or nothing ships (gift cards only) \u2014 same copy rule as /cart.\n    const shippingSettled = !math.hasPhysical || (showShip && unlocked);\n    document.querySelectorAll(`${selectors.miniCartForm} [data-mini-cart-tax-note]`).forEach((node) => {\n      node.textContent = shippingSettled ? 'Taxes calculated at checkout.' : 'Taxes and shipping calculated at checkout.';\n    });\n  };\n\n  // Split test \"ship\", arm b: keeps the footer's Shipping row + form[data-ship-estimate] in step with the cart.\n  // Arm a never sees these nodes (caf-rd-cart.css). Returns the estimate for the \"Estimated total\" amount.\n  const renderShipEstimate = (cart) => {\n    const estimate = getShipEstimate(cart, getCartMath(cart), getConfig());\n\n    getForms().forEach((form) => {\n      const row = form.querySelector(selectors.ship);\n      if (!row) return;\n      const state = String(Boolean(estimate));\n      if (form.dataset.shipEstimate !== state) form.dataset.shipEstimate = state;\n      setClass(row, 'is-free', estimate?.mode === 'free');\n      setHtml(\n        row.querySelector('[data-mini-cart-ship-amount]'),\n        estimate ? (estimate.mode === 'free' ? 'Free' : formatMoney(estimate.cents)) : '',\n      );\n      setHidden(row.querySelector('[data-mini-cart-ship-note]'), estimate?.mode !== 'rate');\n    });\n\n    return estimate;\n  };\n\n  const renderRows = (cart) => {\n    const rows = getDiscountRows(cart);\n    const math = getCartMath(cart);\n    const html = rows.length\n      ? [\n          `<div class=\"mini-cart__row\"><span>Items (${Number(cart.item_count || 0)})</span><span class=\"money\">${formatMoney(\n            math.itemsOriginal,\n          )}</span></div>`,\n          ...rows.map(\n            (row) =>\n              `<div class=\"mini-cart__row is-save\"><span>${row.type === 'discount_code' ? 'Code ' : ''}${escapeHtml(\n                row.title,\n              )}</span><span>\u2212${formatMoney(row.amount)}</span></div>`,\n          ),\n        ].join('')\n      : '';\n\n    document.querySelectorAll(`${selectors.miniCartForm} ${selectors.rows}`).forEach((node) => {\n      node.innerHTML = html;\n      node.hidden = !html;\n    });\n  };\n\n  const renderCodes = (cart) => {\n    const codes = getApplicableCodes(cart);\n    const applications = [\n      ...(Array.isArray(cart?.cart_level_discount_applications) ? cart.cart_level_discount_applications : []),\n    ];\n    (cart?.items || []).forEach((item) => {\n      (item.line_level_discount_allocations || []).forEach((allocation) => {\n        if (allocation.discount_application) applications.push(allocation.discount_application);\n      });\n    });\n\n    const html = codes\n      .map((code) => {\n        const application = applications.find(\n          (entry) => String(entry?.title || '').toUpperCase() === String(code).toUpperCase(),\n        );\n        const value = Number(application?.value);\n        const detail =\n          application?.value_type === 'percentage' && Number.isFinite(value) && value > 0 ? ` \u2014 ${value}% off` : '';\n        return `<span class=\"mini-cart__code-chip\">${icons.tag}<span><strong>${escapeHtml(\n          code,\n        )}</strong> applied${escapeHtml(detail)}</span><button type=\"button\" class=\"mini-cart__code-remove\" data-mini-cart-code-remove=\"${escapeHtml(\n          code,\n        )}\" aria-label=\"Remove code ${escapeHtml(code)}\">${icons.close}</button></span>`;\n      })\n      .join('');\n\n    document.querySelectorAll(`${selectors.miniCartForm} ${selectors.codes}`).forEach((node) => {\n      node.innerHTML = html;\n      node.hidden = !html;\n    });\n\n    document.querySelectorAll(`${selectors.miniCartForm} ${selectors.discount}`).forEach((details) => {\n      details.hidden = Boolean(html);\n      if (html) details.open = false;\n    });\n  };\n\n  let statusTimer = null;\n\n  const setStatus = (kind) => {\n    window.clearTimeout(statusTimer);\n    const html =\n      kind === 'adding'\n        ? `${spinner}<span>Adding\u2026</span>`\n        : kind === 'added'\n          ? `${icons.check}<span>Added</span>`\n          : kind === 'updated'\n            ? `${icons.check}<span>Updated</span>`\n            : '';\n\n    document.querySelectorAll(selectors.status).forEach((node) => {\n      node.innerHTML = html;\n      node.dataset.state = kind || '';\n    });\n  };\n\n  const setCount = (count) => {\n    document.querySelectorAll(selectors.count).forEach((node) => {\n      node.textContent = itemsLabel(count);\n      node.hidden = !count;\n    });\n  };\n\n  let removedTitle = '';\n\n  // Long SEO product titles \u2192 the part a shopper recognises (\"Our Little Christmas Miracle \u2013 Personalized\n  // Ornament\" instead of the whole comma list).\n  const shortTitle = (title) => {\n    const text = String(title || '').trim();\n    const head = text.split(',')[0].trim();\n    return head.length >= 12 ? head : text;\n  };\n\n  const renderRemoved = () => {\n    document.querySelectorAll(selectors.removed).forEach((node) => {\n      node.innerHTML = removedTitle\n        ? `<span class=\"mini-cart__removed-icon caf-inline-icon\" aria-hidden=\"true\">${icons.check}</span><span>Removed <strong>${escapeHtml(\n            removedTitle,\n          )}</strong> from your cart.</span>`\n        : '';\n      node.hidden = !removedTitle;\n    });\n  };\n\n  const clearRemoved = () => {\n    if (!removedTitle) return;\n    removedTitle = '';\n    renderRemoved();\n  };\n\n  const setFormState = (state) => {\n    getForms().forEach((form) => {\n      if (state) {\n        form.dataset.state = state;\n      } else {\n        delete form.dataset.state;\n      }\n\n      const button = form.querySelector(selectors.checkout);\n      if (!button) return;\n      const label = button.querySelector('.caf-primary-checkout__label');\n      if (label && !label.dataset.defaultLabel) label.dataset.defaultLabel = label.textContent.trim();\n\n      const busyLabel = state === 'updating' ? 'Updating your cart\u2026' : state === 'checkout' ? 'Opening secure checkout\u2026' : '';\n      button.classList.toggle('is-busy', Boolean(busyLabel));\n      button.toggleAttribute('aria-busy', Boolean(busyLabel));\n      if (label) label.textContent = busyLabel || label.dataset.defaultLabel || 'Proceed to checkout';\n\n      let spin = button.querySelector('.caf-spin');\n      if (busyLabel && !spin) {\n        button.insertAdjacentHTML('afterbegin', spinner);\n      } else if (!busyLabel && spin) {\n        spin.remove();\n      }\n\n      // Never disable the submitter synchronously during a checkout submit (its name=\"checkout\"\n      // must stay in the form data); only the \"updating\" state hard-disables.\n      button.disabled = state === 'updating';\n    });\n  };\n\n  // The Shipping row (arm b) + the Total row. Called again once a product's zone has been looked up.\n  const renderTotal = (cart) => {\n    const shipEstimate = renderShipEstimate(cart);\n\n    // Same markup as snippets/cart-drawer.liquid: today's Total (.caf-ship-a) + \"Estimated total\" (.caf-ship-b,\n    // cart total + the shipping estimate); CSS shows one. One outer label span on purpose.\n    const totalLabel = escapeHtml(getMiniCartTotalLabel());\n    const totalMoney = formatMoney(cart.total_price || 0);\n    const totalHtml = `<span><span class=\"caf-ship-a\">${totalLabel}</span><span class=\"caf-ship-b\">Estimated total</span></span><span class=\"right\"><span class=\"money caf-ship-a\">${totalMoney}</span><span class=\"money caf-ship-b\">${formatMoney(\n      Number(cart.total_price || 0) + (shipEstimate?.cents || 0),\n    )}</span></span>`;\n    // Markup from before 2026-10-12 (a page served while a release is rolling out) has no Shipping row and no\n    // switch rules \u2192 it keeps the single Total.\n    const plainTotalHtml = `<span>${totalLabel}</span><span class=\"right\"><span class=\"money\">${totalMoney}</span></span>`;\n    document.querySelectorAll(`${selectors.miniCartForm} ${selectors.total}`).forEach((node) => {\n      setHtml(node, node.closest(selectors.miniCartForm)?.querySelector(selectors.ship) ? totalHtml : plainTotalHtml);\n    });\n  };\n\n  let renderedCart = null;\n\n  const refreshMiniCart = (cart) => {\n    if (!cart || !Array.isArray(cart.items)) return;\n    renderedCart = cart;\n\n    const count = Number(cart.item_count || 0);\n    document.querySelectorAll('.cart_count').forEach((node) => {\n      node.textContent = String(count);\n      node.classList.toggle('cart_count--zero', !count);\n    });\n\n    getForms().forEach((form) => {\n      form.dataset.totalDiscount = cart.total_discount || 0;\n      form.classList.toggle('hidden', !count);\n    });\n\n    document.querySelectorAll(selectors.urgency).forEach((node) => {\n      node.classList.toggle('hidden', !count);\n    });\n\n    document.querySelectorAll('.cart_content .js-empty-cart__message').forEach((node) => {\n      node.classList.toggle('hidden', Boolean(count));\n    });\n\n    setCount(count);\n\n    document.querySelectorAll(selectors.items).forEach((node) => {\n      if (node.closest(selectors.miniCartForm)) node.innerHTML = renderMiniCartItems(cart);\n    });\n\n    renderPerks(cart);\n    renderRows(cart);\n    renderCodes(cart);\n    renderRemoved();\n    renderTotal(cart);\n\n    setFormState(null);\n\n    if (window.PXUTheme?.currency?.show_multiple_currencies && window.currencyConverter) {\n      window.currencyConverter.convertCurrencies();\n    }\n\n    ensureBundleTags(cart).then((changed) => {\n      // A newer cart may have been rendered while the lookup ran: its own lookup re-renders it.\n      if (!changed || cart !== renderedCart) return;\n      renderPerks(cart);\n      renderTotal(cart);\n      document.querySelectorAll(`${selectors.miniCartForm} [data-cart-item][data-product-id]`).forEach((line) => {\n        const id = String(line.dataset.productId);\n        const match = String(bundleTagCache.get(id) === true);\n        const zone = shipZoneCache.get(id) || '';\n        if (line.dataset.bundleMatch !== match) line.dataset.bundleMatch = match;\n        if (line.dataset.shipZone !== zone) line.dataset.shipZone = zone;\n      });\n    });\n\n    document.dispatchEvent(new CustomEvent('caf:mini-cart-refreshed', { detail: { cart } }));\n  };\n\n  /* ------------------------------------------------------------------ open / close / adding */\n\n  const isVisibleMiniCartContainer = (node) => {\n    if (!(node instanceof HTMLElement)) return false;\n\n    const style = window.getComputedStyle(node);\n    if (style.display === 'none' || style.visibility === 'hidden') return false;\n\n    const rect = node.getBoundingClientRect();\n    return rect.width > 0 && rect.height > 0;\n  };\n\n  const getPreferredMiniCartContainer = () => {\n    const selectorsToTry = [\n      '#header .cart-container',\n      '[data-desktop-header] .cart-container',\n      '.header .cart-container',\n      '.sticky_nav .cart-container',\n      '.top-bar .cart-container',\n      '.cart-container',\n    ];\n\n    const candidates = [];\n\n    for (const selector of selectorsToTry) {\n      document.querySelectorAll(selector).forEach((node) => {\n        if (node.querySelector('.cart_content') && !candidates.includes(node)) candidates.push(node);\n      });\n    }\n\n    return candidates.find(isVisibleMiniCartContainer) || candidates[0] || null;\n  };\n\n  const canOpenMiniCartDrawer = () =>\n    window.matchMedia('(min-width: 799px)').matches && Boolean(getPreferredMiniCartContainer());\n\n  const openMiniCart = () => {\n    if (!canOpenMiniCartDrawer()) return false;\n\n    const container = getPreferredMiniCartContainer();\n    if (!container) return false;\n\n    document.body?.classList.add('caf-mini-cart-open');\n    document.querySelectorAll('.dropdown_link, .cart-container').forEach((node) => {\n      node.classList.remove('active_link');\n    });\n    container.classList.add('active_link');\n    document.dispatchEvent(new CustomEvent('caf:mini-cart-opened', { detail: { source: 'api' } }));\n    return true;\n  };\n\n  const closeMiniCart = () => {\n    document.body?.classList.remove('caf-mini-cart-open', 'is-active', 'blocked-scroll');\n    document.querySelectorAll('.dropdown_link.active_link, .cart-container.active_link').forEach((node) => {\n      node.classList.remove('active_link');\n    });\n    // Closed while still \"Adding\u2026\" (e.g. the add failed): drop the skeleton and repaint from the server\n    // so the next open shows the real cart.\n    if (isAdding()) {\n      setAdding(false);\n      setStatus('');\n      fetchCart().then(refreshMiniCart).catch(() => {});\n    }\n    return true;\n  };\n\n  let addingTimer = null;\n\n  const setAdding = (adding) => {\n    window.clearTimeout(addingTimer);\n    document.querySelectorAll(selectors.drawer).forEach((drawer) => {\n      if (drawer.querySelector(selectors.miniCartForm)) drawer.classList.toggle('is-adding', adding);\n    });\n    if (adding) {\n      setStatus('adding');\n      // Safety net: never leave the skeleton up if the add flow dies silently. The refresh itself is\n      // capped too \u2014 a /cart.js request that never answers must not keep \"Adding\u2026\" on screen.\n      addingTimer = window.setTimeout(() => {\n        let settled = false;\n        const finish = () => {\n          if (settled) return;\n          settled = true;\n          setAdding(false);\n          setStatus('');\n        };\n        const giveUp = window.setTimeout(finish, 5000);\n        fetchCart()\n          .then(refreshMiniCart)\n          .catch(() => {})\n          .then(() => {\n            window.clearTimeout(giveUp);\n            finish();\n          });\n      }, 15000);\n    }\n  };\n\n  const isAdding = () => Boolean(document.querySelector(`${selectors.drawer}.is-adding`));\n\n  const showAddingMiniCart = () => {\n    if (!canOpenMiniCartDrawer()) return false;\n    clearRemoved();\n    setAdding(true);\n    return openMiniCart();\n  };\n\n  const fetchCart = () =>\n    window.fetch('/cart.js', { headers: { Accept: 'application/json' } }).then((response) => {\n      if (!response.ok) throw new Error('Cart refresh failed');\n      return response.json();\n    });\n\n  const fetchRefreshAndOpenMiniCart = (options = {}) => {\n    const reason = typeof options === 'object' && options?.reason ? options.reason : 'added';\n\n    if (reason === 'added') {\n      if (canOpenMiniCartDrawer()) {\n        clearRemoved();\n        setAdding(true);\n      }\n    } else if (!isAdding()) {\n      setStatus('');\n    }\n\n    const openedBeforeRefresh = openMiniCart();\n\n    return (\n      fetchCart()\n        .then((cart) => {\n          refreshMiniCart(cart);\n          setAdding(false);\n          if (reason === 'added' && Number(cart.item_count || 0) > 0) {\n            setStatus('added');\n          } else if (reason === 'updated') {\n            setStatus('updated');\n          } else {\n            setStatus('');\n          }\n          return openedBeforeRefresh || openMiniCart();\n        })\n        // The drawer already opened synchronously above; swallow a refresh failure (network blip /\n        // throttle) so it never becomes an unhandled rejection. Resolve false so the TeeInBlue-add\n        // caller still falls back to the full /cart page rather than showing a stale drawer.\n        .catch(() => {\n          setAdding(false);\n          setStatus('');\n          return false;\n        })\n    );\n  };\n\n  const refreshMiniCartFromServer = () =>\n    fetchCart().then((cart) => {\n      refreshMiniCart(cart);\n      openMiniCart();\n      return cart;\n    });\n\n  /* ------------------------------------------------------------------ dialog focus (v3 kit: role=\"dialog\" aria-modal=\"true\") */\n\n  const FOCUSABLE =\n    'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex=\"-1\"])';\n  let drawerReturnFocus = null;\n\n  const getOpenDrawer = () => document.querySelector('.cart-container.active_link .cart_content');\n\n  const isShown = (node) => node instanceof HTMLElement && !node.hidden && node.getClientRects().length > 0;\n\n  // Another dialog on top (remove confirm / preview hoisted to <body>, the TeeInBlue editor) owns focus.\n  const otherDialogOpen = () =>\n    [...document.querySelectorAll(`${selectors.removeConfirm}, ${selectors.previewModal}, .vm--container`)].some(\n      (node) => !node.closest('.cart_content') && isShown(node),\n    );\n\n  const drawerFocusables = (drawer) =>\n    [...drawer.querySelectorAll(FOCUSABLE)].filter(\n      (node) => node.getClientRects().length > 0 && window.getComputedStyle(node).visibility !== 'hidden',\n    );\n\n  // Opening (cart icon, ATC, reopen after editing) moves focus into the drawer; closing gives it back.\n  const focusIntoDrawer = () => {\n    const drawer = getOpenDrawer();\n    if (!drawer || !document.body?.classList.contains('caf-mini-cart-open')) return;\n    if (drawer.contains(document.activeElement) || otherDialogOpen()) return;\n    const active = document.activeElement;\n    drawerReturnFocus = active instanceof HTMLElement && active !== document.body ? active : null;\n    const close = drawer.querySelector('.cart_content__close');\n    (isShown(close) ? close : drawer).focus({ preventScroll: true });\n  };\n\n  const restoreFocusAfterDrawer = () => {\n    const target = drawerReturnFocus;\n    drawerReturnFocus = null;\n    if (!(target instanceof HTMLElement) || !target.isConnected || otherDialogOpen()) return;\n    const active = document.activeElement;\n    // Only when focus was left inside the (now hidden) drawer or dropped to <body>.\n    if (active && active !== document.body && !active.closest('.cart_content')) return;\n    target.focus({ preventScroll: true });\n  };\n\n  const bindDrawerFocusTrap = () => {\n    document.addEventListener('keydown', (event) => {\n      if (event.key !== 'Tab' || !document.body?.classList.contains('caf-mini-cart-open') || otherDialogOpen()) return;\n      const drawer = getOpenDrawer();\n      if (!drawer) return;\n      const items = drawerFocusables(drawer);\n      if (!items.length) return;\n      const first = items[0];\n      const last = items[items.length - 1];\n      const active = document.activeElement;\n      if (!drawer.contains(active)) {\n        event.preventDefault();\n        (event.shiftKey ? last : first).focus({ preventScroll: true });\n      } else if (event.shiftKey && active === first) {\n        event.preventDefault();\n        last.focus({ preventScroll: true });\n      } else if (!event.shiftKey && active === last) {\n        event.preventDefault();\n        first.focus({ preventScroll: true });\n      }\n    });\n  };\n\n  /* ------------------------------------------------------------------ html.caf-overlay-open (chat bubble steps aside) */\n\n  let overlayClassOwned = false;\n  let drawerWasOpen = false;\n\n  // Shared convention: every overlay sets html.caf-overlay-open (the BeOne chat bubble steps aside).\n  // Prefer the ref-counted helper from caf-rd-header.js (window.CAFChromeOverlay) so two overlays never\n  // clear each other's flag; fall back to \"add if absent / remove only what we added\".\n  const syncOverlayState = () => {\n    const open = Boolean(document.body?.classList.contains('caf-mini-cart-open'));\n    const root = document.documentElement;\n    const shared = window.CAFChromeOverlay;\n\n    if (shared && typeof shared.set === 'function' && !overlayClassOwned) {\n      if (open !== drawerWasOpen) shared.set('mini-cart', open);\n    } else if (open && !root.classList.contains('caf-overlay-open')) {\n      root.classList.add('caf-overlay-open');\n      overlayClassOwned = true;\n    } else if (!open && overlayClassOwned) {\n      root.classList.remove('caf-overlay-open');\n      overlayClassOwned = false;\n    }\n\n    if (open && !drawerWasOpen) window.requestAnimationFrame(focusIntoDrawer);\n\n    if (drawerWasOpen && !open) {\n      // Closing ends the \"just added / removed\" context.\n      if (!isAdding()) setStatus('');\n      clearRemoved();\n      restoreFocusAfterDrawer();\n    }\n    drawerWasOpen = open;\n  };\n\n  /* ------------------------------------------------------------------ discount codes */\n\n  const setDiscountBusy = (wrapper, busy) => {\n    const apply = wrapper.querySelector(selectors.discountApply);\n    const input = wrapper.querySelector(selectors.discountInput);\n    if (input) input.readOnly = busy;\n    if (!apply) return;\n    apply.disabled = busy;\n    apply.classList.toggle('is-busy', busy);\n    if (busy) {\n      apply.setAttribute('aria-busy', 'true');\n      apply.setAttribute('aria-label', 'Applying code');\n      if (!apply.querySelector('.caf-spin')) apply.insertAdjacentHTML('afterbegin', spinner);\n    } else {\n      apply.removeAttribute('aria-busy');\n      apply.removeAttribute('aria-label');\n      apply.querySelector('.caf-spin')?.remove();\n    }\n  };\n\n  const showDiscountError = (wrapper, message) => {\n    const error = wrapper.querySelector(selectors.discountError);\n    const input = wrapper.querySelector(selectors.discountInput);\n    wrapper.classList.add('is-error');\n    if (input) input.setAttribute('aria-invalid', 'true');\n    if (!error) return;\n    error.innerHTML = `<span class=\"caf-cart-discount__error-icon caf-inline-icon\" aria-hidden=\"true\">${icons.alert}</span><span>${message}</span>`;\n    error.hidden = false;\n  };\n\n  const clearDiscountError = (wrapper) => {\n    const error = wrapper.querySelector(selectors.discountError);\n    const input = wrapper.querySelector(selectors.discountInput);\n    wrapper.classList.remove('is-error');\n    if (input) input.removeAttribute('aria-invalid');\n    if (!error) return;\n    error.textContent = '';\n    error.hidden = true;\n  };\n\n  const findDiscountCode = (cart, code) => {\n    const normalizedCode = code.toUpperCase();\n    const codes = Array.isArray(cart?.discount_codes) ? cart.discount_codes : [];\n\n    return codes.find((discount) => discount?.code?.toUpperCase() === normalizedCode);\n  };\n\n  const postDiscountCodes = (codes) =>\n    window\n      .fetch('/cart/update.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n        body: JSON.stringify({ discount: codes.join(',') }),\n      })\n      .then((response) => {\n        if (!response.ok) throw new Error('Discount update failed');\n        return response.json();\n      });\n\n  const applyDiscountUrlWithoutNavigation = (code) =>\n    window.fetch(`/discount/${encodeURIComponent(code)}?redirect=${encodeURIComponent('/cart.js')}`, {\n      credentials: 'same-origin',\n      headers: { Accept: 'application/json, text/javascript, */*; q=0.01' },\n    });\n\n  const invalidCodeMessage = (code) =>\n    `<strong>\u201C${escapeHtml(code)}\u201D</strong> isn\u2019t valid for this cart. Check the spelling, or try another code.`;\n\n  // /cart/update.js `discount` REPLACES the cart's code list (verified on this store 2026-10-04 with an\n  // invalid code: {discount:'XMAS10'} \u2192 applicable:false; {discount:''} \u2192 cleared). So: send the codes\n  // already applied + the new one, and on failure restore the previous list so an invalid code never\n  // lingers on the cart into checkout.\n  const applyMiniCartDiscount = (wrapper) => {\n    const input = wrapper.querySelector(selectors.discountInput);\n    const code = (input?.value || '').trim();\n\n    if (!input) return;\n\n    if (!code) {\n      input.focus();\n      return;\n    }\n\n    clearDiscountError(wrapper);\n    clearRemoved();\n    setDiscountBusy(wrapper, true);\n\n    let previousCodes = [];\n\n    fetchCart()\n      .then((cart) => {\n        previousCodes = getApplicableCodes(cart).filter((existing) => existing.toUpperCase() !== code.toUpperCase());\n        return postDiscountCodes([...previousCodes, code]);\n      })\n      .then((cart) => {\n        const match = findDiscountCode(cart, code);\n        if (match) return cart;\n        // Older shop versions silently ignore the AJAX `discount` param \u2192 silent URL fallback.\n        return applyDiscountUrlWithoutNavigation(code).then(() => fetchCart());\n      })\n      .then((cart) => {\n        const match = findDiscountCode(cart, code);\n        if (match && match.applicable !== false) {\n          refreshMiniCart(cart);\n          openMiniCart();\n          if (input) input.value = '';\n          setDiscountBusy(wrapper, false);\n          return null;\n        }\n\n        return postDiscountCodes(previousCodes)\n          .catch(() => null)\n          .then(() => fetchCart())\n          .then((restored) => {\n            refreshMiniCart(restored);\n            openMiniCart();\n          })\n          .catch(() => null)\n          .then(() => {\n            setDiscountBusy(wrapper, false);\n            const liveWrapper = document.querySelector(`.cart-container.active_link ${selectors.discount}`) || wrapper;\n            const liveInput = liveWrapper.querySelector(selectors.discountInput);\n            liveWrapper.open = true;\n            if (liveInput) {\n              liveInput.value = code;\n              liveInput.focus();\n              liveInput.select();\n            }\n            showDiscountError(liveWrapper, invalidCodeMessage(code));\n          });\n      })\n      .catch(() => {\n        refreshMiniCartFromServer()\n          .catch(() => null)\n          .then(() => {\n            setDiscountBusy(wrapper, false);\n            showDiscountError(wrapper, 'We couldn\u2019t apply that code. Please try again.');\n          });\n      });\n  };\n\n  const removeMiniCartDiscountCode = (button) => {\n    const code = String(button?.dataset.miniCartCodeRemove || '').trim();\n    if (!code) return;\n\n    button.disabled = true;\n    button.insertAdjacentHTML('afterbegin', spinner);\n    suppressMiniCartOutsideClose(1500);\n\n    fetchCart()\n      .then((cart) => postDiscountCodes(getApplicableCodes(cart).filter((existing) => existing.toUpperCase() !== code.toUpperCase())))\n      .then(() => refreshMiniCartFromServer())\n      .catch(() => {\n        window.location.href = getCartUrl();\n      });\n  };\n\n  const bindMiniCartDiscount = () => {\n    document.addEventListener('click', (event) => {\n      const remove = closestElement(event.target, selectors.codeRemove);\n      if (remove && remove.closest(selectors.miniCartForm)) {\n        event.preventDefault();\n        removeMiniCartDiscountCode(remove);\n        return;\n      }\n\n      const apply = closestElement(event.target, selectors.discountApply);\n      if (!apply) return;\n      const wrapper = apply.closest(selectors.discount);\n      if (wrapper) applyMiniCartDiscount(wrapper);\n    });\n\n    document.addEventListener('keydown', (event) => {\n      const input = closestElement(event.target, selectors.discountInput);\n      if (!input || event.key !== 'Enter') return;\n      event.preventDefault();\n      const wrapper = input.closest(selectors.discount);\n      if (wrapper && !input.readOnly) applyMiniCartDiscount(wrapper);\n    });\n\n    document.addEventListener('input', (event) => {\n      const input = closestElement(event.target, selectors.discountInput);\n      const wrapper = input?.closest(selectors.discount);\n      if (wrapper) clearDiscountError(wrapper);\n    });\n\n    // Opening the field focuses it (v3: \"\u00F4 m\u00E3 m\u1EDF s\u1EB5n focus\").\n    document.addEventListener(\n      'toggle',\n      (event) => {\n        const details = event.target;\n        if (!(details instanceof HTMLDetailsElement) || !details.matches(selectors.discount) || !details.open) return;\n        const input = details.querySelector(selectors.discountInput);\n        window.setTimeout(() => input?.focus({ preventScroll: true }), 30);\n      },\n      true,\n    );\n  };\n\n  /* ------------------------------------------------------------------ quantity */\n\n  const clampMiniCartQuantity = (input, quantity) => {\n    const parsedQuantity = Number.parseInt(quantity, 10);\n    const min = Number.parseInt(input?.getAttribute('min') || '0', 10);\n    const maxAttribute = input?.getAttribute('max');\n    const max = maxAttribute == null ? Number.POSITIVE_INFINITY : Number.parseInt(maxAttribute, 10);\n    const safeQuantity = Number.isFinite(parsedQuantity) ? parsedQuantity : min;\n    const safeMin = Number.isFinite(min) ? min : 0;\n    const safeMax = Number.isFinite(max) ? max : Number.POSITIVE_INFINITY;\n\n    return Math.max(safeMin, Math.min(safeQuantity, safeMax));\n  };\n\n  const setMiniCartLineBusy = (itemNode, busy, label = 'Updating\u2026') => {\n    if (!itemNode) return;\n\n    itemNode.toggleAttribute('aria-busy', busy);\n    itemNode.classList.toggle('is-updating', busy);\n    itemNode.querySelectorAll(`${selectors.quantityInput}, ${selectors.quantityButton}`).forEach((control) => {\n      if (busy) {\n        control.setAttribute('aria-disabled', 'true');\n      } else {\n        control.removeAttribute('aria-disabled');\n      }\n    });\n\n    itemNode.querySelector('.mini-cart__busy')?.remove();\n    if (busy) {\n      itemNode.insertAdjacentHTML(\n        'beforeend',\n        `<span class=\"mini-cart__busy\" role=\"status\"><span class=\"mini-cart__busy-pill\">${spinner}<span>${escapeHtml(label)}</span></span></span>`,\n      );\n    }\n\n    itemNode.style.pointerEvents = busy ? 'none' : '';\n  };\n\n  const updateMiniCartLineQuantity = (input, quantity) => {\n    const itemNode = input?.closest('[data-cart-item]');\n    const line = Number(itemNode?.dataset.lineId || 0);\n\n    if (!input || !itemNode || !line) {\n      window.location.href = '/cart';\n      return;\n    }\n\n    const nextQuantity = clampMiniCartQuantity(input, quantity);\n\n    // Removing always goes through the confirmation (a personalized design would be lost).\n    if (nextQuantity <= 0) {\n      input.value = input.defaultValue || '1';\n      const removeButton = itemNode.querySelector(selectors.removeTrigger);\n      if (removeButton) openMiniCartRemoveConfirm(removeButton);\n      return;\n    }\n\n    input.value = String(nextQuantity);\n    clearRemoved();\n    if (!isAdding()) setStatus(''); // the shopper changed the cart \u2014 drop a stale \"\u2713 Added\" (review 2026-10-09)\n    setMiniCartLineBusy(itemNode, true);\n    setFormState('updating');\n    suppressMiniCartOutsideClose(1200);\n    openMiniCart();\n\n    window\n      .fetch('/cart/change.js', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          Accept: 'application/json',\n        },\n        body: JSON.stringify({ line, quantity: nextQuantity }),\n      })\n      .then((response) => {\n        if (!response.ok) throw new Error('Cart quantity update failed');\n        return refreshMiniCartFromServer();\n      })\n      .catch(() => {\n        setMiniCartLineBusy(itemNode, false);\n        setFormState(null);\n        window.location.href = '/cart';\n      });\n  };\n\n  const bindMiniCartQuantity = () => {\n    document.addEventListener(\n      'click',\n      (event) => {\n        const button = closestFromEvent(event, selectors.quantityButton);\n        if (!button || !button.closest(selectors.miniCartForm)) return;\n\n        const input = button.parentElement?.querySelector(selectors.quantityInput);\n        if (!input) return;\n\n        event.preventDefault();\n        event.stopImmediatePropagation();\n\n        if (button.disabled || button.getAttribute('aria-disabled') === 'true') return;\n\n        const currentQuantity = clampMiniCartQuantity(input, input.value);\n        if (button.dataset.func !== 'plus' && currentQuantity <= 1) return; // \u2212 is locked at 1 (use Remove)\n\n        const nextQuantity = button.dataset.func === 'plus' ? currentQuantity + 1 : currentQuantity - 1;\n        updateMiniCartLineQuantity(input, nextQuantity);\n      },\n      true,\n    );\n\n    document.addEventListener(\n      'change',\n      (event) => {\n        const input = closestFromEvent(event, selectors.quantityInput);\n        if (!input || !input.closest(selectors.miniCartForm)) return;\n\n        event.preventDefault();\n        event.stopImmediatePropagation();\n        updateMiniCartLineQuantity(input, input.value);\n      },\n      true,\n    );\n  };\n\n  /* ------------------------------------------------------------------ checkout feedback */\n\n  const bindMiniCartCheckout = () => {\n    document.addEventListener(\n      'submit',\n      (event) => {\n        const form = event.target;\n        if (!(form instanceof HTMLFormElement) || !form.matches(selectors.miniCartForm)) return;\n\n        const submitter = event.submitter;\n        if (form.dataset.state === 'updating') {\n          event.preventDefault();\n          return;\n        }\n        if (form.dataset.state === 'checkout') {\n          event.preventDefault(); // double click \u2014 the first submit is already on its way\n          return;\n        }\n        if (!submitter || submitter.name !== 'checkout') return;\n\n        // Instant feedback; Shopify then takes over (/checkouts). The state is applied only after the\n        // submit has captured its form data (name=\"checkout\" must be included), and never disables\n        // the button itself. Safety reset if the navigation never happens.\n        window.setTimeout(() => {\n          if (event.defaultPrevented) return;\n          setFormState('checkout');\n          window.setTimeout(() => {\n            if (form.dataset.state === 'checkout') setFormState(null);\n          }, 15000);\n        }, 0);\n      },\n      false,\n    );\n\n    // Back/forward cache: never come back to a spinning checkout button.\n    window.addEventListener('pageshow', (event) => {\n      if (event.persisted) setFormState(null);\n    });\n  };\n\n  /* ------------------------------------------------------------------ preview modal (theme fallback) */\n\n  let lastMiniCartPreviewTrigger = null;\n\n  const ensureMiniCartPreviewModal = () => {\n    let modal = document.querySelector(selectors.previewModal);\n    if (modal) return modal;\n\n    modal = document.createElement('div');\n    modal.className = 'mini-cart-preview-modal';\n    modal.setAttribute('data-mini-cart-preview-modal', '');\n    modal.hidden = true;\n    modal.innerHTML = [\n      '<button type=\"button\" class=\"mini-cart-preview-modal__overlay\" data-mini-cart-preview-close aria-label=\"Close preview\" tabindex=\"-1\"></button>',\n      '<div class=\"mini-cart-preview-modal__dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"caf-mini-cart-preview-title\">',\n      `<button type=\"button\" class=\"mini-cart-preview-modal__close\" data-mini-cart-preview-close aria-label=\"Close preview\">${icons.close}</button>`,\n      '<h2 class=\"mini-cart-preview-modal__title\" id=\"caf-mini-cart-preview-title\">Your design</h2>',\n      '<p class=\"mini-cart-preview-modal__sub\" data-mini-cart-preview-sub></p>',\n      '<div class=\"mini-cart-preview-modal__media\"><img class=\"mini-cart-preview-modal__image\" alt=\"\"></div>',\n      '<div class=\"mini-cart-preview-modal__details\" data-mini-cart-preview-details></div>',\n      '<div class=\"mini-cart-preview-modal__actions\">',\n      `<button type=\"button\" class=\"mini-cart-preview-modal__edit\" data-mini-cart-preview-edit>${icons.edit}<span>Edit design</span></button>`,\n      `<button type=\"button\" class=\"mini-cart-preview-modal__ok\" data-mini-cart-preview-close>${icons.check}<span>Looks good</span></button>`,\n      '</div>',\n      '</div>',\n    ].join('');\n\n    modal.addEventListener('click', (event) => {\n      const editTrigger = closestElement(event.target, selectors.previewEdit);\n      if (editTrigger) {\n        event.preventDefault();\n        editFromPreview();\n      } else if (closestElement(event.target, selectors.previewClose)) {\n        event.preventDefault();\n        closeMiniCartPreview();\n      }\n\n      event.stopPropagation();\n    });\n\n    document.body.appendChild(modal);\n    return modal;\n  };\n\n  let previewLine = null;\n\n  const closeMiniCartPreview = ({ restoreFocus = true } = {}) => {\n    const modal = document.querySelector(selectors.previewModal);\n    if (!modal || modal.hidden) return;\n\n    suppressMiniCartOutsideClose();\n    modal.hidden = true;\n    document.documentElement.classList.remove('mini-cart-preview-open');\n    document.body?.classList.remove('mini-cart-preview-open');\n\n    if (restoreFocus && lastMiniCartPreviewTrigger instanceof HTMLElement && document.contains(lastMiniCartPreviewTrigger)) {\n      lastMiniCartPreviewTrigger.focus({ preventScroll: true });\n    }\n  };\n\n  // \"Edit design\" inside the preview clicks the REAL TeeInBlue edit button of that line (same path as\n  // the drawer's own Edit); without an injected button it follows the /cart?caf_edit_customization_id route.\n  const editFromPreview = () => {\n    const line = previewLine;\n    closeMiniCartPreview({ restoreFocus: false });\n    if (!(line instanceof HTMLElement) || !document.contains(line)) return;\n\n    const injected = line.querySelector('.tee-edit-customization[data-customization-id] :is(button, a, [role=\"button\"])');\n    if (injected instanceof HTMLElement) {\n      injected.click();\n      return;\n    }\n\n    const fallback = line.querySelector('[data-mini-cart-edit]');\n    if (fallback instanceof HTMLAnchorElement) window.location.href = fallback.href;\n  };\n\n  const openMiniCartPreview = (trigger) => {\n    const itemNode = trigger.closest('[data-cart-item]');\n    const imageNode = itemNode?.querySelector('[data-caf-cart-preview-src], .mini-cart__item-image img');\n    const imageUrl = normalizeCartImageUrl(\n      trigger.dataset.previewImage ||\n        itemNode?.dataset.previewImage ||\n        imageNode?.dataset.cafCartPreviewSrc ||\n        imageNode?.currentSrc ||\n        imageNode?.src ||\n        '',\n    );\n\n    if (!isLikelyCartImageUrl(imageUrl)) return;\n\n    const modal = ensureMiniCartPreviewModal();\n    const modalImage = modal.querySelector('.mini-cart-preview-modal__image');\n    const closeButton = modal.querySelector('.mini-cart-preview-modal__close');\n    const title =\n      trigger.dataset.productTitle ||\n      itemNode?.querySelector('.mini-cart__item-title a')?.textContent?.trim() ||\n      'Your design';\n\n    if (modalImage instanceof HTMLImageElement) {\n      modalImage.src = imageUrl;\n      modalImage.alt = `Design preview: ${title}`;\n    }\n\n    const sub = modal.querySelector('[data-mini-cart-preview-sub]');\n    if (sub) sub.textContent = title;\n\n    const detailsSlot = modal.querySelector('[data-mini-cart-preview-details]');\n    if (detailsSlot) {\n      const details = itemNode?.querySelector('[data-caf-text-line]');\n      detailsSlot.innerHTML = details ? details.outerHTML.replace('caf-text-line--drawer', 'caf-text-line--preview') : '';\n      detailsSlot.hidden = !details;\n    }\n\n    previewLine = itemNode;\n    lastMiniCartPreviewTrigger = trigger;\n    modal.hidden = false;\n    document.documentElement.classList.add('mini-cart-preview-open');\n    document.body?.classList.add('mini-cart-preview-open');\n    closeButton?.focus({ preventScroll: true });\n  };\n\n  const bindMiniCartPreview = () => {\n    document.addEventListener('click', (event) => {\n      if (closestElement(event.target, selectors.previewModal)) return;\n\n      const previewTrigger = closestElement(event.target, selectors.previewTrigger);\n      if (!previewTrigger) return;\n\n      event.preventDefault();\n      event.stopPropagation();\n      openMiniCartPreview(previewTrigger);\n    });\n\n    document.addEventListener('keydown', (event) => {\n      if (event.key !== 'Escape') return;\n      closeMiniCartPreview();\n    });\n  };\n\n  /* ------------------------------------------------------------------ remove (with confirmation) */\n\n  let activeMiniCartRemoveButton = null;\n  let activeMiniCartRemoveModal = null;\n  let activeMiniCartRemoveContainer = null;\n  let lastMiniCartRemoveFocus = null;\n\n  const getMiniCartContainer = (removeButton, modal) =>\n    removeButton?.closest('.cart-container') ||\n    modal?.closest('.cart-container') ||\n    document.querySelector('.cart-container.active_link');\n\n  const restoreMiniCartContainer = (container) => {\n    if (!(container instanceof HTMLElement) || !document.contains(container)) return;\n\n    document.body?.classList.add('caf-mini-cart-open');\n    container.classList.add('active_link');\n  };\n\n  const scheduleMiniCartRestore = (container) => {\n    if (!(container instanceof HTMLElement)) return;\n    [0, 80, 240].forEach((delay) => {\n      window.setTimeout(() => restoreMiniCartContainer(container), delay);\n    });\n  };\n\n  const getMiniCartRemoveImage = (removeButton) => {\n    const itemNode = removeButton?.closest('[data-cart-item]');\n    const imageNode = itemNode?.querySelector('[data-caf-cart-preview-src], .mini-cart__item-image img');\n    const imageUrl = normalizeCartImageUrl(\n      itemNode?.dataset.previewImage ||\n        imageNode?.dataset.cafCartPreviewSrc ||\n        imageNode?.currentSrc ||\n        imageNode?.src ||\n        '',\n    );\n\n    return isLikelyCartImageUrl(imageUrl) ? imageUrl : '';\n  };\n\n  const fillMiniCartRemoveConfirm = (modal, removeButton) => {\n    const itemNode = removeButton?.closest('[data-cart-item]');\n    const title = itemNode?.querySelector('.mini-cart__item-title a')?.textContent?.trim() || 'this item';\n    const meta = itemNode?.querySelector('.mini-cart__item-meta')?.textContent?.replace(/\\s+/g, ' ').trim() || '';\n    const forName = itemNode?.querySelector('[data-caf-details-for]')?.dataset.cafDetailsFor || '';\n    const personalized = Boolean(itemNode?.classList.contains('mini-cart__item--has-customization'));\n\n    const image = modal.querySelector(selectors.removeConfirmImage);\n    if (image instanceof HTMLImageElement) {\n      const imageUrl = getMiniCartRemoveImage(removeButton);\n      if (imageUrl) {\n        image.src = imageUrl;\n        image.alt = '';\n        image.hidden = false;\n      } else {\n        image.hidden = true;\n        image.removeAttribute('src');\n      }\n    }\n\n    const name = modal.querySelector('[data-cart-remove-confirm-name]');\n    if (name) name.textContent = title;\n    const metaNode = modal.querySelector('[data-cart-remove-confirm-meta]');\n    if (metaNode) metaNode.textContent = [forName ? `For ${forName}` : '', meta].filter(Boolean).join(' \u00B7 ');\n    const text = modal.querySelector('[data-cart-remove-confirm-text]');\n    if (text) {\n      text.textContent = personalized\n        ? 'Your personalization will be removed too \u2014 you would need to design it again.'\n        : 'You can add it again anytime.';\n    }\n  };\n\n  const closeMiniCartRemoveConfirm = ({ restoreMiniCart = true } = {}) => {\n    const modal =\n      activeMiniCartRemoveModal ||\n      document.querySelector(`.cart-container.active_link .cart_content ${selectors.removeConfirm}`) ||\n      document.querySelector(selectors.removeConfirm);\n    if (!modal || modal.hidden) return;\n    const miniCartContainer = activeMiniCartRemoveContainer || getMiniCartContainer(activeMiniCartRemoveButton, modal);\n\n    suppressMiniCartOutsideClose();\n    modal.hidden = true;\n    modal.setAttribute('aria-hidden', 'true');\n    document.documentElement.classList.remove('caf-cart-remove-confirm-open');\n    document.body?.classList.remove('caf-cart-remove-confirm-open');\n\n    if (lastMiniCartRemoveFocus instanceof HTMLElement && document.contains(lastMiniCartRemoveFocus)) {\n      lastMiniCartRemoveFocus.focus({ preventScroll: true });\n    }\n\n    if (restoreMiniCart) scheduleMiniCartRestore(miniCartContainer);\n\n    activeMiniCartRemoveButton = null;\n    activeMiniCartRemoveModal = null;\n    activeMiniCartRemoveContainer = null;\n    lastMiniCartRemoveFocus = null;\n  };\n\n  function openMiniCartRemoveConfirm(removeButton) {\n    // Reuse the copy already hoisted to <body> before taking another one from a drawer clone.\n    const modal =\n      removeButton.closest('.cart_content')?.querySelector(selectors.removeConfirm) ||\n      document.querySelector(`body > ${selectors.removeConfirm}`) ||\n      document.querySelector(`.cart-container.active_link .cart_content ${selectors.removeConfirm}`) ||\n      document.querySelector(selectors.removeConfirm);\n    if (!modal) return;\n\n    activeMiniCartRemoveButton = removeButton;\n    activeMiniCartRemoveModal = modal;\n    activeMiniCartRemoveContainer = getMiniCartContainer(removeButton, modal);\n    lastMiniCartRemoveFocus = document.activeElement instanceof HTMLElement ? document.activeElement : removeButton;\n\n    // Hoisted to <body> so the fixed drawer's stacking/overflow never swallows clicks (2026-05-09);\n    // caf-rd-cart.css lays it over the drawer column.\n    if (modal.parentElement !== document.body) {\n      document.body.appendChild(modal);\n    }\n\n    fillMiniCartRemoveConfirm(modal, removeButton);\n\n    modal.hidden = false;\n    modal.setAttribute('aria-hidden', 'false');\n    document.documentElement.classList.add('caf-cart-remove-confirm-open');\n    document.body?.classList.add('caf-cart-remove-confirm-open');\n\n    const keep = modal.querySelector('.caf-cart-remove-confirm__cancel');\n    const dialog = modal.querySelector('.caf-cart-remove-confirm__dialog');\n    if (keep instanceof HTMLElement) {\n      keep.focus({ preventScroll: true });\n    } else if (dialog instanceof HTMLElement) {\n      dialog.focus({ preventScroll: true });\n    }\n  }\n\n  const removeMiniCartLine = (removeButton) => {\n    const itemNode = removeButton?.closest('[data-cart-item]');\n    const line = Number(itemNode?.dataset.lineId || removeButton?.dataset.lineId || 0);\n    const title = itemNode?.querySelector('.mini-cart__item-title a')?.textContent?.trim() || '';\n\n    if (!line) {\n      window.location.href = removeButton?.href || '/cart';\n      return;\n    }\n\n    setMiniCartLineBusy(itemNode, true, 'Removing\u2026');\n    setFormState('updating');\n    removeButton.setAttribute('aria-busy', 'true');\n    suppressMiniCartOutsideClose(1200);\n    openMiniCart();\n\n    window\n      .fetch('/cart/change.js', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          Accept: 'application/json',\n        },\n        body: JSON.stringify({ line, quantity: 0 }),\n      })\n      .then((response) => {\n        if (!response.ok) throw new Error('Cart remove failed');\n        removedTitle = shortTitle(title);\n        setStatus(''); // \"\u2713 Added\" no longer describes the cart once something was removed (review 2026-10-09)\n        return refreshMiniCartFromServer();\n      })\n      .catch(() => {\n        window.location.href = removeButton.href || '/cart';\n      });\n  };\n\n  const confirmMiniCartRemove = () => {\n    if (!activeMiniCartRemoveButton) return;\n\n    const removeButton = activeMiniCartRemoveButton;\n    closeMiniCartRemoveConfirm();\n    removeMiniCartLine(removeButton);\n  };\n\n  const bindMiniCartRemoveConfirmation = () => {\n    window.CAFMiniCartCloseRemoveConfirm = (trigger, event) => {\n      event?.preventDefault();\n      event?.stopPropagation();\n      event?.stopImmediatePropagation?.();\n\n      const modal = trigger?.closest?.(selectors.removeConfirm);\n      if (modal) activeMiniCartRemoveModal = modal;\n      closeMiniCartRemoveConfirm();\n      return false;\n    };\n\n    window.CAFMiniCartConfirmRemove = (trigger, event) => {\n      event?.preventDefault();\n      event?.stopPropagation();\n      event?.stopImmediatePropagation?.();\n\n      const modal = trigger?.closest?.(selectors.removeConfirm);\n      if (modal) activeMiniCartRemoveModal = modal;\n      confirmMiniCartRemove();\n      return false;\n    };\n\n    const handleConfirmSurfaceEvent = (event) => {\n      const closeButton = closestFromEvent(event, selectors.removeConfirmClose);\n      const confirmButton = closestFromEvent(event, selectors.removeConfirmRemove);\n\n      if (!closeButton && !confirmButton) return;\n      if (!closestFromEvent(event, selectors.removeConfirm)) return;\n\n      event.preventDefault();\n      event.stopImmediatePropagation();\n\n      if (event.type !== 'click') return; // act once (on click); pointerdown only blocks outside-close\n\n      if (closeButton) {\n        closeMiniCartRemoveConfirm();\n      } else {\n        confirmMiniCartRemove();\n      }\n    };\n\n    ['pointerdown', 'click'].forEach((eventName) => {\n      document.addEventListener(eventName, handleConfirmSurfaceEvent, true);\n    });\n\n    document.addEventListener(\n      'click',\n      (event) => {\n        const removeButton = closestFromEvent(event, selectors.removeTrigger);\n        if (!removeButton || !removeButton.closest(selectors.miniCartForm)) return;\n\n        event.preventDefault();\n        event.stopImmediatePropagation();\n        openMiniCartRemoveConfirm(removeButton);\n      },\n      true,\n    );\n\n    document.addEventListener('keydown', (event) => {\n      if (event.key !== 'Escape') return;\n      closeMiniCartRemoveConfirm();\n    });\n  };\n\n  /* ------------------------------------------------------------------ reservation timer (owner: keep) */\n\n  let miniCartCountdownInterval = null;\n\n  const initMiniCartCountdown = () => {\n    const countdownNodes = document.querySelectorAll('[data-mini-cart-countdown-message]');\n\n    if (miniCartCountdownInterval) {\n      window.clearInterval(miniCartCountdownInterval);\n      miniCartCountdownInterval = null;\n    }\n\n    if (!countdownNodes.length) return;\n\n    // Wall-clock based: background tabs throttle intervals, so counting ticks would run slow.\n    const total = Number(window.PXUTheme?.theme_settings?.cart_expire_timer || 10) * 60;\n    const startedAt = Date.now();\n\n    const render = () => {\n      const remaining = Math.max(0, total - Math.floor((Date.now() - startedAt) / 1000));\n      const expired = remaining <= 0;\n      const minutes = Math.floor(remaining / 60);\n      const seconds = remaining % 60;\n      const timerDisplay = `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;\n\n      countdownNodes.forEach((node) => {\n        node.innerHTML = expired\n          ? 'Your items are still in your cart \u2014 check out whenever you\u2019re ready.'\n          : `Your cart is saved for <strong class=\"cart-page-countdown-timer\">${timerDisplay}</strong> \u2014 no rush, take your time.`;\n        node.closest(selectors.urgency)?.classList.toggle('is-expired', expired);\n      });\n\n      if (expired) {\n        window.clearInterval(miniCartCountdownInterval);\n        miniCartCountdownInterval = null;\n      }\n    };\n\n    render();\n    miniCartCountdownInterval = window.setInterval(render, 1000);\n  };\n\n  /* ------------------------------------------------------------------ /cart?caf_edit_customization_id (fallback Edit route) */\n\n  const clearCartEditCustomizationParam = () => {\n    try {\n      const url = new URL(window.location.href);\n      url.searchParams.delete('caf_edit_customization_id');\n      window.history.replaceState(null, '', `${url.pathname}${url.search}${url.hash}`);\n    } catch (error) {\n      // Non-critical: leaving the param in place is safer than interrupting edit.\n    }\n  };\n\n  const isElementVisible = (element) => {\n    if (!element || !element.getClientRects().length) return false;\n    const style = window.getComputedStyle(element);\n    return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n  };\n\n  const findVisibleCartEditButton = (customizationId) => {\n    const wrappers = Array.from(document.querySelectorAll('.tee-edit-customization[data-customization-id]'));\n    const matchingWrappers = wrappers.filter((wrapper) => wrapper.dataset.customizationId === customizationId);\n\n    for (const wrapper of matchingWrappers) {\n      const button = wrapper.querySelector('button, a, [role=\"button\"]');\n      if (isElementVisible(button)) return button;\n    }\n\n    return null;\n  };\n\n  const maybeOpenCartEditFromUrl = () => {\n    let customizationId = '';\n\n    try {\n      customizationId = new URL(window.location.href).searchParams.get('caf_edit_customization_id') || '';\n    } catch (error) {\n      return;\n    }\n\n    if (!customizationId || !document.body.classList.contains('cart')) return;\n\n    let isDone = false;\n    let attempts = 0;\n    let observer = null;\n    let intervalId = null;\n\n    const cleanup = () => {\n      isDone = true;\n      if (observer) observer.disconnect();\n      if (intervalId) window.clearInterval(intervalId);\n    };\n\n    const tryOpen = () => {\n      if (isDone) return true;\n\n      const button = findVisibleCartEditButton(customizationId);\n      if (!button) return false;\n\n      cleanup();\n      clearCartEditCustomizationParam();\n      button.click();\n      return true;\n    };\n\n    if (tryOpen()) return;\n\n    observer = new MutationObserver(() => {\n      tryOpen();\n    });\n    observer.observe(document.body, { childList: true, subtree: true });\n\n    intervalId = window.setInterval(() => {\n      attempts += 1;\n      if (tryOpen()) return;\n      if (attempts >= 40) cleanup();\n    }, 250);\n  };\n\n  /* ------------------------------------------------------------------ bootstrap */\n\n  const bootstrap = () => {\n    window.refreshCart = refreshMiniCart;\n    window.CAFMiniCartDrawer = {\n      canOpen: canOpenMiniCartDrawer,\n      close: closeMiniCart,\n      fetchRefreshAndOpen: fetchRefreshAndOpenMiniCart,\n      open: openMiniCart,\n      refresh: refreshMiniCart,\n      showAdding: showAddingMiniCart,\n    };\n\n    seedBundleTagCache();\n    bindMiniCartDiscount();\n    bindMiniCartQuantity();\n    bindMiniCartCheckout();\n    bindMiniCartPreview();\n    bindMiniCartRemoveConfirmation();\n    bindDrawerFocusTrap();\n    initMiniCartCountdown();\n    maybeOpenCartEditFromUrl();\n\n    if (document.body) {\n      new MutationObserver(syncOverlayState).observe(document.body, { attributes: true, attributeFilter: ['class'] });\n      syncOverlayState();\n    }\n\n    if (!getForms().length) return;\n\n    fetchCart()\n      .then((cart) => {\n        // Don't clobber an \"Adding\u2026\" skeleton that an ATC started before this first refresh resolved.\n        if (!isAdding()) refreshMiniCart(cart);\n      })\n      .catch(() => {});\n  };\n\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', bootstrap);\n  } else {\n    bootstrap();\n  }\n})();\n"],
  "mappings": "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",
  "names": []
}
