{
  "version": 3,
  "sources": ["/cdn/shop/t/224/assets/aw-cart-sync.js?r=20260818b"],
  "sourcesContent": ["/* aw-cart-sync.js - VARIANT C FORK (2026-07-18, live-test rule 4)\n * Identical to theme B's aw-cart-sync.js except syncOffer(), which now\n * REPLACES the cart's discount-code set via the cart API instead of\n * appending via /discount/{code}. Appending let Shopify keep whichever\n * attached code paid the customer most (home77 -$77 beat family33 -$74.91\n * on 6 jug carts - Brian's 2026-07-18 report + Round 1 finding 6).\n * POST-TEST BACK-PORT CANDIDATE for B: never back-deploy mid-Round-1.\n *\n * Cart-side guardian for the water delivery flow. Three jobs:\n *  1. Keep the refundable bottle deposit quantity locked 1:1 to the water bottle\n *     quantity on ANY cart change. The change listener catches the drawer's\n *     quantity selects; a debounced MutationObserver on [data-products] catches\n *     everything else (remove links, +/- steppers, the theme's own re-renders).\n *     Corrections require a confirmed double-read: the legacy theme's own qty\n *     sequence writes deposits FIRST and water SECOND, so single snapshots lie.\n *  2. Own the drawer's \"Renews at\" line: published-curve math, shown only while\n *     a subscription line is in the cart. Never the legacy theme.js math\n *     ($24/bottle - the $48/$96/$144 quotes).\n *  3. Keep the auto-applied first-order discount code matched to the cart\n *     composition after cart edits (see syncOffer below).\n *\n * Re-renders go through the theme's own cart:build event so theme.js rebinds its\n * listeners; we never replace [data-products] innerHTML ourselves.\n * Deploy note: Rollouts serving contexts refresh asset digests only on a REAL\n * content change while the experiment is running (identical upserts dedupe;\n * events fired while paused are missed) - hence this line, 2026-07-17.\n */\nconst DEPOSIT_VARIANT_ID = 50052669866266; // One-Time Refundable Deposit (see theme-launch-admin-checklist.md)\nconst WATER_HANDLE = 'spring-water-delivery';\nconst DEPOSIT_HANDLES = ['refundable-jug-deposit', 'one-time-refundable-deposit'];\nconst DISPENSER_PRODUCT_ID = 8076964419; // 2.5 Gallon Dispenser\n\n/* Shared cart transport (2026-08-07, add-to-cart 429 fix).\n * The singleton on window.__awCartNet is created by whichever of\n * aw-guided-flow.js / this file loads first; the full rationale and the measured\n * read-amplification trace live at the top of aw-guided-flow.js. Short version:\n * one tap of the order-page CTA put ~15 /cart.js requests on the wire, several\n * simultaneous, and the edge answered the losers with 429 + an HTML challenge\n * body. This module contributed 3 of those reads and could dispatch a second\n * 'cart:build', which is what makes the two installed apps re-read the cart.\n * Routing through the singleton means concurrent readers share ONE request and\n * every write is serialised. This file also ships on pages with no wizard, so\n * every helper falls back to a plain fetch of the same shape when the singleton\n * is absent. Keep in sync with aw-guided-flow.js. */\nfunction awNet() { return window.__awCartNet || null; }\n\nasync function cartRead(fresh) {\n  const n = awNet();\n  if (n) return n.readSoft({ fresh: !!fresh });\n  try {\n    const r = await fetch('/cart.js');\n    const t = await r.text();\n    // /cart.js is text/javascript; an edge block is identifiable by an HTML body.\n    if (!r.ok || t.trim().charAt(0) === '<') return null;\n    return JSON.parse(t);\n  } catch (_) { return null; }\n}\n\nasync function cartPost(url, payload) {\n  const n = awNet();\n  if (n) return n.post(url, payload);\n  try {\n    const r = await fetch(url, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(payload),\n    });\n    return { ok: r.ok, status: r.status, transient: r.status === 429 || r.status >= 500 };\n  } catch (_) { return { ok: false, status: 0, transient: true }; }\n}\n\nfunction cartAnnounce() {\n  const n = awNet();\n  if (n) return n.announce();\n  try { document.dispatchEvent(new CustomEvent('cart:build')); } catch (_) {}\n}\n\nlet timer = null;\nlet busy = false;\nlet dirtyWhileBusy = false; // mutations that land during a pass queue one follow-up\nlet settleChecked = false; // one bounded follow-up pass per trigger burst\n\n/* Circuit breaker: this module should write to the cart a handful of times per\n * interaction at most. If some interplay with the legacy theme ever loops\n * (write -> re-render -> write), stop writing entirely for the rest of the\n * page view instead of fighting. Checkout enforcement still owns correctness. */\nlet writeStamps = [];\nlet tripped = false;\nfunction breakerOk() {\n  if (tripped) return false;\n  const now = Date.now();\n  writeStamps = writeStamps.filter((t) => now - t < 60000);\n  if (writeStamps.length >= 10) {\n    tripped = true;\n    try { console.warn('[aw-cart-sync] write breaker tripped; standing down for this page view'); } catch (_) {}\n    return false;\n  }\n  writeStamps.push(now);\n  return true;\n}\n\n/* One customer-facing money format (\"$104\" / \"$23.50\"): flush dollar sign, two\n * decimals only when there are cents, no USD suffix. Mirrors aw-money.liquid and\n * usd() in aw-order-widget.js; keep the three in sync.\n * (The Subtotal row USED to be deliberately not ours. It is now - see\n * paintSubtotal() below, pre-launch audit IMPORTANT-1.) */\nfunction usd(cents) {\n  const n = cents / 100;\n  const digits = n % 1 === 0 ? 0 : 2;\n  return '$' + n.toLocaleString('en-US', { minimumFractionDigits: digits, maximumFractionDigits: 2 });\n}\n\nfunction schedule(delay) {\n  clearTimeout(timer);\n  timer = setTimeout(reconcile, delay);\n}\n\n/* ---- Drawer SUBTOTAL (2026-08-07, pre-launch audit IMPORTANT-1) -------------\n *\n * THE DEFECT. The drawer rendered SUBTOTAL $313.00 on the DEFAULT 4-jug path\n * while /cart.js said 23600 and checkout charged $236.00. Also $425 vs $354.11\n * (6 jugs, family33) and $195 vs $166.62 (2-jug trial, starter22). It was exact\n * whenever no offer was attached ($348 vs 34800, 6 jugs no dispenser), which\n * pins the cause precisely: the figure is the pre-offer sum and the drawer never\n * subtracted the offer code's allocation.\n *\n * MECHANISM. The number is not computed here at all. templates/cart.ajax.liquid\n * publishes data-cart-subtotal on .cart__items and snippets/cart-drawer.liquid\n * server-renders {{ cart.total_price | money }}; legacy theme.js copies that into\n * [data-subtotal] on every re-render. Both are Liquid-side figures that do not\n * carry the cart-API discount allocation this theme attaches through syncOffer().\n * Editing the Liquid would not fix it - the value it reads is the wrong one, and\n * theme.js would overwrite the fix on the next render anyway.\n *\n * THE FIX. /cart.js total_price is the ONE figure verified equal to the checkout\n * charge, and it is already the number the wizard quotes. Take the drawer's\n * subtotal from there, and re-assert it whenever theme.js rewrites the row. The\n * savings line is filled from the same snapshot (original_total_price -\n * total_price, i.e. every discount Shopify itself counts, line-level and\n * cart-level), so a customer who sees a lower subtotal is told why instead of\n * being left to wonder.\n *\n * An over-quote is less dangerous than an under-quote, but it still contradicted\n * the card on the default path and was visible from every page in the store.\n *\n * Guarded against loops by idempotence, NOT by suppression: every write happens\n * only when the rendered text actually differs from the target, so the observer\n * callback our own write provokes finds nothing left to change and stops. (The\n * `painting` flag cannot do that job on its own - MutationObserver callbacks are\n * microtasks, so they run after the flag has already been cleared.) */\nlet lastCart = null;\nlet subObserver = null;\nlet painting = false;\n\nfunction paintSubtotal() {\n  const cart = lastCart;\n  if (!cart || typeof cart.total_price !== 'number') return;\n  painting = true;\n  try {\n    const target = usd(cart.total_price);\n    document.querySelectorAll('[data-subtotal]').forEach((el) => {\n      if (el.textContent.trim() !== target) el.textContent = target;\n    });\n    // Keep the attribute theme.js re-reads in step, so its next render starts\n    // from the right number rather than reinstating the pre-offer one.\n    document.querySelectorAll('[data-cart-subtotal]').forEach((el) => {\n      if (el.getAttribute('data-cart-subtotal') !== String(cart.total_price)) {\n        el.setAttribute('data-cart-subtotal', String(cart.total_price));\n      }\n    });\n    const saved = Number(cart.original_total_price || 0) - Number(cart.total_price);\n    document.querySelectorAll('[data-savings]').forEach((el) => {\n      if (saved > 0) {\n        const txt = \"You're saving \" + usd(saved);\n        if (el.textContent.trim() !== txt) el.textContent = txt;\n        el.classList.remove('hide');\n      } else {\n        if (el.textContent !== '') el.textContent = '';\n        el.classList.add('hide');\n      }\n    });\n  } catch (_) {\n    /* non-blocking; checkout enforcement still owns correctness */\n  } finally {\n    painting = false;\n  }\n}\n\n/* theme.js rebuilds the drawer footer (and the cart page) on every cart change\n * and writes its own figure back in. One observer over the drawer + cart page\n * re-asserts ours right after, on the same frame. */\nfunction watchSubtotal() {\n  if (subObserver) return;\n  const found = [document.getElementById('CartDrawer'), document.querySelector('.cart__page'), document.querySelector('form[action*=\"/cart\"]')].filter(Boolean);\n  // The drawer's own form matches the third selector, so drop any root already\n  // inside another - one subtree, one callback per mutation.\n  const roots = found.filter((r) => !found.some((o) => o !== r && o.contains(r)));\n  if (!roots.length) return;\n  subObserver = new MutationObserver(() => {\n    if (painting) return;\n    // lastCart is dropped the moment anything signals a cart change, so this can\n    // only ever re-assert a figure read AFTER the last change. A stale snapshot\n    // would be the one thing worse than the bug: a total below the charge.\n    paintSubtotal();\n  });\n  roots.forEach((r) => subObserver.observe(r, { childList: true, subtree: true, characterData: true }));\n}\n\nfunction noteCart(cart) {\n  if (!cart) return cart;\n  lastCart = cart;\n  paintSubtotal();\n  return cart;\n}\n\n/* Anything that signals the cart has moved drops the snapshot. Until the next\n * fresh read lands (reconcile, ~600ms later) the theme's own number stands - the\n * pre-existing over-quote at worst, never an under-quote from a stale figure. */\nfunction invalidateCart() { lastCart = null; }\n\ndocument.addEventListener('change', (e) => {\n  if (!e.target.classList || !e.target.classList.contains('water-delivery-cart-select-quantity')) return;\n  settleChecked = false;\n  invalidateCart();\n  schedule(1100); // let the theme's own update land first\n});\n\nconst observed = new WeakSet();\nfunction observeProducts() {\n  document.querySelectorAll('[data-products]').forEach((el) => {\n    if (observed.has(el)) return;\n    observed.add(el);\n    new MutationObserver(() => {\n      invalidateCart(); // the line list moved: our snapshot is now stale\n      if (busy) { dirtyWhileBusy = true; return; } // coalesce; drained in reconcile's finally\n      settleChecked = false;\n      schedule(600);\n    }).observe(el, { childList: true, subtree: true });\n  });\n}\n\nasync function reconcile() {\n  if (busy) return;\n  busy = true;\n  try {\n    const cart = await cartRead(true);\n    // A rate-limited read is not \"the cart is empty\": stand down and let the\n    // next mutation or the settle pass judge it. Writing off a null here is how\n    // a 429 would turn into a wrong deposit correction.\n    if (!cart) return;\n    updateRenewal(cart);\n    noteCart(cart); // drawer SUBTOTAL from /cart.js, the figure checkout charges\n\n    let waterQty = 0;\n    let hasDispenser = false;\n    const depositLines = [];\n    for (const item of cart.items) {\n      if (item.handle === WATER_HANDLE) waterQty += item.quantity;\n      else if (DEPOSIT_HANDLES.some((h) => item.handle.indexOf(h) === 0)) depositLines.push(item);\n      if (item.product_id === DISPENSER_PRODUCT_ID) hasDispenser = true;\n    }\n    syncOffer(cart, waterQty, hasDispenser);\n    const primary = depositLines.find((l) => l.variant_id === DEPOSIT_VARIANT_ID) || depositLines[0] || null;\n\n    /* Never correct deposits off a single snapshot. The legacy theme's own\n     * quantity sequence edits the DEPOSIT line first and the WATER line second\n     * (~1-3s apart), so a mid-sequence read (old water, new deposits) looks\n     * like a mismatch that is about to resolve itself - and a write here\n     * re-asserts the stale quantity (observed live 2026-07-17: downward edits\n     * ended water 4 / deposits 6). Rule: re-read after 1200ms and write only\n     * if the water quantity is UNCHANGED across both reads; if water moved,\n     * the theme is mid-sequence - stand down and let the settle pass judge\n     * the final state. */\n    let changed = false;\n    const mismatched = depositLines.some((l) => l.quantity !== (l === primary ? waterQty : 0));\n    if (mismatched) {\n      await new Promise((r) => setTimeout(r, 1200));\n      const confirm = await cartRead(true);\n      if (!confirm) return;\n      let cWaterQty = 0;\n      const cDepositLines = [];\n      for (const item of confirm.items) {\n        if (item.handle === WATER_HANDLE) cWaterQty += item.quantity;\n        else if (DEPOSIT_HANDLES.some((h) => item.handle.indexOf(h) === 0)) cDepositLines.push(item);\n      }\n      if (cWaterQty === waterQty) {\n        const cPrimary = cDepositLines.find((l) => l.variant_id === DEPOSIT_VARIANT_ID) || cDepositLines[0] || null;\n        for (const line of cDepositLines) {\n          const want = line === cPrimary ? cWaterQty : 0; // one deposit line, matched to jugs\n          if (line.quantity !== want && breakerOk()) {\n            await change(line.key, want);\n            changed = true;\n          }\n        }\n      } else {\n        settleChecked = false; // water moved between reads: theme mid-sequence\n      }\n    }\n    if (!primary && waterQty > 0) {\n      // \"Water present, deposits absent\" is also the transient middle of the\n      // theme's own remove-water sequence (it zeroes the deposit line first).\n      // Confirm with a second read before adding, so we never re-add deposits\n      // into a cart that is about to lose its water line.\n      await new Promise((r) => setTimeout(r, 1200));\n      const confirmCart = await cartRead(true);\n      if (!confirmCart) return;\n      let cWater = 0;\n      let cDeposit = 0;\n      for (const item of confirmCart.items) {\n        if (item.handle === WATER_HANDLE) cWater += item.quantity;\n        else if (DEPOSIT_HANDLES.some((h) => item.handle.indexOf(h) === 0)) cDeposit += item.quantity;\n      }\n      if (cWater > 0 && cDeposit === 0 && breakerOk()) {\n        const n = awNet();\n        const items = [{ id: DEPOSIT_VARIANT_ID, quantity: cWater }];\n        // Adds are not idempotent: go through addItems, which re-reads before it\n        // ever re-sends, so a lost response cannot double the deposit line.\n        if (n) await n.addItems(items, confirmCart);\n        else await cartPost('/cart/add.js', { items: items });\n        changed = true;\n      }\n    }\n\n    if (changed) {\n      // The theme rebuilds its own markup (and rebinds listeners); the rebuild\n      // mutates [data-products], which re-runs this reconcile as a final check.\n      cartAnnounce();\n      const fresh = await cartRead(true);\n      if (fresh) { updateRenewal(fresh); noteCart(fresh); }\n    } else if (!settleChecked) {\n      // The theme's own deposit adjustment can land AFTER the last drawer\n      // re-render (no DOM signal). One delayed verification pass per burst\n      // catches that late write; a second clean pass ends the burst.\n      settleChecked = true;\n      schedule(2500);\n    }\n  } catch (_) {\n    /* non-blocking; checkout enforcement still owns correctness */\n  } finally {\n    busy = false;\n    if (dirtyWhileBusy) {\n      dirtyWhileBusy = false;\n      settleChecked = false;\n      schedule(600); // re-renders that landed mid-pass get their own pass\n    }\n    gateButtons();\n  }\n}\n\n/* Checkout-button gate. The legacy theme ships TWO competing checkDepositAgree\n * implementations: a global one that only reads the DRAWER terms box\n * (#CartTermsDrawer) but fires on every .checkAgreeJS change, and a CartForm one\n * that only reads #DepositAgree but runs only on cart re-renders. Net effect on\n * the /cart page: checking the deposit box DISABLES the button (the global\n * handler consults the hidden drawer's unchecked terms box) until a quantity\n * change forces a re-render (observed live 2026-07-17, arm B day-1 smoke).\n * One rule instead, evaluated per surface and always LAST (microtask after the\n * legacy handlers): a checkout button is enabled iff every agreement checkbox\n * rendered in ITS OWN surface (drawer vs page form) is checked; no checkboxes\n * rendered means nothing to agree to. */\nfunction gateButtons() {\n  document.querySelectorAll('button.cart__checkout').forEach((btn) => {\n    const scope = btn.closest('#CartDrawer') || btn.closest('form') || document;\n    const boxes = Array.from(new Set(scope.querySelectorAll('input.cart__terms-checkbox, input.checkAgreeJS')));\n    const ok = boxes.every((b) => b.checked);\n    btn.disabled = !ok;\n    btn.classList.toggle('cart-checkout-button-disabled', !ok);\n  });\n}\n\ndocument.addEventListener('change', (e) => {\n  const t = e.target;\n  if (!t || !t.matches || !t.matches('input.cart__terms-checkbox, input.checkAgreeJS')) return;\n  setTimeout(gateButtons, 0); // after the legacy handlers, so this state wins\n});\n\nfunction change(key, quantity) {\n  // Absolute quantity, therefore idempotent: safe for the transport to retry.\n  return cartPost('/cart/change.js', { id: key, quantity });\n}\n\n/* Keep the auto-applied first-order discount matched to the cart when\n * quantities change after add to cart. offerCode() mirrors aw-order-widget.js\n * (codes starter22 / home77 / family33; jugs + dispenser count toward the\n * minimums, deposits and shelf never do) - keep the two in sync. Only runs\n * when the widget armed an offer (aw_offer_code in localStorage), so carts\n * built outside the offer flow are never touched. */\n/* The only discount codes this theme owns. Anything else attached to the cart\n * belongs to the customer (a typed promo) or a referral/ambassador link\n * (LeadDyno / UpPromote); the cart API's discount field REPLACES the whole code\n * set, so a blind write strips it and kills that order's attribution and the\n * partner's commission. Fix 2026-07-20. */\nconst THEME_CODES = ['starter22', 'home77', 'family33'];\n\nfunction offerCode(waterQty, hasDispenser) {\n  const eligible = waterQty + (hasDispenser ? 1 : 0);\n  if (waterQty < 1) return null;\n  if (waterQty <= 3) return eligible >= 3 ? 'starter22' : null;\n  /* 2026-08-18 (Brian): home77 extended from <=5 to <=6 so the chart-matched\n   * 6-jug default keeps the FREE DISPENSER as the go-to offer. Verified in\n   * admin: home77 is a Buy-X-Get-Y (buy 4+ water jugs -> dispenser 100% off,\n   * no upper limit) so a 6-jug cart validates; at exactly 6+dispenser it also\n   * pays the customer more than family33 ($77.00 vs $76.89). family33 (33%,\n   * admin minimum 7 items) now starts at 8 jugs, or 7+ eligible items.\n   * starter22 stays the sub-4-jug offer, unchanged. */\n  if (waterQty <= 6) return hasDispenser && eligible >= 5 ? 'home77' : null;\n  return eligible >= 7 ? 'family33' : null;\n}\n\nfunction syncOffer(cart, waterQty, hasDispenser) {\n  // Only touch carts the widget armed, same opt-in as B.\n  let armed = null;\n  let ineligible = null;\n  try {\n    armed = localStorage.getItem('aw_offer_code');\n    ineligible = localStorage.getItem('aw_offer_ineligible');\n  } catch (_) { return; }\n  if (!armed) return;\n  // Eligibility gate. All three theme codes are new-customers-only and\n  // one-use-per-customer, so a returning customer must never have one\n  // re-attached off a stale aw_offer_code. This file ships on the drawer and is\n  // handed no liquid data blob, so it cannot read customerEligible itself; the\n  // widget, which can, writes the durable aw_offer_ineligible marker when it\n  // suppresses the offer. Contract: marker present = ineligible (stand down\n  // completely: do not attach, do not subtract), marker absent = eligible.\n  // Fix 2026-07-21.\n  if (ineligible) return;\n  const want = offerCode(waterQty, hasDispenser) || 'none';\n  // C fork: the CART's attached codes are the truth (localStorage lied once:\n  // a failed write left it claiming the swap already happened, so every later\n  // pass stood down). Compare against cart.discount_codes and re-assert until\n  // the cart actually matches; update localStorage only after a 2xx.\n  const attached = (cart.discount_codes || []).map((d) => String(d.code || '').toLowerCase());\n  // Never clobber a code we did not put there (see THEME_CODES). If the cart\n  // carries a customer-entered or referral code, stand down completely: the\n  // customer's code wins and their attribution survives.\n  if (attached.some((c) => THEME_CODES.indexOf(c) === -1)) return;\n  const matches = want === 'none' ? attached.length === 0 : (attached.length === 1 && attached[0] === want);\n  if (matches) {\n    try { localStorage.setItem('aw_offer_code', want); } catch (_) {}\n    return;\n  }\n  // want === 'none' writes discount:'' on purpose: that is the ONLY path that\n  // DETACHES a theme code the cart has stopped qualifying for (drop 8 jugs to 4\n  // and family33 must come off, or it rides to checkout and pays out a discount\n  // the summary never quoted). Safe because the THEME_CODES check above already\n  // stood us down on any cart carrying a code we do not own. Revert 2026-07-21.\n  cartPost('/cart/update.js', { discount: want === 'none' ? '' : want }).then((r) => {\n    if (r && r.ok) { try { localStorage.setItem('aw_offer_code', want); } catch (_) {} }\n  }).catch(() => {});\n}\n\n/* Renewal line: always the published curve for CA/FL/TX water, on the 4 bottle\n * minimum (trial sizes 1 to 3 continue on the 4 bottle plan). Other regions bill\n * their flat variant price until their curves are published. */\nconst CURVE = { 4: 2600, 6: 2500, 8: 2400, 10: 2350, 12: 2300 };\nfunction curvePer(qty) {\n  if (CURVE[qty]) return CURVE[qty];\n  if (qty > 12) return 2300;\n  return 2600;\n}\n\n/* Route minimums (keep in sync with ROUTE_MIN_QTY in aw-guided-flow.js):\n * San Diego renews at 8 jugs, everywhere else at the standard 4\n * (Brian, 2026-08-18). The route rides the 'Delivery Cadence' cart\n * attribute the wizard writes on every add, e.g. 'once every 3 weeks\n * (San Diego)', so pre-existing carts resolve correctly too. */\nconst ROUTE_MIN_QTY = { 'San Diego': 8 };\nfunction cartMinQty(cart) {\n  const cad = (cart.attributes && cart.attributes['Delivery Cadence']) || '';\n  for (const k in ROUTE_MIN_QTY) if (cad.indexOf('(' + k + ')') > -1) return ROUTE_MIN_QTY[k];\n  return 4;\n}\n\nfunction updateRenewal(cart) {\n  let total = 0;\n  let planName = '';\n  const minQ = cartMinQty(cart);\n  for (const item of cart.items) {\n    if (!item.selling_plan_allocation) continue;\n    if (item.handle === WATER_HANDLE) {\n      const eff = Math.max(item.quantity, minQ);\n      const onCurve = (item.variant_title || '').indexOf('CA/FL/TX') > -1;\n      const per = onCurve ? curvePer(eff) : item.selling_plan_allocation.price;\n      total += per * eff;\n    } else {\n      total += item.selling_plan_allocation.price * item.quantity;\n    }\n    planName = item.selling_plan_allocation.selling_plan.name || planName;\n  }\n  const show = total > 0;\n  if (show) {\n    const text = usd(total) + ' ' + planName.replace(/^Deliver every/i, 'every').toLowerCase();\n    document.querySelectorAll('[data-aw-recurring]').forEach((el) => { el.textContent = text; });\n  }\n  document.querySelectorAll('[data-aw-recurring-wrap], [data-aw-recurring-note]').forEach((el) => { el.hidden = !show; });\n}\n\n/* Cart drawer open/close race (2026-08-06, Brian on mobile: \"if you click on it\n * once, it will appear and then disappear\").\n *\n * theme.Drawers.open() ends by calling bindEvents(), which attaches the\n * click-outside-to-close listener to WINDOW - synchronously, inside the very\n * event dispatch that opened the drawer. Per the DOM spec a listener added to an\n * ancestor the event has not reached yet still receives that event, so the\n * opening click carries straight on to window and closes the drawer it just\n * opened. open() only calls stopPropagation() when it is handed the event AND\n * the drawer was closed, so every open that does not carry its event is exposed.\n * Two such paths are live on this store: theme.CartDrawer opens on 'cart:open'\n * and on 'ajaxProduct:added' via this.drawer.open() with NO event, and two\n * installed apps dispatch 'cart:open' from inside a click - Appstle Bundles\n * (appstle-bundles-trigger-cart-refresh) and LB Upsell (lb-utils.js).\n * Traced live 2026-08-06, identical on E8 and on LIVE E10: one click produced\n * open -> drawerOpen -> that same click reaching window -> close.\n *\n * Fix: let the theme bind its closer exactly as it always did, then hold back\n * that ONE listener until the current event has finished dispatching. Nothing\n * else about bindEvents changes - the ESC handler and the mobile scroll lock\n * still run synchronously, and unbindEvents still removes the listener through\n * the theme's own window.namespaces bookkeeping (window.on stores one callback\n * per \"type.namespace\" key, so the re-arm has to reuse that same key).\n *\n * Deliberately NOT changed: tapping the cart icon while the drawer is open still\n * closes it. That is a different branch - open() returns early on this.isOpen,\n * so the click reaches the already-armed closer - and it is the toggle customers\n * expect. Verified as a separate trace before this fix was written.\n */\nfunction guardDrawerCloseRace() {\n  const P = window.theme && window.theme.Drawers && window.theme.Drawers.prototype;\n  if (!P) return false;\n  if (P.__awCloseRaceGuarded) return true;\n  const original = P.bindEvents;\n  if (typeof original !== 'function' || typeof window.on !== 'function' || typeof window.off !== 'function') return false;\n  P.__awCloseRaceGuarded = true;\n  P.bindEvents = function () {\n    const self = this;\n    const result = original.apply(this, arguments);\n    const key = 'click' + this.config.namespace; // e.g. \"click.drawer-cart\"\n    const closer = window.namespaces && window.namespaces[key];\n    if (!closer) return result; // theme changed shape: leave its behaviour alone\n    window.off(key); // detach the closer the theme just armed mid-dispatch\n    setTimeout(function () {\n      // A close that lands before this fires (isOpen false) must not re-arm it,\n      // or the listener would outlive its unbindEvents and leak onto window.\n      if (self.isOpen) window.on(key, closer);\n    }, 0);\n    return result;\n  };\n  return true;\n}\n\n/* Stale cart line key on a side-cart removal (2026-08-07, Brian on mobile: \"I\n * attempted to remove items from it in the mobile version, and it will show a\n * zero value, but the items are still reflecting\").\n *\n * MEASURED on E8 at 393x852, plan-only path (no accessory added). Shopify\n * RE-KEYS a cart line whenever its discount allocation changes, and\n * applyOffer() attaches home77 AFTER the drawer has already been rendered from\n * the pre-discount cart. Captured, one run:\n *\n *   /cart.js keys   32526818082867:36162ea8...   50650537263386:985f8a9c...\n *   drawer keys     32526818082867:3660afa3...   50650537263386:1caacf7e...\n *\n * Both dead. theme.js's changeItem() posts {id: <key>} - handleWaterDeliveryChange\n * forces cartLine to -1, so the line-index path is never taken - and the edge\n * answers:\n *\n *   POST /cart/change.js {\"quantity\":0,\"id\":\"50650537263386:1caacf7e...\"}\n *   -> 400 {\"status\":\"bad_request\",\"message\":\"no valid id or line parameter\"}\n *\n * theme.js only alerts on 422, so the 400 is swallowed. Worse, the theme's own\n * water sequence zeroes the DEPOSIT line FIRST and then calls\n * adjustRefundableJugQuantity(), which finds water 4 / deposits 0 and ADDS THE\n * DEPOSITS BACK. Net effect of one removal: the select flicks to \"0 jugs\", four\n * cart writes go out, and the cart ends byte-for-byte where it started - 9\n * items, $236.00. The items are still there. That is Brian's report exactly.\n *\n * Fix: repair the key instead of failing. On a 400/404 from a change that was\n * posted with a LINE KEY, re-read the cart, find the line by variant id and\n * re-issue with the key the cart actually holds. Only when EXACTLY ONE line\n * carries that variant: two lines of the same variant cannot be told apart from\n * a dead key, and guessing there would remove the wrong line and the wrong\n * money. Calls made with a bare variant id (the theme's own deposit\n * adjustments) are left alone - those never go stale.\n *\n * The sequencing is also fixed at source in aw-guided-flow.js, which now\n * announces a cart:build after the discount write so the drawer re-renders with\n * live keys. This guard is the belt to that braces, and it also covers re-keys\n * caused by the installed apps, which we do not control. */\nfunction guardStaleLineKey() {\n  const C = window.theme && window.theme.cart;\n  if (!C) return false;\n  if (C.__awStaleKeyGuarded) return true;\n  const original = C.changeItem;\n  if (typeof original !== 'function') return false;\n  C.__awStaleKeyGuarded = true;\n  C.changeItem = function (key, qty, cartLine) {\n    const self = this;\n    return Promise.resolve(original.call(this, key, qty, cartLine)).then(function (body) {\n      // Only a line key can go stale, and only a rejected change is worth retrying.\n      if (typeof key !== 'string' || key.indexOf(':') === -1) return body;\n      let parsed = null;\n      try { parsed = JSON.parse(body); } catch (_) { return body; }\n      if (!parsed || (parsed.status !== 400 && parsed.status !== 404)) return body;\n      const variantId = key.split(':')[0];\n      return cartRead(true).then(function (cart) {\n        if (!cart || !cart.items) return body;\n        const matches = cart.items.filter((i) => String(i.variant_id) === variantId);\n        if (matches.length !== 1) return body; // ambiguous: never guess which line\n        if (matches[0].key === key) return body; // key was fine; the failure is something else\n        return original.call(self, matches[0].key, qty, -1);\n      }, function () { return body; });\n    });\n  };\n  return true;\n}\n\n/* theme.js defines theme.Drawers and theme.cart, and the header section\n * instantiates the cart drawer on its own onLoad, so neither may exist when this\n * module runs. The patches only have to be in place before a human can open the\n * drawer, so a short poll is ample; give up quietly rather than spin. */\n(function armGuards(tries) {\n  const drawerArmed = guardDrawerCloseRace();\n  const keyArmed = guardStaleLineKey();\n  if (drawerArmed && keyArmed) return;\n  if (tries > 60) return; // ~6s\n  setTimeout(function () { armGuards(tries + 1); }, 100);\n})(0);\n\nfunction boot() {\n  observeProducts();\n  watchSubtotal();\n  gateButtons();\n  cartRead().then((c) => { if (c) { updateRenewal(c); noteCart(c); } }).catch(() => {});\n  // Heal any pre-existing deposit mismatch on load - a cart left wrong by an\n  // interrupted edit sequence must not survive a page view. Each page view is\n  // a fresh breaker budget; reconcile no-ops on clean carts.\n  settleChecked = false;\n  schedule(1500);\n}\nif (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);\nelse boot();\n"],
  "mappings": "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",
  "names": []
}
