{"version":3,"file":"build.sticky-atc.min.js","sources":["../src/js/entrypoints/sticky-atc.js"],"sourcesContent":["/**\n * sticky-atc.js — AB test sticky ATC controller\n *\n * Manages show/hide of #sticky-bar-desktop and #sticky-bar-mobile based on whether\n * #atc-anchor is visible in the viewport (accounting for the fixed header height).\n *\n * Globals consumed:\n *   window._abStickyVariants        — product variants JSON (thumbnail swap on color change)\n *   window._stickyIsMemberExclusive — true/string \"true\" if variant is member exclusive\n *   window._stickyIsLoggedIn        — true if customer session exists\n *   window._stickyLoginUrl          — /account/login?return_to=... for the current page\n *\n * Globals exposed:\n *   window.stickyBarCta — called by onclick on both sticky CTA buttons\n */\n\n// ── Utility ──────────────────────────────────────────────────────────────────\n\nfunction getHeaderHeight() {\n  const header = document.querySelector('#shopify-section-header')\n               || document.querySelector('header[role=\"banner\"]')\n               || document.querySelector('header');\n  return header ? header.offsetHeight : 80;\n}\n\nfunction getShopifyImageSrc(src, size) {\n  return src.replace(/(\\.[^.?]+)(\\?.*)?$/, `_${size}$1$2`);\n}\n\nfunction getPriceSection() {\n  return document.querySelector('[id^=\"price-\"][role=\"status\"]')\n      || document.querySelector('.price-wrapper[role=\"status\"]')\n      || document.querySelector('[role=\"status\"]:has(.text-promo, .compare-at-price)');\n}\n\n// ── DOM refs ──────────────────────────────────────────────────────────────────\n\nconst desktopBar = document.getElementById('sticky-bar-desktop');\nconst mobileBar = document.getElementById('sticky-bar-mobile');\nconst stickyColorElement = document.getElementById('sticky-bar-color');\nconst stickyThumbElement = document.getElementById('sticky-bar-thumbnail');\nconst stickySizeElement = document.getElementById('sticky-bar-size');\nconst stickySizeWrapper = document.getElementById('sticky-bar-size-wrap');\nconst stickyInseamElement = document.getElementById('sticky-bar-inseam');\nconst stickyInseamWrapper = document.getElementById('sticky-bar-inseam-wrap');\nconst stickyHandElement = document.getElementById('sticky-bar-hand');\nconst stickyHandWrapper = document.getElementById('sticky-bar-hand-wrap');\nconst stickyPriceElement = document.getElementById('sticky-bar-price');\nconst stickyCompareElement = document.getElementById('sticky-bar-compare-price');\nconst desktopCtaButton = document.getElementById('sticky-bar-cta-desktop');\nconst mobileCtaButton = document.getElementById('sticky-bar-cta-mobile');\nconst desktopCtaLabel = document.getElementById('sticky-bar-cta-desktop-label');\nconst mobileCtaLabel = document.getElementById('sticky-bar-cta-mobile-label');\n\n// ── Wrapper show/hide ─────────────────────────────────────────────────────────\n\nfunction showWrapper(wrapper) {\n  if (wrapper) {\n    wrapper.classList.remove('hidden');\n  }\n}\n\nfunction hideWrapper(wrapper) {\n  if (wrapper) {\n    wrapper.classList.add('hidden');\n  }\n}\n\n// ── Bar show/hide ─────────────────────────────────────────────────────────────\n// Tracks whether bars are logically \"showing\" (anchor scrolled out of view) so\n// the resize handler can re-evaluate which bar to display after a viewport change.\nlet barsVisible = false;\n\n// showBars() and hideBars() fully manage display, opacity, and transform via JS.\n// Tailwind's responsive classes (hidden lg:flex, lg:hidden) are not relied upon —\n// they only set the pre-JS initial state. The breakpoint is 1024 px so that\n// tablets (768–1023 px) get the mobile bottom bar and true desktops get the top bar.\nfunction showBars() {\n  barsVisible = true;\n  const isDesktop = window.innerWidth >= 1024;\n\n  if (desktopBar) {\n    if (isDesktop) {\n      desktopBar.style.display = 'flex';\n      desktopBar.style.opacity = '1';\n      desktopBar.style.pointerEvents = 'auto';\n      desktopBar.style.transform = 'translateY(0)';\n      desktopBar.setAttribute('aria-hidden', 'false');\n    } else {\n      desktopBar.style.display = 'none';\n      desktopBar.style.opacity = '0';\n      desktopBar.style.pointerEvents = 'none';\n      desktopBar.style.transform = 'translateY(-8px)';\n      desktopBar.setAttribute('aria-hidden', 'true');\n    }\n  }\n\n  if (mobileBar) {\n    if (isDesktop) {\n      mobileBar.style.display = 'none';\n      mobileBar.style.opacity = '0';\n      mobileBar.style.pointerEvents = 'none';\n      mobileBar.style.transform = 'translateY(8px)';\n      mobileBar.setAttribute('aria-hidden', 'true');\n    } else {\n      mobileBar.style.display = 'block';\n      mobileBar.style.opacity = '1';\n      mobileBar.style.pointerEvents = 'auto';\n      mobileBar.style.transform = 'translateY(0)';\n      mobileBar.setAttribute('aria-hidden', 'false');\n    }\n  }\n}\n\nfunction hideBars() {\n  barsVisible = false;\n\n  if (desktopBar) {\n    desktopBar.style.display = 'none';\n    desktopBar.style.opacity = '0';\n    desktopBar.style.pointerEvents = 'none';\n    desktopBar.style.transform = 'translateY(-8px)';\n    desktopBar.setAttribute('aria-hidden', 'true');\n  }\n\n  if (mobileBar) {\n    mobileBar.style.display = 'none';\n    mobileBar.style.opacity = '0';\n    mobileBar.style.pointerEvents = 'none';\n    mobileBar.style.transform = 'translateY(8px)';\n    mobileBar.setAttribute('aria-hidden', 'true');\n  }\n}\n\n// ── Price sync ────────────────────────────────────────────────────────────────\n\nfunction syncPriceFromDOM() {\n  const priceSection = getPriceSection();\n  if (!priceSection || !stickyPriceElement) {\n    return;\n  }\n\n  const saleElement = priceSection.querySelector('.text-promo');\n  const compareElement = priceSection.querySelector('.compare-at-price');\n  const regularElement = priceSection.querySelector('.text-price:not(.compare-at-price):not(.text-promo)');\n  const isSale = Boolean(saleElement);\n\n  if (isSale) {\n    stickyPriceElement.textContent = saleElement.textContent.trim();\n    stickyPriceElement.style.color = '#9b3b3b';\n    stickyPriceElement.classList.add('font-semibold');\n  } else {\n    stickyPriceElement.textContent = regularElement ? regularElement.textContent.trim() : '';\n    stickyPriceElement.style.color = '';\n    stickyPriceElement.classList.remove('font-semibold');\n  }\n\n  if (stickyCompareElement) {\n    if (isSale && compareElement) {\n      stickyCompareElement.textContent = compareElement.textContent.trim();\n      stickyCompareElement.classList.remove('hidden');\n      stickyCompareElement.style.display = '';\n    } else {\n      stickyCompareElement.textContent = '';\n      stickyCompareElement.classList.add('hidden');\n      stickyCompareElement.style.display = 'none';\n    }\n  }\n}\n\nfunction initPriceSync() {\n  syncPriceFromDOM();\n  const priceSection = getPriceSection();\n  if (priceSection) {\n    const priceMutationObserver = new MutationObserver(syncPriceFromDOM);\n    priceMutationObserver.observe(priceSection, { childList: true, subtree: true });\n  }\n}\n\n// ── Member exclusive helper ───────────────────────────────────────────────────\n\nfunction isMemberExclusiveLoggedOut() {\n  const me = window._stickyIsMemberExclusive;\n  return (me === true || me === 'true') && !window._stickyIsLoggedIn;\n}\n\n// ── Explicit size-selection gate ──────────────────────────────────────────────\n// Shopify auto-pre-selects the first available size on page load, and ?variant=\n// URL params also arrive pre-selected. Both should still show \"Select a Size\"\n// in the sticky bar until the user consciously taps a size button.\n// Set to true only on an explicit user interaction (change / variant-selected events).\n// Reset to false on size-reset (e.g. color swatch change clears size).\nlet userExplicitlySelectedSize = false;\n\n// ── IntersectionObserver ──────────────────────────────────────────────────────\n\nlet anchorElement = document.getElementById('atc-anchor');\nlet stickyObserver;\nlet observerStarted = false;\n\nfunction createObserver(target) {\n  if (stickyObserver) {\n    stickyObserver.disconnect();\n  }\n\n  const headerHeight = getHeaderHeight();\n  stickyObserver = new IntersectionObserver((entries) => {\n    const entry = entries[0];\n    const rect = entry.boundingClientRect;\n    if (rect.width === 0 && rect.height === 0) {\n      return;\n    }\n\n    if (entry.isIntersecting) {\n      hideBars();\n    } else {\n      showBars();\n    }\n  }, { threshold: 0, rootMargin: `-${headerHeight}px 0px 0px 0px` });\n  stickyObserver.observe(target);\n}\n\nfunction snapAndObserve(target) {\n  const rect = target.getBoundingClientRect();\n  if (rect.width === 0 && rect.height === 0) {\n    hideBars();\n  } else {\n    for (const element of [desktopBar, mobileBar]) {\n      if (element) {\n        element.style.transition = 'none';\n      }\n    }\n\n    const headerHeight = getHeaderHeight();\n    const isOutOfView = rect.bottom <= headerHeight || rect.top >= window.innerHeight;\n    if (isOutOfView) {\n      showBars();\n    } else {\n      hideBars();\n    }\n\n    requestAnimationFrame(() => {\n      for (const element of [desktopBar, mobileBar]) {\n        if (element) {\n          element.style.transition = '';\n        }\n      }\n    });\n  }\n\n  createObserver(target);\n}\n\nfunction startObserver() {\n  if (observerStarted || !anchorElement) {\n    return;\n  }\n\n  observerStarted = true;\n  snapAndObserve(anchorElement);\n}\n\n// ── Sold-out sync ─────────────────────────────────────────────────────────────\n\nfunction getSubmitButton() {\n  const anchorNode = document.getElementById('atc-anchor');\n  const sectionId = anchorNode ? anchorNode.dataset.sectionId : null;\n  return sectionId\n    ? document.getElementById(`ProductSubmitButton-${sectionId}`)\n    : document.querySelector('[id^=\"ProductSubmitButton-\"]');\n}\n\nfunction isSoldOut() {\n  const submitButton = getSubmitButton();\n  if (!submitButton || !submitButton.disabled) {\n    return false;\n  }\n\n  // The main button is disabled for two reasons:\n  //   1. Selection incomplete (needs size / inseam / hand) — shows \"Add to cart\" (grayed)\n  //   2. All options selected but variant unavailable  — shows \"Sold out\"\n  // Replicating the Alpine component's local \"isVariantAvailable\" logic is fragile,\n  // so instead read the text of whichever x-show span Alpine is currently showing.\n  // Alpine sets display:none inline on hidden spans, so the visible one has no inline display.\n  const xShowSpans = submitButton.querySelectorAll('span[x-show]');\n  for (const xShowSpan of xShowSpans) {\n    if (xShowSpan.style.display !== 'none') {\n      return xShowSpan.textContent.trim().toLowerCase().includes('sold out');\n    }\n  }\n\n  return false;\n}\n\n// Shopify appends ?key=<line_item_key> when the user arrives via cart \"Edit Details\".\n// In that flow the main product form button says \"Update\" — sticky bar must match.\nfunction isCartEditMode() {\n  return new URLSearchParams(window.location.search).has('key');\n}\n\nfunction getCtaLabel(soldOut) {\n  if (soldOut) {\n    return 'Sold out';\n  }\n\n  if (isCartEditMode()) {\n    return 'Update';\n  }\n\n  return 'Add to Cart';\n}\n\n// Extracted to keep syncCtaState under the ESLint complexity limit.\n// Returns true when the user still needs to pick a size before ATC is valid.\nfunction computeNeedsSize(soldOut) {\n  if (soldOut) {\n    return false;\n  }\n\n  const hasSizeOption = Boolean(\n    document.querySelector(\n      'fieldset[data-is-size=\"true\"], fieldset[data-has-inseam=\"true\"], fieldset[data-has-hand=\"true\"]',\n    ),\n  );\n  if (!hasSizeOption) {\n    return false;\n  }\n\n  const state = window.Alpine && window.Alpine.store('state');\n  const isMobile = window.innerWidth < 1024;\n  return (isMobile && !userExplicitlySelectedSize)\n    || !state\n    || state.isFirstLoad\n    || !state.sizeSelected\n    || (state.hasHandOption && !state.handSelected)\n    || (state.hasInseamOption && !state.inseamSelected);\n}\n\nfunction syncCtaState() {\n  // Member exclusive + logged out: show \"Sign in to buy\", skip all size/sold-out gating\n  if (isMemberExclusiveLoggedOut()) {\n    for (const label of [desktopCtaLabel, mobileCtaLabel]) {\n      if (label) {\n        label.textContent = 'Sign in to buy';\n      }\n    }\n\n    for (const btn of [desktopCtaButton, mobileCtaButton]) {\n      if (btn) {\n        btn.disabled = false;\n      }\n    }\n\n    return;\n  }\n\n  const soldOut = isSoldOut();\n  const _needsSize = computeNeedsSize(soldOut);\n\n  // Detect external cart-level blocks (gift card in cart, quantity rules, etc.).\n  // isGiftCardBlocked() checks whether ProductSubmitButton-{id} has been replaced in the\n  // DOM by a static disabled button — the signal buy-buttons.liquid uses for cart blocks.\n  // We apply a visual-only class (not disabled attribute) so the button stays clickable\n  // and stickyBarCta() can scroll the user to the warning message on click.\n  const cartBlocked = !soldOut && !_needsSize && isGiftCardBlocked();\n\n  const labelText = getCtaLabel(soldOut);\n\n  for (const labelElement of [desktopCtaLabel, mobileCtaLabel]) {\n    if (labelElement) {\n      labelElement.textContent = labelText;\n    }\n  }\n\n  // Never truly disable — keep the button clickable so stickyBarCta() can scroll the user\n  // to the appropriate section (variant picker for sold-out, warning for cart-blocked).\n  // Visual gray comes from .sticky-cart-blocked, which keeps pointer-events active.\n  const isBlocked = soldOut || cartBlocked;\n  for (const ctaButton of [desktopCtaButton, mobileCtaButton]) {\n    if (ctaButton) {\n      ctaButton.disabled = false;\n      ctaButton.classList.toggle('sticky-cart-blocked', isBlocked);\n    }\n  }\n}\n\nfunction watchSubmitButton() {\n  const submitButton = getSubmitButton();\n  if (!submitButton) {\n    return;\n  }\n\n  const submitButtonObserver = new MutationObserver(syncCtaState);\n  submitButtonObserver.observe(submitButton, { attributes: true, attributeFilter: ['disabled'] });\n}\n\n// When a gift card is in the cart, buy-buttons.liquid's Alpine component removes\n// ProductSubmitButton-{id} from the DOM and renders a static <button disabled> in its place.\n// getSubmitButton() returns null in that state. Detect by checking for the ID-less\n// disabled button inside #atc-anchor.\nfunction isGiftCardBlocked() {\n  if (getSubmitButton()) {\n    return false;\n  }\n\n  const anchorNode = document.getElementById('atc-anchor');\n  return Boolean(anchorNode && anchorNode.querySelector('button[disabled]'));\n}\n\n// Observe the [data-ajax-cart-section] container for childList changes. LiquidAjaxCart\n// re-renders it on every cart update, which causes Alpine's x-if directives to swap the\n// buttons in/out. Without this observer syncCtaState() would not fire after the swap\n// because the submitButtonObserver is watching a now-detached element.\nfunction watchCartSection() {\n  const anchorNode = document.getElementById('atc-anchor');\n  if (!anchorNode) {\n    return;\n  }\n\n  const cartSection = anchorNode.querySelector('[data-ajax-cart-section]');\n  if (!cartSection) {\n    return;\n  }\n\n  const cartSectionObserver = new MutationObserver(syncCtaState);\n  cartSectionObserver.observe(cartSection, { childList: true, subtree: true });\n}\n\n// ── Cart / CTA ────────────────────────────────────────────────────────────────\n\n// ── Inline size hint ──────────────────────────────────────────────────────────\n// Appears centered on the top border of the highlighted size fieldset — same\n// color as the pulse outline (#9b3b3b). Absolutely positioned inside the\n// fieldset so it takes up zero layout space and leaves no gap when hidden.\n\nlet sizeHintTimer = null;\n\nfunction showSizeHint(targetFieldset) {\n  if (!targetFieldset) {\n    return;\n  }\n\n  // Fieldset must be a positioning context for the absolute hint\n  if (window.getComputedStyle(targetFieldset).position === 'static') {\n    targetFieldset.style.position = 'relative';\n  }\n\n  let hint = document.getElementById('size-hint-inline');\n\n  if (!hint) {\n    hint = document.createElement('span');\n    hint.id = 'size-hint-inline';\n    hint.setAttribute('role', 'status');\n    hint.setAttribute('aria-live', 'polite');\n    hint.textContent = 'Select / confirm a size to continue';\n    hint.style.cssText = [\n      'position: absolute',\n      'top: -1.4em',\n      'left: 50%',\n      'transform: translateX(-50%)',\n      'white-space: nowrap',\n      'background: #fff',\n      'padding: 0 6px',\n      'color: #9b3b3b',\n      'font-size: 0.7rem',\n      'font-weight: 600',\n      'letter-spacing: 0.01em',\n      'line-height: 1',\n      'opacity: 0',\n      'transition: opacity 0.8s ease',\n      'pointer-events: none',\n      'z-index: 2',\n    ].join(';');\n    targetFieldset.appendChild(hint);\n  } else if (hint.parentNode !== targetFieldset) {\n    // Re-attach when fieldset is replaced after AJAX re-render (e.g. color change)\n    if (window.getComputedStyle(targetFieldset).position === 'static') {\n      targetFieldset.style.position = 'relative';\n    }\n\n    targetFieldset.appendChild(hint);\n  }\n\n  hint.style.opacity = '1';\n\n  clearTimeout(sizeHintTimer);\n  sizeHintTimer = setTimeout(() => {\n    hint.style.opacity = '0';\n  }, 7000);\n}\n\n// Scroll to the first product option (typically color swatches) so the user can\n// pick a different variant when the current selection is sold out.\nfunction scrollToVariants() {\n  const target = document.querySelector('main fieldset')\n    || document.getElementById('atc-anchor');\n  if (target) {\n    target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n  }\n}\n\nfunction scrollToSize() {\n  const state = window.Alpine && window.Alpine.store('state');\n  const handFieldset = document.querySelector('fieldset[data-has-hand=\"true\"]');\n  const sizeFieldset = document.querySelector('fieldset[data-is-size=\"true\"]');\n  const inseamFieldset = document.querySelector('fieldset[data-has-inseam=\"true\"]');\n\n  if (handFieldset && state && state.hasHandOption && !state.handSelected) {\n    showSizeHint(handFieldset);\n    handFieldset.scrollIntoView({ behavior: 'smooth', block: 'center' });\n    handFieldset.classList.add('size-highlight');\n    setTimeout(() => {\n      handFieldset.classList.remove('size-highlight');\n    }, 7000);\n    return;\n  }\n\n  const targetFieldset = sizeFieldset || inseamFieldset;\n  if (!targetFieldset) {\n    return;\n  }\n\n  showSizeHint(targetFieldset);\n  targetFieldset.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n  for (const fieldset of [sizeFieldset, inseamFieldset]) {\n    if (fieldset) {\n      fieldset.classList.add('size-highlight');\n      setTimeout(() => {\n        fieldset.classList.remove('size-highlight');\n      }, 7000);\n    }\n  }\n}\n\n// ── Sticky loading state ──────────────────────────────────────────────────────\n// Mirrors the main ATC button's gray/disabled appearance while the cart AJAX\n// request is in flight, preventing double-taps and clarifying order status.\n\nlet stickyLoadingTimer = null;\n\nfunction setStickyLoading(loading) {\n  for (const btn of [mobileCtaButton, desktopCtaButton]) {\n    if (!btn) {\n      continue;\n    }\n\n    if (loading) {\n      btn.disabled = true;\n      btn.style.opacity = '0.5';\n      btn.style.cursor = 'not-allowed';\n      btn.style.backgroundColor = '#ddd';\n      btn.style.color = '#555';\n      btn.style.borderColor = '#ddd';\n    } else {\n      btn.disabled = false;\n      btn.style.opacity = '';\n      btn.style.cursor = '';\n      btn.style.backgroundColor = '';\n      btn.style.color = '';\n      btn.style.borderColor = '';\n    }\n  }\n}\n\n// Cart edit mode — mirrors update-cart.liquid's submitForm() but reads the correct\n// variant from the form's hidden input (updated by Shopify's variant picker) rather\n// than from Alpine's stale x-data initializer.\nasync function submitCartUpdate() {\n  const key = new URLSearchParams(window.location.search).get('key');\n  if (!key || !window.liquidAjaxCart) {\n    return;\n  }\n\n  setStickyLoading(true);\n\n  try {\n    const variantInput = document.querySelector(\n      'product-form input.product-variant-id, product-form input[name=\"id\"]',\n    );\n    const quantityInput = document.querySelector('product-form input[name=\"quantity\"]');\n    const newVariantId = variantInput ? parseInt(variantInput.value, 10) : null;\n    const quantity = quantityInput ? parseInt(quantityInput.value, 10) || 1 : 1;\n\n    if (!newVariantId) {\n      setStickyLoading(false);\n      return;\n    }\n\n    const cart = await window.liquidAjaxCart.cart;\n    const lineItem = cart.items.find((item) => item.key === key);\n\n    if (!lineItem) {\n      setStickyLoading(false);\n      return;\n    }\n\n    const redirectToCart = () => {\n      window.location.href = '/cart';\n    };\n\n    if (newVariantId === lineItem.id) {\n      // Same variant — quantity-only change\n      window.liquidAjaxCart.change({ id: lineItem.key, quantity }, { lastCallback: redirectToCart });\n    } else {\n      // Variant changed: add new line item then zero-out the old one\n      if (window.Rebuy) {\n        window.Rebuy.SmartCart.skip_open = true;\n      }\n\n      await window.liquidAjaxCart.add({ items: [{ id: newVariantId, quantity }] });\n      window.liquidAjaxCart.change({ id: lineItem.key, quantity: 0 }, { lastCallback: redirectToCart });\n    }\n  } catch (_) {\n    setStickyLoading(false);\n  }\n}\n\nfunction submitCart() {\n  if (isCartEditMode()) {\n    submitCartUpdate();\n    return;\n  }\n\n  const anchorNode = document.getElementById('atc-anchor');\n  const sectionId = anchorNode ? anchorNode.dataset.sectionId : null;\n  const mainButton = sectionId\n    ? document.getElementById(`ProductSubmitButton-${sectionId}`)\n    : document.querySelector('[id^=\"ProductSubmitButton-\"]');\n\n  if (!mainButton) {\n    return;\n  }\n\n  // Lock sticky buttons immediately on tap\n  setStickyLoading(true);\n\n  // Watch the main button's disabled attribute — when Alpine re-enables it the\n  // cart request has completed (success or error)\n  const mainButtonObserver = new MutationObserver(() => {\n    if (!mainButton.disabled) {\n      setStickyLoading(false);\n      mainButtonObserver.disconnect();\n      clearTimeout(stickyLoadingTimer);\n    }\n  });\n  mainButtonObserver.observe(mainButton, { attributes: true, attributeFilter: ['disabled'] });\n\n  // Also listen for common AJAX cart completion events\n  const cartDoneHandler = () => {\n    setStickyLoading(false);\n    mainButtonObserver.disconnect();\n    clearTimeout(stickyLoadingTimer);\n  };\n\n  for (const eventName of ['cart:updated', 'cart:error', 'ajax-cart:request-done', 'theme:cart:added']) {\n    document.addEventListener(eventName, cartDoneHandler, { once: true });\n  }\n\n  // Safety fallback — re-enable after 5s regardless, so the button never stays locked\n  clearTimeout(stickyLoadingTimer);\n  stickyLoadingTimer = setTimeout(() => {\n    setStickyLoading(false);\n    mainButtonObserver.disconnect();\n  }, 5000);\n\n  mainButton.click();\n}\n\nfunction stickyBarCta() {\n  // Member exclusive + logged out: redirect to login instead of attempting cart add\n  if (isMemberExclusiveLoggedOut()) {\n    window.location.href = window._stickyLoginUrl || '/account/login';\n    return;\n  }\n\n  // Sold out — scroll to variant picker so user can try a different color or size\n  if (isSoldOut()) {\n    scrollToVariants();\n    return;\n  }\n\n  const state = window.Alpine && window.Alpine.store('state');\n  const hasSizeOption = Boolean(\n    document.querySelector(\n      'fieldset[data-is-size=\"true\"], fieldset[data-has-inseam=\"true\"], fieldset[data-has-hand=\"true\"]',\n    ),\n  );\n  // No-size products skip all size checks — go straight to ATC.\n  // Same mobile-only gate as syncCtaState() — desktop respects pre-selected size.\n  const isMobile = window.innerWidth < 1024;\n  const needsSize = hasSizeOption && (\n    (isMobile && !userExplicitlySelectedSize)\n    || !state || state.isFirstLoad || !state.sizeSelected\n    || (state.hasHandOption && !state.handSelected)\n    || (state.hasInseamOption && !state.inseamSelected)\n  );\n  if (needsSize) {\n    scrollToSize();\n    return;\n  }\n\n  // Gift card in cart — ProductSubmitButton-{id} has been replaced in the DOM by a static\n  // disabled button. Scroll the user to the warning message rather than failing silently.\n  if (isGiftCardBlocked()) {\n    const anchor = document.getElementById('atc-anchor');\n    if (anchor) {\n      anchor.scrollIntoView({ behavior: 'smooth', block: 'center' });\n    }\n\n    return;\n  }\n\n  submitCart();\n}\n\nwindow.stickyBarCta = stickyBarCta;\n\n// ── Safe-area fill height fix ─────────────────────────────────────────────────\n// env(safe-area-inset-bottom) resolves to 0 on the first iOS Safari render pass\n// and only gets the correct value (≈34 px on notched iPhones) after a browser\n// repaint. That's why the fill is intermittent: at DOMContentLoaded both the\n// fill div height and the mobile bar padding-bottom are 0, and they only correct\n// themselves after some browser event (e.g. adding to cart triggers a repaint).\n//\n// Fix: use ResizeObserver on the mobile bar. When env() finally resolves, the\n// bar's computed padding-bottom changes, the observer fires immediately, and we\n// copy that value to the fill div. This runs exactly once on each env() update —\n// no polling, no arbitrary timeouts.\n\nfunction syncSafeAreaFill() {\n  const fill = document.getElementById('sticky-safe-area-fill');\n  const bar = document.getElementById('sticky-bar-mobile');\n  if (!fill || !bar) {\n    return;\n  }\n\n  function applyHeight() {\n    const h = parseFloat(window.getComputedStyle(bar).paddingBottom) || 0;\n    fill.style.height = `${h}px`;\n  }\n\n  applyHeight();\n\n  if (window.ResizeObserver) {\n    new ResizeObserver(applyHeight).observe(bar);\n  }\n}\n\n// ── Desktop bar positioning ───────────────────────────────────────────────────\n\nfunction updateDesktopBarTop() {\n  if (desktopBar) {\n    desktopBar.style.top = `${getHeaderHeight()}px`;\n  }\n}\n\nupdateDesktopBarTop();\nwindow.addEventListener('resize', () => {\n  updateDesktopBarTop();\n  // Re-evaluate which bar to show/hide when the viewport crosses the breakpoint.\n  // showBars() reads window.innerWidth so it automatically picks the right bar.\n  if (barsVisible) {\n    showBars();\n  }\n});\n\n// ── Pre-selected thumbnail sync ───────────────────────────────────────────────\n// product-sticky-atc.liquid always renders product.featured_image (the product\n// default), not the selected variant's image. When the user lands via a direct\n// variant URL (?variant=X) or from a PLP that pre-selects a color, the thumbnail\n// stays wrong until the user clicks a swatch. Fix: resolve the active variant on\n// load and set the thumbnail without waiting for a change event.\n\nfunction syncThumbnailFromDOM() {\n  if (!stickyThumbElement || !window._abStickyVariants) {\n    return;\n  }\n\n  let matchedVariant = null;\n\n  // 1. ?variant= param is the most authoritative signal\n  const variantParam = new URLSearchParams(window.location.search).get('variant');\n  if (variantParam) {\n    const variantId = parseInt(variantParam, 10);\n    matchedVariant = window._abStickyVariants.find((v) => v.id === variantId) || null;\n  }\n\n  // 2. Fall back to the currently-checked color radio (covers PLP swatch links\n  //    that may pass color via a different mechanism than ?variant=)\n  if (!matchedVariant) {\n    const checkedColor = document.querySelector(\n      'input[type=\"radio\"]:checked[name*=\"color\" i], input[type=\"radio\"]:checked[name*=\"Color\"]',\n    );\n    if (checkedColor) {\n      const colorValue = checkedColor.value;\n      matchedVariant = window._abStickyVariants.find(\n        (v) => v.option1 === colorValue || v.option2 === colorValue || v.option3 === colorValue,\n      ) || null;\n    }\n  }\n\n  if (matchedVariant && matchedVariant.featured_image && matchedVariant.featured_image.src) {\n    stickyThumbElement.src = getShopifyImageSrc(matchedVariant.featured_image.src, '160x160');\n  }\n}\n\n// ── Pre-selected variant sync ─────────────────────────────────────────────────\n// When a user lands with ?variant=xxx already in the URL (e.g. from PLP/carousel),\n// the radio button is pre-checked by server-rendered HTML but no JS change event\n// fires. Read the checked state from the DOM and populate sticky labels on load.\n\nfunction syncSelectionFromDOM() {\n  // Guard: Shopify always pre-checks the first available variant's radio in the\n  // server-rendered HTML even when the user hasn't made a selection.  Only\n  // populate the sticky labels if Alpine's store confirms a real selection exists\n  // (which it does when a ?variant= param caused a specific variant to load).\n  const state = window.Alpine && window.Alpine.store('state');\n  if (!state || !state.sizeSelected) {\n    return;\n  }\n\n  const checkedInputs = document.querySelectorAll('input[type=\"radio\"]:checked');\n  for (const input of checkedInputs) {\n    if (!input.name || !input.value) {\n      continue;\n    }\n\n    const inputName = input.name.toLowerCase();\n    const inputValue = input.value;\n\n    if (inputName === 'inseam' || inputName.includes('inseam')) {\n      if (stickyInseamElement) {\n        stickyInseamElement.textContent = inputValue;\n      }\n\n      showWrapper(stickyInseamWrapper);\n    }\n\n    if (inputName === 'size' || inputName.includes('size')) {\n      if (stickySizeElement) {\n        stickySizeElement.textContent = inputValue;\n      }\n\n      showWrapper(stickySizeWrapper);\n    }\n\n    if (inputName === 'hand' || inputName.includes('hand')) {\n      if (stickyHandElement) {\n        stickyHandElement.textContent = inputValue;\n      }\n\n      showWrapper(stickyHandWrapper);\n    }\n  }\n}\n\n// ── Start observer on DOM ready ───────────────────────────────────────────────\n// Use DOMContentLoaded (not 'load') so the sticky bar appears as soon as the\n// HTML is parsed — before images / videos / 3rd-party scripts finish loading.\n// Alpine also initialises on DOMContentLoaded, so the store is available here.\n\nfunction initAll() {\n  startObserver();\n  initPriceSync();\n  syncCtaState();\n  watchSubmitButton();\n  watchCartSection();\n  syncSafeAreaFill();\n  // One rAF so Alpine finishes any microtask updates before we read :checked state\n  requestAnimationFrame(syncSelectionFromDOM);\n  requestAnimationFrame(syncThumbnailFromDOM);\n  // alpine:initialized fires after Alpine has walked every x-init and populated\n  // its stores — this catches the race where our module runs before Alpine\n  // finishes setting sizeSelected = true for a ?variant= pre-selection.\n  document.addEventListener('alpine:initialized', () => {\n    requestAnimationFrame(syncSelectionFromDOM);\n    requestAnimationFrame(syncThumbnailFromDOM);\n  }, { once: true });\n}\n\nif (document.readyState === 'loading') {\n  // HTML not yet parsed — wait for DOMContentLoaded\n  document.addEventListener('DOMContentLoaded', initAll);\n} else {\n  // 'interactive' or 'complete' — DOM already parsed, run immediately\n  initAll();\n}\n\n// ── Layout-stabilisation re-snap ──────────────────────────────────────────────\n// DOMContentLoaded runs before images load, so page height (and therefore the\n// ATC button's position) can shift significantly on image-heavy pages — especially\n// on mobile where the product carousel stacks vertically above the ATC.\n// Re-run snapAndObserve after 'load' so the sticky bar reflects the final layout.\n\nif (document.readyState !== 'complete') {\n  window.addEventListener('load', () => {\n    if (anchorElement) {\n      snapAndObserve(anchorElement);\n    }\n\n    syncCtaState();\n    // Belt-and-suspenders: by 'load' Alpine is always fully initialised,\n    // so sizeSelected is correct for any ?variant= pre-selection.\n    syncSelectionFromDOM();\n    syncThumbnailFromDOM();\n  });\n}\n\n// ── Re-attach observer after AJAX section re-renders ─────────────────────────\n// Color swatch clicks replace #atc-anchor with a new DOM node — re-observe it.\n\nconst mutationContainer = document.querySelector('main') || document.body;\nconst anchorMutationObserver = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    for (const node of mutation.addedNodes) {\n      if (node.nodeType !== 1) {\n        continue;\n      }\n\n      const newAnchor = node.id === 'atc-anchor'\n        ? node\n        : node.querySelector && node.querySelector('#atc-anchor');\n      if (newAnchor && newAnchor !== anchorElement) {\n        anchorElement = newAnchor;\n        snapAndObserve(anchorElement);\n        initPriceSync();\n        syncCtaState();\n        watchSubmitButton();\n        requestAnimationFrame(syncSelectionFromDOM);\n        requestAnimationFrame(syncThumbnailFromDOM);\n        return;\n      }\n    }\n  }\n});\nanchorMutationObserver.observe(mutationContainer, { childList: true, subtree: true });\n\n// ── Event listeners ───────────────────────────────────────────────────────────\n\ndocument.addEventListener('change', (event) => {\n  if (!event.target || !event.target.name || !event.target.value) {\n    return;\n  }\n\n  const inputName = event.target.name.toLowerCase();\n  const inputValue = event.target.value;\n\n  if (inputName.includes('color')) {\n    if (stickyColorElement) {\n      stickyColorElement.textContent = inputValue;\n    }\n\n    if (stickyThumbElement && window._abStickyVariants) {\n      const matchedVariant = window._abStickyVariants.find(\n        (variant) => variant.option1 === inputValue || variant.option2 === inputValue || variant.option3 === inputValue,\n      );\n      if (matchedVariant && matchedVariant.featured_image && matchedVariant.featured_image.src) {\n        stickyThumbElement.src = getShopifyImageSrc(matchedVariant.featured_image.src, '160x160');\n      }\n    }\n\n    return;\n  }\n\n  if (inputName === 'inseam' || inputName.includes('inseam')) {\n    if (stickyInseamElement) {\n      stickyInseamElement.textContent = inputValue;\n    }\n\n    showWrapper(stickyInseamWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  if (inputName === 'size' || inputName.includes('size')) {\n    if (stickySizeElement) {\n      stickySizeElement.textContent = inputValue;\n    }\n\n    showWrapper(stickySizeWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  if (inputName === 'hand' || inputName.includes('hand')) {\n    if (stickyHandElement) {\n      stickyHandElement.textContent = inputValue;\n    }\n\n    showWrapper(stickyHandWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  requestAnimationFrame(syncPriceFromDOM);\n  requestAnimationFrame(syncCtaState);\n});\n\ndocument.addEventListener('variant-selected', (event) => {\n  const detail = event && event.detail ? event.detail : {};\n\n  if (detail.selectedSize) {\n    if (stickySizeElement) {\n      stickySizeElement.textContent = detail.selectedSize;\n    }\n\n    showWrapper(stickySizeWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  if (detail.selectedInseam && detail.selectedInseam !== 'true' && detail.selectedInseam !== 'false') {\n    if (stickyInseamElement) {\n      stickyInseamElement.textContent = detail.selectedInseam;\n    }\n\n    showWrapper(stickyInseamWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  if (detail.selectedHand) {\n    if (stickyHandElement) {\n      stickyHandElement.textContent = detail.selectedHand;\n    }\n\n    showWrapper(stickyHandWrapper);\n    userExplicitlySelectedSize = true;\n  }\n\n  requestAnimationFrame(syncPriceFromDOM);\n  requestAnimationFrame(syncCtaState);\n});\n\ndocument.addEventListener('size-reset', () => {\n  userExplicitlySelectedSize = false;\n  hideWrapper(stickySizeWrapper);\n  hideWrapper(stickyInseamWrapper);\n  hideWrapper(stickyHandWrapper);\n  requestAnimationFrame(syncCtaState);\n});\n"],"names":["getHeaderHeight","header","document","querySelector","offsetHeight","getShopifyImageSrc","src","size","replace","getPriceSection","desktopBar","getElementById","mobileBar","stickyColorElement","stickyThumbElement","stickySizeElement","stickySizeWrapper","stickyInseamElement","stickyInseamWrapper","stickyHandElement","stickyHandWrapper","stickyPriceElement","stickyCompareElement","desktopCtaButton","mobileCtaButton","desktopCtaLabel","mobileCtaLabel","showWrapper","wrapper","classList","remove","hideWrapper","add","barsVisible","showBars","isDesktop","window","innerWidth","style","display","opacity","pointerEvents","transform","setAttribute","hideBars","syncPriceFromDOM","priceSection","saleElement","compareElement","regularElement","isSale","Boolean","textContent","trim","color","initPriceSync","MutationObserver","observe","childList","subtree","isMemberExclusiveLoggedOut","me","_stickyIsMemberExclusive","_stickyIsLoggedIn","stickyObserver","userExplicitlySelectedSize","anchorElement","observerStarted","snapAndObserve","target","rect","getBoundingClientRect","width","height","element","transition","headerHeight","bottom","top","innerHeight","requestAnimationFrame","disconnect","IntersectionObserver","entries","entry","boundingClientRect","isIntersecting","threshold","rootMargin","createObserver","getSubmitButton","anchorNode","sectionId","dataset","isSoldOut","submitButton","disabled","xShowSpans","querySelectorAll","xShowSpan","toLowerCase","includes","isCartEditMode","URLSearchParams","location","search","has","syncCtaState","label","btn","soldOut","_needsSize","state","Alpine","store","isFirstLoad","sizeSelected","hasHandOption","handSelected","hasInseamOption","inseamSelected","computeNeedsSize","cartBlocked","isGiftCardBlocked","labelText","getCtaLabel","labelElement","isBlocked","ctaButton","toggle","watchSubmitButton","attributes","attributeFilter","sizeHintTimer","showSizeHint","targetFieldset","getComputedStyle","position","hint","parentNode","appendChild","createElement","id","cssText","join","clearTimeout","setTimeout","stickyLoadingTimer","setStickyLoading","loading","cursor","backgroundColor","borderColor","submitCart","async","key","get","liquidAjaxCart","variantInput","quantityInput","newVariantId","parseInt","value","quantity","lineItem","cart","items","find","item","redirectToCart","href","change","lastCallback","Rebuy","SmartCart","skip_open","_","submitCartUpdate","mainButton","mainButtonObserver","cartDoneHandler","eventName","addEventListener","once","click","updateDesktopBarTop","syncThumbnailFromDOM","_abStickyVariants","matchedVariant","variantParam","variantId","v","checkedColor","colorValue","option1","option2","option3","featured_image","syncSelectionFromDOM","checkedInputs","input","name","inputName","inputValue","initAll","cartSection","watchCartSection","fill","bar","applyHeight","h","parseFloat","paddingBottom","ResizeObserver","syncSafeAreaFill","stickyBarCta","_stickyLoginUrl","scrollIntoView","behavior","block","scrollToVariants","hasSizeOption","isMobile","handFieldset","sizeFieldset","inseamFieldset","fieldset","scrollToSize","anchor","readyState","mutationContainer","body","mutations","mutation","node","addedNodes","nodeType","newAnchor","event","variant","detail","selectedSize","selectedInseam","selectedHand"],"mappings":"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"}