{
  "version": 3,
  "sources": ["/cdn/shop/t/341/assets/skb-custom.js?cb=9"],
  "sourcesContent": ["// Aurum Brothers \u2014 custom JavaScript\r\n\r\n// === Featured collections \u2014 sliding tab indicator (data-active) ===\r\n(function () {\r\n  function initFeaturedCollectionsNav() {\r\n    document.querySelectorAll('.featured-collections-navigation').forEach(function (nav) {\r\n      var buttons = Array.from(nav.querySelectorAll('button'));\r\n\r\n      function setActive(index) {\r\n        nav.setAttribute('data-active', index);\r\n      }\r\n\r\n      // Set initial state from aria-current\r\n      var initial = buttons.findIndex(function (b) {\r\n        return b.getAttribute('aria-current') === 'true';\r\n      });\r\n      setActive(initial >= 0 ? initial : 0);\r\n\r\n      // Update on click\r\n      buttons.forEach(function (btn, index) {\r\n        btn.addEventListener('click', function () {\r\n          setActive(index);\r\n        });\r\n      });\r\n    });\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', initFeaturedCollectionsNav);\r\n  } else {\r\n    initFeaturedCollectionsNav();\r\n  }\r\n})();\r\n\r\n// === Size limits tooltip \u2014 mobile click toggle (KAN-82) ===\r\nvar sizeLimitsReady = false;\r\n\r\nfunction initSizeLimits() {\r\n  document.querySelectorAll('.size-limits').forEach(function (widget) {\r\n    var trigger = widget.querySelector('.size-limits__trigger');\r\n    var closeBtn = widget.querySelector('.size-limits__close');\r\n\r\n    if (!trigger) return;\r\n\r\n    trigger.addEventListener('click', function (e) {\r\n      e.stopPropagation();\r\n      var isOpen = trigger.getAttribute('aria-expanded') === 'true';\r\n      trigger.setAttribute('aria-expanded', String(!isOpen));\r\n    });\r\n\r\n    if (closeBtn) {\r\n      closeBtn.addEventListener('click', function (e) {\r\n        e.stopPropagation();\r\n        trigger.setAttribute('aria-expanded', 'false');\r\n      });\r\n    }\r\n  });\r\n\r\n  if (!sizeLimitsReady) {\r\n    sizeLimitsReady = true;\r\n    document.addEventListener('click', function () {\r\n      document.querySelectorAll('.size-limits__trigger[aria-expanded=\"true\"]').forEach(function (t) {\r\n        t.setAttribute('aria-expanded', 'false');\r\n      });\r\n    });\r\n  }\r\n}\r\n\r\nif (document.readyState === 'loading') {\r\n  document.addEventListener('DOMContentLoaded', initSizeLimits);\r\n} else {\r\n  initSizeLimits();\r\n}\r\n\r\n// === Reusable info point tooltip \u2014 mobile click toggle (KAN-126) ===\r\n// Mirrors the size-limits behaviour for any .info-point widget (e.g. Pre-order).\r\n//\r\n// KAN-142 rewrote this as a single delegated listener, which fixed two things the\r\n// per-widget version got wrong:\r\n//\r\n// 1. Tooltips stacked. Each trigger called stopPropagation, so the document-level\r\n//    \"close everything\" never ran when a trigger was clicked and an already-open\r\n//    bubble stayed open behind the new one.\r\n// 2. In the collection quiz they stopped working after the first answer. Listeners\r\n//    were bound once on DOMContentLoaded, but answering re-renders the whole\r\n//    section through the facets AJAX engine, so every rebuilt icon was inert.\r\n//\r\n// Delegation covers markup that does not exist yet, so there is nothing to\r\n// re-initialise and no window in which a fresh icon is dead.\r\n// KAN-142: the quiz bubble is taken out of the flow (its row is a scroll\r\n// container that would clip it) and sits above the icon that opened it, with a\r\n// tail pointing back down at that icon. CSS cannot know where the icon is, so\r\n// its position is measured here and handed over as custom properties. Read after\r\n// the bubble is visible \u2014 a display:none element measures as zero.\r\nfunction positionInfoPointBubble(trigger) {\r\n  var widget = trigger.closest('.info-point');\r\n  var bubble = widget && widget.querySelector('.info-point__bubble');\r\n  if (!bubble) return;\r\n\r\n  var t = trigger.getBoundingClientRect();\r\n  var anchorX = t.left + t.width / 2;\r\n\r\n  bubble.style.setProperty('--info-point-anchor-x', anchorX + 'px');\r\n  bubble.style.setProperty('--info-point-anchor-y', t.top + 'px');\r\n  bubble.style.setProperty('--info-point-anchor-height', t.height + 'px');\r\n\r\n  // Above by default, below when there is not enough headroom. Without this the\r\n  // bubble runs off the top of the screen for a question sitting high on the\r\n  // page, which is easy to hit on a phone where the viewport is short.\r\n  var b = bubble.getBoundingClientRect();\r\n  var roomAbove = t.top - b.height - 12;\r\n  bubble.setAttribute('data-placement', roomAbove < 8 ? 'below' : 'above');\r\n\r\n  // The tail is placed relative to the bubble, so it needs the anchor expressed\r\n  // as an offset from the bubble's own left edge rather than the viewport's.\r\n  bubble.style.setProperty('--info-point-tail-x', anchorX - b.left + 'px');\r\n}\r\n\r\ndocument.addEventListener('click', function (e) {\r\n  var closeBtn = e.target.closest('.info-point__close');\r\n\r\n  if (closeBtn) {\r\n    var owner = closeBtn.closest('.info-point');\r\n    var ownTrigger = owner && owner.querySelector('.info-point__trigger');\r\n    if (ownTrigger) ownTrigger.setAttribute('aria-expanded', 'false');\r\n    return;\r\n  }\r\n\r\n  var trigger = e.target.closest('.info-point__trigger');\r\n\r\n  // Close every other bubble first, so opening one always shuts the last. Also\r\n  // handles a click anywhere else on the page, including the dimmed backdrop\r\n  // behind an open quiz tooltip.\r\n  document.querySelectorAll('.info-point__trigger[aria-expanded=\"true\"]').forEach(function (t) {\r\n    if (t !== trigger) t.setAttribute('aria-expanded', 'false');\r\n  });\r\n\r\n  if (trigger) {\r\n    var isOpen = trigger.getAttribute('aria-expanded') === 'true';\r\n    trigger.setAttribute('aria-expanded', String(!isOpen));\r\n    if (!isOpen) positionInfoPointBubble(trigger);\r\n  }\r\n});\r\n\r\n// === Homepage Hero Parallax (GSAP ScrollTrigger) ===\r\n// Targets Prestige theme's slideshow section (.shopify-section--slideshow)\r\nfunction initHeroParallax() {\r\n  if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') return;\r\n\r\n  gsap.registerPlugin(ScrollTrigger);\r\n\r\n  // Prestige wraps the slideshow section in .shopify-section--slideshow\r\n  var heroSection = document.querySelector('.shopify-section--slideshow');\r\n  if (!heroSection) return;\r\n\r\n  // First active slide \u2014 Prestige adds .is-selected on initialisation\r\n  var firstSlide =\r\n    heroSection.querySelector('.slideshow__slide.is-selected') || heroSection.querySelector('.slideshow__slide');\r\n  if (!firstSlide) return;\r\n\r\n  // Prestige slideshow renders the background image as a bare <picture> inside .content-over-media\r\n  var heroImage = firstSlide.querySelector('picture');\r\n  // Text overlay lives in .slideshow__slide-content\r\n  var heroContent = firstSlide.querySelector('.slideshow__slide-content');\r\n\r\n  // Pre-scale the picture so the edges never show while it moves\r\n  if (heroImage) {\r\n    gsap.set(heroImage, { scale: 1.15, transformOrigin: '50% 50%' });\r\n    // Image drifts down (slower) \u2192 depth effect\r\n    gsap.to(heroImage, {\r\n      yPercent: 20,\r\n      ease: 'none',\r\n      scrollTrigger: {\r\n        trigger: heroSection,\r\n        start: 'top top',\r\n        end: 'bottom top',\r\n        scrub: 1.5,\r\n      },\r\n    });\r\n  }\r\n\r\n  // Text drifts upward faster \u2192 reinforces the parallax separation\r\n  if (heroContent) {\r\n    gsap.to(heroContent, {\r\n      yPercent: -15,\r\n      ease: 'none',\r\n      scrollTrigger: {\r\n        trigger: heroSection,\r\n        start: 'top top',\r\n        end: 'bottom top',\r\n        scrub: 1.5,\r\n      },\r\n    });\r\n  }\r\n}\r\n\r\n// GSAP is NOT loaded upfront (it used to cost ~110 KB / >1s of mobile\r\n// main-thread on every homepage visit). We inject the self-hosted files only\r\n// when the slideshow hero actually exists on the page \u2014 today it's disabled in\r\n// templates/index.json (the Shoplift hero replaced it), so nothing loads; if\r\n// the slideshow is ever re-enabled, the parallax comes back automatically.\r\nfunction loadHeroParallax() {\r\n  var assets = window.skbGsapAssets;\r\n  if (!assets || !document.querySelector('.shopify-section--slideshow')) return;\r\n\r\n  function inject(src) {\r\n    return new Promise(function (resolve, reject) {\r\n      var s = document.createElement('script');\r\n      s.src = src;\r\n      s.onload = resolve;\r\n      s.onerror = reject;\r\n      document.head.appendChild(s);\r\n    });\r\n  }\r\n\r\n  // ScrollTrigger depends on the gsap core, so load sequentially.\r\n  inject(assets.gsap)\r\n    .then(function () {\r\n      return inject(assets.scrollTrigger);\r\n    })\r\n    .then(initHeroParallax)\r\n    .catch(function () {\r\n      /* parallax is a progressive enhancement \u2014 fail silently */\r\n    });\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', function () {\r\n  loadHeroParallax();\r\n});\r\n\r\n// === Variant Thumb Switcher \u2014 product card swatch click ===\r\n\r\nfunction variantThumb_readData(thumb, handle) {\r\n  const thumbsWrapper = thumb.closest('.variant-thumbs');\r\n  if (!thumbsWrapper) return null;\r\n\r\n  const selectorHandle = window.CSS && CSS.escape ? CSS.escape(handle) : handle.replace(/\"/g, '\\\\\"');\r\n  const template = thumbsWrapper.querySelector('template[data-product-handle=\"' + selectorHandle + '\"]');\r\n  if (!template) return null;\r\n\r\n  const script = template.content\r\n    ? template.content.querySelector('script[type=\"application/json\"]')\r\n    : template.querySelector('script[type=\"application/json\"]');\r\n  if (!script) return null;\r\n\r\n  try {\r\n    return JSON.parse(script.textContent.trim());\r\n  } catch (err) {\r\n    console.error('Invalid template JSON', err);\r\n    return null;\r\n  }\r\n}\r\n\r\nfunction variantThumb_updateMedia(card, data) {\r\n  const img = card.querySelector('.product-card__image--primary') || card.querySelector('.product-card__media img');\r\n  if (!img || !data.image) return;\r\n  const base = data.image.replace(/&width=\\d+/, '');\r\n  img.src = data.image;\r\n  img.srcset = [200, 300, 400, 500, 600, 700, 800, 1000, 1200, 1400, 1600, 1800]\r\n    .map(function (w) {\r\n      return base + '&width=' + w + ' ' + w + 'w';\r\n    })\r\n    .join(', ');\r\n}\r\n\r\nfunction variantThumb_updateLinks(card, data) {\r\n  const mediaLink = card.querySelector('.product-card__media');\r\n  if (mediaLink) mediaLink.href = data.url;\r\n\r\n  const titleEl = card.querySelector('.product-title');\r\n  if (titleEl) {\r\n    titleEl.textContent = data.title;\r\n    titleEl.href = data.url;\r\n  }\r\n}\r\n\r\nfunction variantThumb_updatePrice(card, data) {\r\n  const oldPrice = card.querySelector('.price-list');\r\n  if (!oldPrice || !data.price_html) return;\r\n  const temp = document.createElement('div');\r\n  temp.innerHTML = data.price_html;\r\n  oldPrice.replaceWith(temp.firstElementChild);\r\n}\r\n\r\nfunction variantThumb_updateVariantId(card, handle, data) {\r\n  const variantInput = card.querySelector('input[name=\"id\"]');\r\n  if (variantInput && data.variant_id) variantInput.value = data.variant_id;\r\n\r\n  const quickBuyModal = card.querySelector('quick-buy-modal');\r\n  if (quickBuyModal) quickBuyModal.setAttribute('handle', handle);\r\n}\r\n\r\nfunction variantThumb_updateActiveState(card, activeThumb) {\r\n  card.querySelectorAll('.variant-thumb').forEach(function (el) {\r\n    el.classList.remove('selected');\r\n    const elImg = el.querySelector('img');\r\n    if (elImg) elImg.style.borderBottom = 'none';\r\n  });\r\n  activeThumb.classList.add('selected');\r\n  const thumbImg = activeThumb.querySelector('img');\r\n  if (thumbImg) thumbImg.style.borderBottom = '3px solid white';\r\n}\r\n\r\nfunction variantThumb_updateRating(card, data) {\r\n  card.querySelectorAll('.ab-rating[data-product-id]').forEach(function (el) {\r\n    el.style.display = String(el.dataset.productId) === String(data.product_id) ? '' : 'none';\r\n  });\r\n}\r\n\r\nfunction variantThumb_updateBadges(card, data) {\r\n  const figure = card.querySelector('.product-card__figure');\r\n  let badgeList = card.querySelector('badge-list');\r\n  if (!badgeList && figure) {\r\n    badgeList = document.createElement('badge-list');\r\n    badgeList.className = 'badge-list badge-list--vertical';\r\n    figure.prepend(badgeList);\r\n  }\r\n  if (!badgeList) return;\r\n\r\n  badgeList.innerHTML = '';\r\n  if (data.badge) {\r\n    const badges = Array.isArray(data.badge) ? data.badge : [data.badge];\r\n    badges.forEach(function (text) {\r\n      if (!text || !text.trim()) return;\r\n      const span = document.createElement('span');\r\n      span.className = 'badge badge--custom';\r\n      span.textContent = text;\r\n      badgeList.appendChild(span);\r\n    });\r\n  }\r\n  const soldOutLabel = window.themeVariables?.strings?.soldOutBadge;\r\n  if (data.available === false && soldOutLabel) {\r\n    // Skip the badge entirely when the string is unavailable \u2014 an empty\r\n    // <sold-out-badge> would still paint as a coloured pill.\r\n    const soldOut = document.createElement('sold-out-badge');\r\n    soldOut.className = 'badge badge--sold-out';\r\n    soldOut.textContent = soldOutLabel;\r\n    badgeList.appendChild(soldOut);\r\n  }\r\n  badgeList.hidden = badgeList.children.length === 0;\r\n}\r\n\r\nfunction variantThumb_updateQuickBuy(card, data) {\r\n  const btn = card.querySelector('.product-card__quick-add-button');\r\n  if (btn) btn.style.display = data.available === false ? 'none' : '';\r\n}\r\n\r\ndocument.addEventListener('click', function (e) {\r\n  const thumb = e.target.closest('.variant-thumb');\r\n  if (!thumb) return;\r\n\r\n  const card = thumb.closest('.product-card');\r\n  if (!card) return;\r\n\r\n  const handle = thumb.dataset.variantHandle;\r\n  if (!handle) return;\r\n\r\n  const data = variantThumb_readData(thumb, handle);\r\n  if (!data) return;\r\n\r\n  variantThumb_updateMedia(card, data);\r\n  variantThumb_updateLinks(card, data);\r\n  variantThumb_updatePrice(card, data);\r\n  variantThumb_updateVariantId(card, handle, data);\r\n  variantThumb_updateActiveState(card, thumb);\r\n  variantThumb_updateRating(card, data);\r\n  variantThumb_updateBadges(card, data);\r\n  variantThumb_updateQuickBuy(card, data);\r\n});\r\n\r\n// === Sticky ATC (scroll-back mode) \u2014 button handler ===\r\nfunction skbSmoothScroll(targetY, duration) {\r\n  var startY = window.pageYOffset;\r\n  var diff = targetY - startY;\r\n  var startTime = null;\r\n  function step(ts) {\r\n    if (!startTime) startTime = ts;\r\n    var p = Math.min((ts - startTime) / duration, 1);\r\n    var ease = p < 0.5 ? 4 * p * p * p : 1 - Math.pow(-2 * p + 2, 3) / 2;\r\n    window.scrollTo(0, startY + diff * ease);\r\n    if (p < 1) requestAnimationFrame(step);\r\n  }\r\n  requestAnimationFrame(step);\r\n}\r\n\r\ndocument.addEventListener('click', function (e) {\r\n  var btn = e.target.closest('[data-sticky-atc-trigger]');\r\n  if (!btn) return;\r\n  var formId = btn.dataset.stickyAtcTrigger;\r\n  var f = document.getElementById('wrist-size');\r\n  if (f && f.value.trim() === '') {\r\n    // Pin the label+field to a fixed offset below the top of the viewport\r\n    // instead of centering in whatever space is left once the keyboard\r\n    // opens \u2014 the keyboard only eats space from the bottom, so a top-anchored\r\n    // target is independent of keyboard height and identical on every\r\n    // phone/browser, unlike centering (which needs to know exactly how tall\r\n    // the keyboard + any autofill bar is).\r\n    var wrap = f.closest('.line-item-property') || f;\r\n    var stickyAreaHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--sticky-area-height')) || 0;\r\n    // Margin above the field scales with screen height instead of a flat\r\n    // pixel value \u2014 a fixed px clears the browser's address-bar chrome fine\r\n    // on a tall phone but eats proportionally more of a small phone's\r\n    // screen, so it still doesn't leave enough room there. 14% of the\r\n    // viewport height, clamped, tracks screen size directly.\r\n    var topMargin = Math.max(60, Math.min(window.innerHeight * 0.14, 160));\r\n    var targetY = window.pageYOffset + wrap.getBoundingClientRect().top - stickyAreaHeight - topMargin;\r\n    skbSmoothScroll(targetY, 600);\r\n    f.focus({ preventScroll: true });\r\n  } else {\r\n    document.querySelector('#' + formId + ' [type=submit]')?.click();\r\n  }\r\n});\r\n\r\n// === Sticky ATC (scroll-back mode) \u2014 reliable scroll-based visibility ===\r\n// The native IntersectionObserver in theme.js has edge cases with mobile virtual\r\n// keyboards and smooth scrolling. We override visibility with a direct scroll check\r\n// so the bar ALWAYS appears when the user is below the ATC form.\r\ndocument.addEventListener('DOMContentLoaded', function () {\r\n  var bar = document.querySelector('product-sticky-bar.product-sticky-bar--scroll-only');\r\n  if (!bar) return;\r\n\r\n  var formId = bar.getAttribute('form');\r\n  var form = document.getElementById(formId) || document.forms[formId];\r\n  if (!form) return;\r\n\r\n  var footer = document.querySelector('.shopify-section--footer');\r\n\r\n  function updateVisibility() {\r\n    var formBottom = form.getBoundingClientRect().bottom;\r\n    var belowForm = formBottom < 0;\r\n    var beforeFooter = !footer || footer.getBoundingClientRect().top > window.innerHeight;\r\n\r\n    var shouldShow = belowForm && beforeFooter;\r\n    bar.classList.toggle('is-visible', shouldShow);\r\n    if (shouldShow) bar.removeAttribute('hidden');\r\n  }\r\n\r\n  window.addEventListener('scroll', updateVisibility, { passive: true });\r\n  // Also catch viewport changes from mobile keyboard\r\n  if (window.visualViewport) {\r\n    window.visualViewport.addEventListener('resize', updateVisibility);\r\n  }\r\n  updateVisibility();\r\n});\r\n\r\n// Scroll so an element's top sits just under the sticky header.\r\nfunction skbScrollToElement(target, duration, gap) {\r\n  var sticky = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--sticky-area-height')) || 0;\r\n  var y = window.pageYOffset + target.getBoundingClientRect().top - sticky - (gap || 0);\r\n  skbSmoothScroll(Math.max(0, y), duration);\r\n}\r\n\r\n// === Judge.me rating: smooth scroll to the reviews (was KAN-192 for Klaviyo) ===\r\n// The rating on the product page (snippets/ab-rating.liquid, on_page) links to\r\n// #judgeme_product_reviews. Scroll there ourselves so the sticky header doesn't cover the\r\n// heading. Arriving from a card link (/products/x#judgeme_product_reviews) does the same once\r\n// Judge.me has filled its widget, since the anchor isn't in the HTML on first paint.\r\n(function () {\r\n  var HASH = '#judgeme_product_reviews';\r\n  // Enough of a gap under the sticky header that the heading is not flush against it.\r\n  var BREATHING_ROOM = 16;\r\n\r\n  function findTarget() {\r\n    return document.getElementById('judgeme_product_reviews') || document.querySelector('.jdgm-review-widget');\r\n  }\r\n\r\n  function scrollToReviews(duration) {\r\n    var target = findTarget();\r\n    if (!target) return false;\r\n    skbScrollToElement(target, duration, BREATHING_ROOM);\r\n    return true;\r\n  }\r\n\r\n  document.addEventListener('click', function (event) {\r\n    var link = event.target && event.target.closest && event.target.closest('a.ab-rating--on-page');\r\n    if (!link || !findTarget()) return;\r\n    event.preventDefault();\r\n    scrollToReviews(600);\r\n  });\r\n\r\n  // Landing with the hash: skip product pages with the discovery layout, which handle it themselves.\r\n  if (window.location.hash === HASH && !document.querySelector('ab-pdp-discovery')) {\r\n    var tries = 0;\r\n    var timer = setInterval(function () {\r\n      tries += 1;\r\n      var target = findTarget();\r\n      var filled = target && target.querySelector('[class*=\"jm-review\"], .jdgm-rev-widg');\r\n      if (filled || tries > 40) {\r\n        clearInterval(timer);\r\n        if (target) scrollToReviews(0);\r\n      }\r\n    }, 250);\r\n  }\r\n})();\r\n\r\n// === Hero rating line \u2192 reviews further down the page (Image hero 1.1, \"Reviews on this page\") ===\r\n// Finds the first reviews section below: a Judge.me widget/carousel app block first, the\r\n// Featured reviews section as a fallback. Without one the line is left unclickable.\r\n(function () {\r\n  var TARGETS = [\r\n    '[id*=\"judge_me_reviews\"]',\r\n    '.jdgm-carousel-wrapper',\r\n    '.jdgm-widget:not(.jdgm-preview-badge):not(.jdgm-prev-badge)',\r\n    '.shopify-section--featured-reviews'\r\n  ];\r\n\r\n  function findTarget(link) {\r\n    for (var i = 0; i < TARGETS.length; i++) {\r\n      var nodes = document.querySelectorAll(TARGETS[i]);\r\n      for (var j = 0; j < nodes.length; j++) {\r\n        var node = nodes[j];\r\n        // Must come after the link in the page and not be inside the header area\r\n        if (link.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING && !node.closest('.sl-block')) {\r\n          return node.closest('.shopify-section') || node;\r\n        }\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  function refresh() {\r\n    document.querySelectorAll('[data-ab-reviews-jump]').forEach(function (link) {\r\n      link.classList.toggle('ab-hero-reviews-link--inactive', !findTarget(link));\r\n    });\r\n  }\r\n\r\n  document.addEventListener('click', function (event) {\r\n    var link = event.target && event.target.closest && event.target.closest('[data-ab-reviews-jump]');\r\n    if (!link) return;\r\n    event.preventDefault();\r\n    var target = findTarget(link);\r\n    if (target) skbScrollToElement(target, 700, 16);\r\n  });\r\n\r\n  refresh();\r\n  // App blocks can render late; check again once everything has loaded.\r\n  window.addEventListener('load', refresh);\r\n})();\r\n\r\n// === Cart add-to-cart failure tracking \u2192 GTM dataLayer \u2192 GA4 ===\r\n// Prestige dispatches a bubbling `cart:error` event from the <product-form>'s\r\n// inner <form> when an add-to-cart request fails (out of stock, quantity limit,\r\n// etc.). We forward it to GTM's dataLayer as `cart_add_error`.\r\n// The cart-page quantity updater also emits `cart:error` (with detail.message),\r\n// so we only handle events that originate from an add-to-cart <form>.\r\n(function () {\r\n  document.addEventListener('cart:error', function (event) {\r\n    var form = event.target;\r\n\r\n    // Only track add-to-cart failures, not cart quantity-update errors.\r\n    var isAddForm = form && form.tagName === 'FORM' && /\\/cart\\/add/.test(form.action || '');\r\n    if (!isAddForm) return;\r\n\r\n    var detail = event.detail || {};\r\n    var variantField = form.elements ? form.elements['id'] : null;\r\n    var productField = form.elements ? form.elements['product-id'] : null;\r\n    var card = form.closest ? form.closest('product-card') : null;\r\n\r\n    window.dataLayer = window.dataLayer || [];\r\n    window.dataLayer.push({\r\n      event: 'cart_add_error',\r\n      error_message: detail.error || detail.message || 'unknown',\r\n      variant_id: variantField && variantField.value ? variantField.value : 'unknown',\r\n      product_id: productField && productField.value ? productField.value : 'unknown',\r\n      product_handle: card && card.getAttribute('handle') ? card.getAttribute('handle') : 'unknown',\r\n      page_url: window.location.href,\r\n      page_path: window.location.pathname,\r\n    });\r\n  });\r\n})();\r\n\r\n// === Featured reviews (KAN-88): store-wide latest Klaviyo reviews ===\r\n// Hydrates the custom `featured-reviews` section. Fetches the latest published\r\n// reviews store-wide from Klaviyo's onsite client API (no key needed; public\r\n// company_id only) and renders a multi-column grid of cards, each linking to its\r\n// connected product. Replaces the default testimonial carousel.\r\n//\r\n// IMPORTANT: hit fast.a.klaviyo.com directly \u2014 a.klaviyo.com 301-redirects and\r\n// drops the Access-Control-Allow-Origin header, which CORS-blocks the request.\r\n(function () {\r\n  var ENDPOINT = 'https://fast.a.klaviyo.com/reviews/api/client_reviews/all/';\r\n\r\n  function esc(s) {\r\n    return String(s == null ? '' : s).replace(/[&<>\"']/g, function (c) {\r\n      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\r\n    });\r\n  }\r\n\r\n  function stars(rating) {\r\n    var n = Math.max(0, Math.min(5, Math.round(rating || 0)));\r\n    // role=\"img\" + aria-label gives screen readers a single \"n out of 5 stars\"\r\n    // label; the \u2605 glyphs are decorative and hidden so they aren't read out too.\r\n    return (\r\n      '<span class=\"ab-review__stars\" role=\"img\" aria-label=\"' +\r\n      n +\r\n      ' out of 5 stars\">' +\r\n      '<span class=\"ab-review__stars-on\" aria-hidden=\"true\">' +\r\n      Array(n + 1).join('\u2605') +\r\n      '</span>' +\r\n      '<span class=\"ab-review__stars-off\" aria-hidden=\"true\">' +\r\n      Array(6 - n).join('\u2605') +\r\n      '</span>' +\r\n      '</span>'\r\n    );\r\n  }\r\n\r\n  // Reviews are publicly submittable, so treat product.image_url as untrusted:\r\n  // only emit it if it's an absolute https URL.\r\n  function safeImageUrl(url) {\r\n    return typeof url === 'string' && /^https:\\/\\//i.test(url) ? url : '';\r\n  }\r\n\r\n  function formatDate(iso) {\r\n    var d = new Date(iso);\r\n    if (isNaN(d)) return '';\r\n    try {\r\n      return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\r\n    } catch (e) {\r\n      return d.toISOString().slice(0, 10);\r\n    }\r\n  }\r\n\r\n  function cardHtml(review, opts) {\r\n    var product = review.product || {};\r\n    var content = (review.content || '').trim();\r\n    var parts = [];\r\n\r\n    parts.push(stars(review.rating));\r\n    if (review.title) parts.push('<h3 class=\"ab-review__title\">' + esc(review.title) + '</h3>');\r\n    if (content) parts.push('<p class=\"ab-review__body\" title=\"' + esc(content) + '\">' + esc(content) + '</p>');\r\n\r\n    var meta = [];\r\n    if (review.author) meta.push('<span class=\"ab-review__author\">' + esc(review.author) + '</span>');\r\n    if (review.verified) meta.push('<span class=\"ab-review__verified\">Verified</span>');\r\n    if (opts.showDate && review.created_at) {\r\n      var dt = formatDate(review.created_at);\r\n      if (dt) meta.push('<span class=\"ab-review__date\">' + esc(dt) + '</span>');\r\n    }\r\n    if (meta.length)\r\n      parts.push('<footer class=\"ab-review__meta\">' + meta.join('<span class=\"ab-review__sep\">\u00B7</span>') + '</footer>');\r\n\r\n    // Connected product \u2014 the key feature the default testimonial lacks.\r\n    if (opts.showProduct && product.shopify_handle) {\r\n      var href = '/products/' + encodeURIComponent(product.shopify_handle);\r\n      var imageUrl = safeImageUrl(product.image_url);\r\n      var img = imageUrl\r\n        ? '<img class=\"ab-review__product-image\" src=\"' +\r\n          esc(imageUrl) +\r\n          '\" alt=\"\" loading=\"lazy\" width=\"40\" height=\"40\">'\r\n        : '';\r\n      parts.push(\r\n        '<a class=\"ab-review__product\" href=\"' +\r\n          href +\r\n          '\">' +\r\n          img +\r\n          '<span class=\"ab-review__product-name\">' +\r\n          esc(product.name || '') +\r\n          '</span>' +\r\n          '</a>'\r\n      );\r\n    }\r\n\r\n    return '<article class=\"ab-review\">' + parts.join('') + '</article>';\r\n  }\r\n\r\n  function hydrate(container) {\r\n    if (container.hasAttribute('data-ab-reviews-ready')) return;\r\n    container.setAttribute('data-ab-reviews-ready', '');\r\n\r\n    var companyId = container.getAttribute('data-company-id');\r\n    if (!companyId) return;\r\n\r\n    var count = parseInt(container.getAttribute('data-count'), 10) || 12;\r\n    var minRating = parseInt(container.getAttribute('data-min-rating'), 10) || 0;\r\n    var requireText = container.getAttribute('data-require-text') === 'true';\r\n    var opts = {\r\n      showProduct: container.getAttribute('data-show-product') === 'true',\r\n      showDate: container.getAttribute('data-show-date') === 'true',\r\n    };\r\n\r\n    // Optional collection allow-list (product handles from the section setting).\r\n    // When set, only reviews for those products are shown \u2014 lets the merchant\r\n    // exclude service products (repair/resize) or feature a curated set.\r\n    var allowedRaw = container.getAttribute('data-allowed-handles') || '';\r\n    var allowedHandles = allowedRaw\r\n      ? allowedRaw.split(',').filter(function (h) {\r\n          return h;\r\n        })\r\n      : [];\r\n    var allowedSet = allowedHandles.length ? new Set(allowedHandles) : null;\r\n\r\n    // Over-fetch so client-side filtering (rating / has-text / collection) still\r\n    // yields `count` cards. A collection filter is the most restrictive, so pull\r\n    // the API maximum when one is active.\r\n    var fetchLimit = allowedSet ? 50 : Math.min(count * 3, 50);\r\n    var url = ENDPOINT + '?company_id=' + encodeURIComponent(companyId) + '&limit=' + fetchLimit + '&offset=0&sort=3';\r\n\r\n    fetch(url)\r\n      .then(function (r) {\r\n        if (!r.ok) throw new Error('Klaviyo reviews ' + r.status);\r\n        return r.json();\r\n      })\r\n      .then(function (data) {\r\n        // The dynamic heading (overall rating + total review count) comes from the\r\n        // API `summary`, not the individual reviews \u2014 so it reflects the whole store\r\n        // regardless of the rating/has-text filters applied to the cards below.\r\n        updateDynamicText(container, data && data.summary);\r\n        var reviews = (data && data.reviews) || [];\r\n        var filtered = reviews.filter(function (rv) {\r\n          if (rv.rating < minRating) return false;\r\n          if (requireText && !(rv.content && rv.content.trim())) return false;\r\n          if (allowedSet) {\r\n            var handle = rv.product && rv.product.shopify_handle;\r\n            if (!handle || !allowedSet.has(handle)) return false;\r\n          }\r\n          return true;\r\n        });\r\n        render(container, filtered.slice(0, count), opts);\r\n      })\r\n      .catch(function (err) {\r\n        // On failure, collapse the whole section rather than leaving an empty\r\n        // heading + skeletons behind.\r\n        if (window.console && console.warn) console.warn('[ab-reviews] load failed', err);\r\n        collapseSection(container);\r\n      });\r\n  }\r\n\r\n  // Fill the section heading/subheading from the live API summary. Each token-bearing\r\n  // element carries a `data-template` with [rating] / [count] tokens; we swap them for\r\n  // the real numbers and reveal it (it's kept hidden until now so raw tokens never flash).\r\n  function updateDynamicText(container, summary) {\r\n    var section = container.closest('.shopify-section');\r\n    if (!section) return;\r\n    var els = section.querySelectorAll('[data-ab-reviews-token]');\r\n    if (!els.length) return;\r\n    var rating = summary && typeof summary.star_rating === 'number' ? summary.star_rating.toFixed(1) : '';\r\n    var countNum = summary && typeof summary.review_count === 'number' ? summary.review_count : null;\r\n    var count = countNum == null ? '' : countNum.toLocaleString();\r\n    for (var i = 0; i < els.length; i++) {\r\n      var el = els[i];\r\n      var tpl = el.getAttribute('data-template') || el.textContent || '';\r\n      // The theme editor injects `<!-- BEGIN/END SETTING: ... -->` comments around any\r\n      // `{{ section.settings.x }}` output, including inside this data-* attribute. Strip\r\n      // them so they don't get read back and painted as literal text below.\r\n      tpl = tpl.replace(/<!--\\s*(?:BEGIN|END) SETTING:[\\s\\S]*?-->/g, '');\r\n      el.textContent = tpl.replace(/\\[rating\\]/g, rating).replace(/\\[count\\]/g, count);\r\n      el.classList.remove('ab-reviews__dynamic-text--pending');\r\n    }\r\n  }\r\n\r\n  // Hide the entire section wrapper so a failed/empty fetch leaves no orphaned\r\n  // heading, padding, or border on the page.\r\n  function collapseSection(container) {\r\n    var section = container.closest('.shopify-section');\r\n    if (section) {\r\n      section.style.display = 'none';\r\n    } else {\r\n      var track = container.querySelector('.ab-reviews__track');\r\n      if (track) track.remove();\r\n    }\r\n  }\r\n\r\n  function render(container, reviews, opts) {\r\n    var track = container.querySelector('.ab-reviews__track');\r\n    if (!track) {\r\n      track = document.createElement('div');\r\n      track.className = 'ab-reviews__track';\r\n      container.appendChild(track);\r\n    }\r\n    if (!reviews.length) {\r\n      collapseSection(container);\r\n      return;\r\n    }\r\n    track.removeAttribute('aria-busy');\r\n    track.innerHTML = reviews\r\n      .map(function (rv) {\r\n        return cardHtml(rv, opts);\r\n      })\r\n      .join('');\r\n\r\n    // The native <scroll-carousel> only recomputes `.is-scrollable` (which shows/\r\n    // hides the prev/next controls) on resize. Injecting cards changes scrollWidth\r\n    // but not the element's own box, so nudge the flag to match the real content.\r\n    if (track.classList && typeof track.scrollWidth === 'number') {\r\n      track.classList.toggle('is-scrollable', track.scrollWidth - track.clientWidth > 1);\r\n    }\r\n  }\r\n\r\n  function init() {\r\n    document.querySelectorAll('[data-ab-reviews]').forEach(hydrate);\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    init();\r\n  }\r\n  // Re-run when the theme editor re-renders the section.\r\n  document.addEventListener('shopify:section:load', init);\r\n})();\r\n\r\n// === Wishlist page: swap the remove \"X\" for a trash icon (KAN-31 item 2c) ===\r\n// The remove button lives inside nested OPEN shadow roots\r\n// (<ooo-wl-page-container> \u2192 <ooo-wl-page-product-card>), so theme CSS can't\r\n// reach it (custom properties cross the boundary, plain selectors don't). We\r\n// inject a tiny stylesheet into each product card's shadow root that hides the\r\n// app's X glyph and paints a trash icon via a masked pseudo-element (inheriting\r\n// the button colour set by --ooo-wl-...-remove-button-color). NOTE: this relies\r\n// on the app's open shadow DOM structure \u2014 if Wishlist Power changes its markup,\r\n// revisit this. The trash SVG is inline (no external Flaticon asset).\r\n(function () {\r\n  var TRASH_MASK =\r\n    \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16'/%3E%3Cpath d='M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2'/%3E%3Cpath d='M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13'/%3E%3Cpath d='M10 11v6'/%3E%3Cpath d='M14 11v6'/%3E%3C/svg%3E\\\") center / contain no-repeat\";\r\n\r\n  // NOTE: do NOT set position on the button \u2014 the app already makes it\r\n  // position:absolute at the card's top-right, and overriding it drops the\r\n  // icon into normal flow (bottom-left). The ::after centres itself inside the\r\n  // button's existing grid layout.\r\n  var TRASH_CSS =\r\n    '.ooo-wl-button-icon--delete{display:none!important;}' +\r\n    \"ooo-wl-page-product-card-remove-button button::after{content:'';display:block;\" +\r\n    'width:1.125rem;height:1.125rem;background-color:currentColor;' +\r\n    '-webkit-mask:' +\r\n    TRASH_MASK +\r\n    ';mask:' +\r\n    TRASH_MASK +\r\n    ';}' +\r\n    // Hover: same gold pulse as the share button. The trash glyph is painted\r\n    // with currentColor, so animating `color` on the button recolors it.\r\n    'ooo-wl-page-product-card-remove-button button{transition:color .4s ease;}' +\r\n    'ooo-wl-page-product-card-remove-button button:hover{' +\r\n    'animation:skbTrashGlow 2.8s ease-in-out infinite;}' +\r\n    '@keyframes skbTrashGlow{' +\r\n    '0%,100%{color:#bb9d7b;}' +\r\n    '50%{color:#f0e2c4;}}' +\r\n    // Desktop: the trash shows on hover, like the bookmark on product cards (custom.css).\r\n    '@media screen and (hover:hover) and (pointer:fine){' +\r\n    'ooo-wl-page-product-card-remove-button{opacity:0;transition:opacity .2s ease-in-out;}' +\r\n    ':host(:hover) ooo-wl-page-product-card-remove-button,' +\r\n    'ooo-wl-page-product-card-remove-button:focus-within{opacity:1;}}';\r\n\r\n  // Wishlist page cards follow the theme product card (Theme settings > Product card): same frame,\r\n  // colours, title and price type, arrow, and quick add style; the trash takes the wishlist icon's\r\n  // spot. Built per card from the same --product-card-* custom properties custom.css uses (they\r\n  // inherit across the shadow boundary). The app's variant picker is hidden: single-variant products\r\n  // keep a quick add button, multi-variant products show none (the shopper picks a size on the PDP).\r\n  function svgMask(markup) {\r\n    if (!markup) return '';\r\n    var svg = String(markup).replace(/currentColor/g, 'black');\r\n    if (svg.indexOf('xmlns=') === -1) svg = svg.replace('<svg', \"<svg xmlns='http://www.w3.org/2000/svg'\");\r\n    return 'url(\"data:image/svg+xml,' + encodeURIComponent(svg).replace(/'/g, '%27') + '\") center / contain no-repeat';\r\n  }\r\n\r\n  var PLUS_MASK = svgMask('<svg viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M6 0v12M0 6h12\" stroke=\"black\" stroke-width=\"1.5\"/></svg>');\r\n  var ARROW_BG =\r\n    \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M3 17 17 3M8 3h9v9' fill='none' stroke='%23bb9d7b' stroke-width='1'/%3E%3C/svg%3E\\\") center / contain no-repeat\";\r\n\r\n  function cardCss() {\r\n    var settings = (window.themeVariables && window.themeVariables.settings) || {};\r\n    var outlined = settings.productCardQuickAddStyle === 'outlined';\r\n    var fp = 'var(--product-card-frame-padding,0px)';\r\n    var ip = 'var(--product-card-info-padding-inline,0px)';\r\n    var css =\r\n      ':host{--product-card-qa-size:34px;' +\r\n      '--ooo-wl-page-product-card-remove-button-inline-end:calc(' + ip + ' + (var(--product-card-qa-size) - 2.625rem) / 2);}' +\r\n      // Card frame and image area\r\n      '.ooo-wl-page-product-card{position:relative;container-type:inline-size;gap:0!important;padding:' + fp + ';' +\r\n      'border:var(--product-card-frame-border,0);border-radius:var(--product-card-radius,0px);overflow:hidden;' +\r\n      'background:var(--product-card-card-bg,transparent);}' +\r\n      '.ooo-wl-page-product-card__image-container{border-radius:max(0px,calc(var(--product-card-radius,0px) - ' + fp + '));overflow:hidden;' +\r\n      'background:var(--product-card-image-bg,var(--product-card-card-bg,transparent));}' +\r\n      '.ooo-wl-page-product-card__image-container img{object-fit:contain;}' +\r\n      // Text strip\r\n      '.ooo-wl-page-product-card__info-container{position:static!important;display:flex!important;flex-direction:column!important;' +\r\n      'align-items:var(--product-card-text-align,start)!important;justify-content:flex-start!important;gap:3px!important;' +\r\n      'padding:13px ' + ip + ' ' + fp + '!important;text-align:var(--product-card-text-align,start)!important;' +\r\n      'background:var(--product-card-bg,transparent);}' +\r\n      '.ooo-wl-page-product-card__info-wrapper{width:100%;gap:0!important;justify-items:var(--product-card-text-align,start)!important;' +\r\n      'align-items:var(--product-card-text-align,start)!important;text-align:inherit!important;}' +\r\n      '.ooo-wl-page-product-card__price-container{justify-content:var(--product-card-text-align,start)!important;' +\r\n      'align-items:baseline!important;text-align:inherit!important;}' +\r\n      '[data-field=\"title\"]{display:block;position:relative;width:100%;box-sizing:border-box;' +\r\n      (settings.productCardTitleArrow === false ? '' : 'padding-inline-end:22px;') +\r\n      'font-size:var(--text-base)!important;line-height:var(--leading-snug)!important;font-weight:400!important;' +\r\n      'letter-spacing:0!important;text-transform:none!important;overflow-wrap:anywhere;' +\r\n      'color:var(--product-card-title-color,inherit)!important;}' +\r\n      (settings.productCardTitleArrow === false\r\n        ? ''\r\n        : '[data-field=\"title\"]::after{content:\"\";position:absolute;inset-inline-end:0;top:2px;width:17px;height:17px;background:' + ARROW_BG + ';}') +\r\n      '[data-field=\"price-container\"]{margin-top:7px;gap:6px;}' +\r\n      '[data-field=\"price\"],[data-field=\"compare-at-price\"]{font-size:var(--text-sm)!important;line-height:var(--leading-normal)!important;' +\r\n      'color:var(--product-card-price-color,inherit)!important;}' +\r\n      '[data-field=\"compare-at-price\"]{opacity:.7;}' +\r\n      // Stands in for the product card's rating row (28px), so card heights and the quick add spot match.\r\n      '.ooo-wl-page-product-card__info-wrapper::after{content:\"\";display:block;height:28px;}' +\r\n      // Add to cart: no variant picker; multi-variant products show no button\r\n      '[data-field=\"variants-select-container\"]{display:none!important;}' +\r\n      'ooo-wl-page-product-card-form{margin:0!important;}' +\r\n      'ooo-wl-page-product-card-form:has(select option:nth-child(3)){display:none!important;}' +\r\n      'ooo-wl-page-product-card-form [data-field=\"form-button\"]{position:absolute!important;display:grid!important;place-items:center!important;' +\r\n      'min-height:0!important;padding:0!important;font-size:0!important;letter-spacing:0!important;z-index:2;}' +\r\n      'ooo-wl-page-product-card-form [data-field=\"form-button\"] [data-action=\"label\"]{position:absolute!important;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);}' +\r\n      // The app's loading dots sit over the icon instead of taking a grid cell beside it.\r\n      'ooo-wl-page-product-card-form [data-field=\"form-button\"] [data-action=\"loading\"]{position:absolute!important;}' +\r\n      // The app uses ::before for its own button effect; re-centre it for the icon.\r\n      'ooo-wl-page-product-card-form [data-field=\"form-button\"]::before{content:\"\";display:block;position:absolute!important;inset:0!important;' +\r\n      'margin:auto!important;transform:none!important;opacity:1!important;background-color:currentColor!important;}';\r\n    if (outlined) {\r\n      css +=\r\n        // Round outline with the header cart icon, bottom right of the text strip\r\n        '.ooo-wl-page-product-card__info-container:has(ooo-wl-page-product-card-form:not([hidden])) .ooo-wl-page-product-card__price-container{padding-inline-end:40px;}' +\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]{' +\r\n        'inset-block-end:calc(max(0.65rem,' + fp + ') + ' + fp + ')!important;inset-inline-end:calc(' + fp + ' + ' + ip + ')!important;' +\r\n        'width:var(--product-card-qa-size)!important;height:var(--product-card-qa-size)!important;' +\r\n        'border:1px solid rgb(var(--text-color) / .25)!important;border-radius:999px!important;background:transparent!important;' +\r\n        'color:var(--product-card-price-color,rgb(var(--text-color)))!important;transition:border-color .2s ease!important;}' +\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]::before{width:16px;height:16px;' +\r\n        '-webkit-mask:' + svgMask(settings.productCardQuickAddIcon) + ';mask:' + svgMask(settings.productCardQuickAddIcon) + ';}' +\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]:hover{border-color:var(--color-accent,currentColor)!important;}';\r\n    } else {\r\n      css +=\r\n        // The theme's original plus: square, bottom right of the image, shown on hover on desktop\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]{' +\r\n        'top:calc(' + fp + ' + 100cqw - 0.5rem - 2rem)!important;inset-inline-end:calc(' + fp + ' + 0.5rem)!important;' +\r\n        'width:2rem!important;height:2rem!important;border:0!important;border-radius:0!important;' +\r\n        'background:var(--color-accent,rgb(187 157 123))!important;color:rgb(255 255 255)!important;}' +\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]::before{width:12px;height:12px;-webkit-mask:' + PLUS_MASK + ';mask:' + PLUS_MASK + ';}' +\r\n        '@media screen and (pointer:fine){ooo-wl-page-product-card-form [data-field=\"form-button\"]{opacity:0;transform:translateY(5px);' +\r\n        'transition:opacity .2s ease-in-out,transform .2s ease-in-out!important;}' +\r\n        ':host(:hover) ooo-wl-page-product-card-form [data-field=\"form-button\"],' +\r\n        'ooo-wl-page-product-card-form [data-field=\"form-button\"]:focus{opacity:1;transform:none;}}';\r\n    }\r\n    css +=\r\n      '@media screen and (max-width:760px){:host{--product-card-qa-size:30px;}' +\r\n      '.ooo-wl-page-product-card__info-container{padding-top:8px!important;gap:0!important;}' +\r\n      '[data-field=\"title\"]{font-size:var(--text-sm)!important;}' +\r\n      '[data-field=\"price-container\"]{margin-top:5px;}' +\r\n      '.ooo-wl-page-product-card__info-wrapper::after{height:24px;}}';\r\n    return css;\r\n  }\r\n\r\n  function injectInto(root) {\r\n    if (!root || root.querySelector('style[data-wl-trash]')) return;\r\n    var style = document.createElement('style');\r\n    style.setAttribute('data-wl-trash', '');\r\n    var css = TRASH_CSS + cardCss();\r\n    style.textContent = css;\r\n    root.appendChild(style);\r\n  }\r\n\r\n  // The wishlist bar's Share button drives the app's share control, so the\r\n  // app's own button stays in the page (clickable) but visually hidden.\r\n  function hideAppShareButton(containerRoot) {\r\n    if (containerRoot.querySelector('style[data-wl-share-hidden]')) return;\r\n    var style = document.createElement('style');\r\n    style.setAttribute('data-wl-share-hidden', '');\r\n    style.textContent =\r\n      'ooo-wl-page-content-info[template=\"ooo-wl-page-share-wishlist\"]{' +\r\n      'position:absolute!important;width:1px!important;height:1px!important;' +\r\n      'overflow:hidden!important;clip-path:inset(50%)!important;' +\r\n      'white-space:nowrap!important;margin:0!important;padding:0!important;}';\r\n    containerRoot.appendChild(style);\r\n  }\r\n\r\n  // Hover animation for the share button, injected into the share element's OWN\r\n  // shadow root (where the button lives). On hover the letters/icon gently pulse\r\n  // between gold tones (dark gold -> light cream -> back). currentColor +\r\n  // text-fill-color cover whichever the app uses to paint the glyphs.\r\n  // Background/border stay untouched.\r\n  var SHARE_BUTTON_CSS =\r\n    'ooo-wl-page-share-button{transition:color .4s ease;}' +\r\n    'ooo-wl-page-share-button:hover{animation:skbShareGlow 2.8s ease-in-out infinite;}' +\r\n    '@keyframes skbShareGlow{' +\r\n    '0%,100%{color:#bb9d7b;-webkit-text-fill-color:#bb9d7b;}' +\r\n    '50%{color:#f0e2c4;-webkit-text-fill-color:#f0e2c4;}}';\r\n\r\n  // \"Link copied!\" confirmation: the app renders it as a <span> with a green\r\n  // background (rgb(24,113,48)) and white text/tick, only in the copied state\r\n  // (that span holds the .ooo-wl-button-icon--tick icon). Recolor its background\r\n  // to the brand gold; text stays white. :has() targets only the copied span so\r\n  // the normal \"Share your wishlist\" state is untouched.\r\n  // color + -webkit-text-fill-color both forced white: the hover glow animates\r\n  // text-fill on the button and it inherits into this span, so without pinning\r\n  // text-fill here the \"Link copied!\" text would pulse gold over the gold bg.\r\n  var SHARE_COPIED_CSS =\r\n    'ooo-wl-copy-button button span:has(.ooo-wl-button-icon--tick){' +\r\n    'background:var(--color-accent,#bb9d7b)!important;' +\r\n    'background-color:var(--color-accent,#bb9d7b)!important;' +\r\n    'color:#fff!important;-webkit-text-fill-color:#fff!important;}';\r\n\r\n  function injectShareStyle(root, css) {\r\n    if (!root || root.querySelector('style[data-wl-share-style]')) return;\r\n    var style = document.createElement('style');\r\n    style.setAttribute('data-wl-share-style', '');\r\n    style.textContent = css;\r\n    root.appendChild(style);\r\n  }\r\n\r\n  function styleShareButton(containerRoot) {\r\n    var share = containerRoot.querySelector('ooo-wl-page-content-info[template=\"ooo-wl-page-share-wishlist\"]');\r\n    if (!share || !share.shadowRoot) return;\r\n    var css = SHARE_BUTTON_CSS + SHARE_COPIED_CSS;\r\n    injectShareStyle(share.shadowRoot, css);\r\n    // The copied-confirmation span may sit in a nested shadow root \u2014 inject there too.\r\n    var btn = share.shadowRoot.querySelector('ooo-wl-page-share-button');\r\n    if (btn && btn.shadowRoot) injectShareStyle(btn.shadowRoot, css);\r\n    var scope = btn && btn.shadowRoot ? btn.shadowRoot : share.shadowRoot;\r\n    var copy = scope.querySelector('ooo-wl-copy-button');\r\n    if (copy && copy.shadowRoot) injectShareStyle(copy.shadowRoot, css);\r\n  }\r\n\r\n  // Empty state: hidden (custom.css also collapses it via the app's variables,\r\n  // so it never paints). The wishlist bar carries the page's message.\r\n  var EMPTY_STATE_CSS =\r\n    '.ooo-wl-page-empty__title,.ooo-wl-page-empty__description{color:var(--color-text,#fff)!important;}' +\r\n    '.ooo-wl-page-empty{display:none!important;}';\r\n\r\n  function styleEmptyState(containerRoot) {\r\n    containerRoot.querySelectorAll('ooo-wl-page-content-info').forEach(function (info) {\r\n      var root = info.shadowRoot;\r\n      if (!root || root.querySelector('style[data-wl-empty-style]')) return;\r\n      var style = document.createElement('style');\r\n      style.setAttribute('data-wl-empty-style', '');\r\n      style.textContent = EMPTY_STATE_CSS;\r\n      root.appendChild(style);\r\n    });\r\n  }\r\n\r\n  function injectAll() {\r\n    var container = document.querySelector('ooo-wl-page-container');\r\n    if (!container || !container.shadowRoot) return false;\r\n    hideAppShareButton(container.shadowRoot);\r\n    styleShareButton(container.shadowRoot);\r\n    styleEmptyState(container.shadowRoot);\r\n    container.shadowRoot.querySelectorAll('ooo-wl-page-product-card').forEach(function (card) {\r\n      if (card.shadowRoot) injectInto(card.shadowRoot);\r\n    });\r\n    return true;\r\n  }\r\n\r\n  var observing = false;\r\n  var observed = null;\r\n  function ensureObserver() {\r\n    var container = document.querySelector('ooo-wl-page-container');\r\n    if (observing && container === observed) return;\r\n    if (!container || !container.shadowRoot || !('MutationObserver' in window)) return;\r\n    observing = true;\r\n    observed = container;\r\n    // Re-inject when cards are (re)rendered, e.g. on pagination. Observing the\r\n    // container's shadow root only \u2014 a card's own shadow root is a separate\r\n    // tree, so our injected <style> never retriggers this.\r\n    new MutationObserver(injectAll).observe(container.shadowRoot, {\r\n      childList: true,\r\n      subtree: true,\r\n    });\r\n    injectAll();\r\n  }\r\n\r\n  // Cards render asynchronously; poll until the container shadow root exists,\r\n  // then hand off to the observer. Give up after ~12s.\r\n  var tries = 0;\r\n  var timer;\r\n  function startPolling() {\r\n    clearInterval(timer);\r\n    tries = 0;\r\n    timer = setInterval(function () {\r\n      injectAll();\r\n      ensureObserver();\r\n      if ((observing && observed === document.querySelector('ooo-wl-page-container')) || ++tries > 48) clearInterval(timer);\r\n    }, 250);\r\n  }\r\n  startPolling();\r\n  document.addEventListener('skb:wl-remounted', startPolling); // listing re-mounted by the wishlist bar\r\n})();\r\n\r\n/* ============================================================\r\n   LOAD MORE PAGINATION\r\n   ============================================================ */\r\n(function () {\r\n  // Use event delegation so re-renders from facet filtering don't need re-init\r\n  document.addEventListener('click', function (e) {\r\n    var btn = e.target.closest('[data-load-more-btn]');\r\n    if (!btn) return;\r\n\r\n    var nextUrl = btn.getAttribute('data-next-url');\r\n    if (!nextUrl || btn.disabled) return;\r\n\r\n    btn.disabled = true;\r\n\r\n    fetch(nextUrl)\r\n      .then(function (res) { return res.text(); })\r\n      .then(function (html) {\r\n        var parser = new DOMParser();\r\n        var doc = parser.parseFromString(html, 'text/html');\r\n        var listId = btn.getAttribute('data-product-list-id');\r\n        var targetList = document.getElementById(listId);\r\n        var sourceList = doc.getElementById(listId);\r\n\r\n        if (!targetList || !sourceList) return;\r\n\r\n        Array.from(sourceList.children).forEach(function (child) {\r\n          targetList.appendChild(document.importNode(child, true));\r\n        });\r\n\r\n        var newBtn = doc.querySelector('[data-load-more-btn]');\r\n        var wrapper = btn.closest('[data-load-more-wrapper]');\r\n\r\n        if (newBtn) {\r\n          var newNextUrl = newBtn.getAttribute('data-next-url');\r\n          var newCount = newBtn.getAttribute('data-current-count');\r\n          btn.setAttribute('data-next-url', newNextUrl);\r\n          btn.setAttribute('data-current-count', newCount);\r\n          btn.disabled = false;\r\n\r\n          var showCount = btn.getAttribute('data-show-count') === 'true';\r\n          if (showCount && wrapper) {\r\n            var countEl = wrapper.querySelector('[data-load-more-count]');\r\n            if (countEl) {\r\n              var total = btn.getAttribute('data-total-count');\r\n              // Translated sentence with __shown__/__total__ sentinels, injected by\r\n              // main-collection.liquid so no English is hard-coded here. If it is\r\n              // missing, clear the text rather than leaving the previous page's\r\n              // count on screen, which would read as a wrong number.\r\n              var template = btn.getAttribute('data-count-template');\r\n              countEl.textContent = template\r\n                ? template.replace('__shown__', newCount).replace('__total__', total)\r\n                : '';\r\n            }\r\n          }\r\n        } else {\r\n          // No more pages \u2014 hide the wrapper\r\n          if (wrapper) wrapper.style.display = 'none';\r\n        }\r\n      })\r\n      .catch(function () {\r\n        btn.disabled = false;\r\n      });\r\n  });\r\n})();\r\n\r\n// === Wishlist buttons: remove the white load flash (KAN-31 1d/3b) ===\r\n// Both <ooo-wl-product-page-button> (product page) and <ooo-wl-product-card-button>\r\n// (collection/product cards) render their real <button> inside a shadow root\r\n// whose stylesheet is an async <link>; for one frame the button paints with the\r\n// browser's default white background before the styled state applies. custom.css\r\n// keeps the wrapper invisible until we add .skb-wl-ready, which we do once that\r\n// shadow stylesheet has actually loaded \u2014 so it reveals already styled.\r\n(function () {\r\n  var TAGS = ['ooo-wl-product-page-button', 'ooo-wl-product-card-button'];\r\n  var SELECTOR = TAGS.join(',');\r\n\r\n  function revealWhenStyled(el) {\r\n    if (el.__skbFoucDone) return;\r\n    var root = el.shadowRoot;\r\n    if (!root) return; // not upgraded yet \u2014 a later scan will catch it\r\n    el.__skbFoucDone = true;\r\n\r\n    var reveal = function () {\r\n      el.classList.add('skb-wl-ready');\r\n    };\r\n    var link = root.querySelector('link[rel=\"stylesheet\"]');\r\n\r\n    if (!link || link.sheet) {\r\n      reveal(); // no external sheet, or it's already applied\r\n    } else {\r\n      link.addEventListener('load', reveal, { once: true });\r\n      link.addEventListener('error', reveal, { once: true });\r\n      setTimeout(reveal, 4000); // safety net: never stay hidden for good\r\n    }\r\n  }\r\n\r\n  function scan() {\r\n    document.querySelectorAll(SELECTOR).forEach(revealWhenStyled);\r\n  }\r\n\r\n  function init() {\r\n    scan();\r\n    if (window.customElements && customElements.whenDefined) {\r\n      TAGS.forEach(function (t) {\r\n        customElements\r\n          .whenDefined(t)\r\n          .then(scan)\r\n          .catch(function () {});\r\n      });\r\n    }\r\n    // Global fail-safe: if the app never upgrades the elements (e.g. it fails to\r\n    // load), reveal anyway after 5s so the buttons are never hidden permanently.\r\n    setTimeout(function () {\r\n      document.querySelectorAll(SELECTOR).forEach(function (el) {\r\n        el.classList.add('skb-wl-ready');\r\n      });\r\n    }, 5000);\r\n    // The product info block re-renders on variant change, recreating the\r\n    // button \u2014 re-scan (debounced) so the new instance is handled too.\r\n    if ('MutationObserver' in window) {\r\n      var t;\r\n      new MutationObserver(function () {\r\n        clearTimeout(t);\r\n        t = setTimeout(scan, 50);\r\n      }).observe(document.body, { childList: true, subtree: true });\r\n    }\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    init();\r\n  }\r\n})();\r\n\r\n// === Wishlist page bar (sections/ab-wishlist-bar.liquid) ===\r\n// Share: logged in -> clicks the app's copy button + shows a toast;\r\n// logged out -> the theme modal opens via aria-controls.\r\n// Live refresh: the app fires ooo-wishlist:product-added/-removed when the\r\n// wishlist changes elsewhere (e.g. cart drawer); we re-mount the listing so it\r\n// fetches again. Changes made inside the listing are left to the app.\r\n(function () {\r\n  var bar = document.querySelector('[data-ab-wl-bar]');\r\n  if (!bar) return;\r\n  var shareBtn = bar.querySelector('[data-ab-wl-share]');\r\n  var toast = bar.querySelector('[data-ab-wl-toast]');\r\n  var SHARE_SEL = 'ooo-wl-page-content-info[template=\"ooo-wl-page-share-wishlist\"]';\r\n\r\n  function container() {\r\n    return document.querySelector('ooo-wl-page-container');\r\n  }\r\n\r\n  // Depth-first search through nested open shadow roots.\r\n  function deepFind(root, selector) {\r\n    if (!root) return null;\r\n    var hit = root.querySelector(selector);\r\n    if (hit) return hit;\r\n    var all = root.querySelectorAll('*');\r\n    for (var i = 0; i < all.length; i++) {\r\n      if (all[i].shadowRoot) {\r\n        hit = deepFind(all[i].shadowRoot, selector);\r\n        if (hit) return hit;\r\n      }\r\n    }\r\n    return null;\r\n  }\r\n\r\n  function appShare() {\r\n    var c = container();\r\n    return c && c.shadowRoot ? c.shadowRoot.querySelector(SHARE_SEL) : null;\r\n  }\r\n\r\n  function syncShare() {\r\n    if (shareBtn) shareBtn.hidden = !appShare();\r\n  }\r\n\r\n  var toastTimer;\r\n  function showToast(text) {\r\n    if (!toast) return;\r\n    toast.textContent = text;\r\n    toast.classList.add('is-visible');\r\n    clearTimeout(toastTimer);\r\n    toastTimer = setTimeout(function () {\r\n      toast.classList.remove('is-visible');\r\n    }, 2600);\r\n  }\r\n\r\n  if (shareBtn) {\r\n    shareBtn.addEventListener('click', function () {\r\n      if (shareBtn.hasAttribute('aria-controls')) return;\r\n      var share = appShare();\r\n      var root = share && share.shadowRoot;\r\n      var copy = root ? deepFind(root, 'ooo-wl-copy-button') : null;\r\n      if (copy) {\r\n        var copyTarget = (copy.shadowRoot && copy.shadowRoot.querySelector('button')) || copy.querySelector('button') || copy;\r\n        copyTarget.click();\r\n        showToast(toast.getAttribute('data-copied'));\r\n        return;\r\n      }\r\n      showToast(toast.getAttribute('data-failed'));\r\n    });\r\n  }\r\n\r\n  // Keep the Share button in step with the listing (empty <-> has products).\r\n  var watched = null;\r\n  var mo = 'MutationObserver' in window ? new MutationObserver(syncShare) : null;\r\n  function watch() {\r\n    var c = container();\r\n    if (c && c.shadowRoot && c !== watched && mo) {\r\n      mo.disconnect();\r\n      mo.observe(c.shadowRoot, { childList: true, subtree: true });\r\n      watched = c;\r\n    }\r\n    syncShare();\r\n  }\r\n  // The app renders asynchronously: poll briefly until its shadow root exists.\r\n  var poll;\r\n  function startWatching() {\r\n    var tries = 0;\r\n    clearInterval(poll);\r\n    poll = setInterval(function () {\r\n      watch();\r\n      if (watched === container() || ++tries > 60) clearInterval(poll);\r\n    }, 250);\r\n  }\r\n  startWatching();\r\n\r\n  var refreshTimer;\r\n  function remount() {\r\n    var c = container();\r\n    if (!c) return;\r\n    c.replaceWith(c.cloneNode(false)); // the app rebuilds the listing on connect\r\n    document.dispatchEvent(new CustomEvent('skb:wl-remounted'));\r\n    startWatching();\r\n  }\r\n  function onChange(e) {\r\n    var c = container();\r\n    var path = e.composedPath ? e.composedPath() : [];\r\n    if (c && path.indexOf(c) !== -1) return; // changed from the listing itself\r\n    clearTimeout(refreshTimer);\r\n    refreshTimer = setTimeout(remount, 600); // give the app time to save first\r\n  }\r\n  ['ooo-wishlist:product-added', 'ooo-wishlist:product-removed'].forEach(function (name) {\r\n    document.addEventListener(name, onChange);\r\n  });\r\n})();\r\n\r\n// === Product page: place the wishlist icon beside ADD TO CART (KAN-31 item 5) ===\r\n// The Wishlist Power app block renders as its own stacked block below the buy\r\n// buttons. The brief wants the (icon-only) button on the SAME ROW as ADD TO\r\n// CART, to its right. Rather than fight the block layout with fragile negative\r\n// margins, we move the app's <ooo-wl-access-button> INTO <buy-buttons> so they\r\n// share one flex row (custom.css styles .buy-buttons--with-wishlist). Moving the\r\n// node preserves the app element (variant handling, added-state) intact. We\r\n// re-apply after Prestige re-renders the product info on variant change.\r\n(function () {\r\n  var SECTION = '.shopify-section--main-product';\r\n\r\n  function place() {\r\n    var section = document.querySelector(SECTION);\r\n    if (!section) return;\r\n    var buyButtons = section.querySelector('buy-buttons');\r\n    var wishlist = section.querySelector('ooo-wl-access-button');\r\n    if (!buyButtons || !wishlist || buyButtons.contains(wishlist)) return;\r\n    buyButtons.appendChild(wishlist);\r\n    buyButtons.classList.add('buy-buttons--with-wishlist');\r\n  }\r\n\r\n  function init() {\r\n    // PERF: bail on any page that has no product section. Without this the interval\r\n    // below still scheduled 41 main-thread wakeups over 10 seconds on every home,\r\n    // collection, cart, search and article page, each one calling place() only for it\r\n    // to return on its first line.\r\n    //\r\n    // Provably the same behaviour: place() already opens with this exact query and\r\n    // returns when it misses, and the MutationObserver further down is guarded by the\r\n    // same check, so on a page without the section nothing happened before either.\r\n    // Sections are server-rendered and init runs at DOMContentLoaded, and nothing here\r\n    // listens for shopify:section:load, so the section cannot appear after this point.\r\n    if (!document.querySelector(SECTION)) return;\r\n\r\n    place();\r\n    // App + Prestige render asynchronously; retry briefly until both exist.\r\n    var tries = 0;\r\n    var timer = setInterval(function () {\r\n      place();\r\n      if (++tries > 40) clearInterval(timer);\r\n    }, 250);\r\n\r\n    // Prestige rebuilds the product info on variant change, which resets the\r\n    // node back to its own block, so this has to keep re-placing it.\r\n    //\r\n    // KAN-192: observe document.body, not the section. theme.js replaces the whole\r\n    // product section on a variant change, so a node captured here is detached the\r\n    // moment that happens: the observer stays alive and keeps firing against a tree\r\n    // nobody is looking at, and the button never comes back. document.body outlives\r\n    // every re-render, and place() re-queries the section each time anyway, so it\r\n    // always works on the current one.\r\n    //\r\n    // Coalesced with requestAnimationFrame rather than a timeout: place()'s own\r\n    // appendChild is a mutation inside the observed tree, and the next pass sees the\r\n    // button already inside <buy-buttons> and returns on its guard, so the cascade\r\n    // stops after one extra frame.\r\n    if ('MutationObserver' in window) {\r\n      var scheduled = false;\r\n      new MutationObserver(function () {\r\n        if (scheduled) return;\r\n        scheduled = true;\r\n        requestAnimationFrame(function () {\r\n          scheduled = false;\r\n          place();\r\n        });\r\n      }).observe(document.body, { childList: true, subtree: true });\r\n    }\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    init();\r\n  }\r\n})();\r\n\r\n// === Header: show the wishlist link only when the Wishlist Power app is on ===\r\n// The header bookmark is hardcoded in the theme (sections/header.liquid), so it\r\n// would otherwise show even when the merchant disables the Wishlist Power app\r\n// embed. custom.css hides .header__wishlist-link by DEFAULT; we add .skb-wl-active\r\n// only once the app's setup embed has loaded (window.Maestrooo). So when the\r\n// embed is OFF the icon never appears (no flash); when it's ON the icon reveals\r\n// as soon as the app loads. Hidden-by-default avoids the show-then-hide flash.\r\n(function () {\r\n  var link = document.querySelector('.header__wishlist-link');\r\n  if (!link) return;\r\n  // Toggle the class on the <ooo-wl-access-button> WRAPPER (the flex child of\r\n  // the header nav) so hiding it leaves no empty gap; fall back to the link.\r\n  var wrap = link.closest('ooo-wl-access-button') || link;\r\n\r\n  function reveal() {\r\n    wrap.classList.add('skb-wl-active');\r\n  }\r\n\r\n  if (window.Maestrooo) {\r\n    reveal();\r\n    return;\r\n  }\r\n  // Poll briefly for the app; if it never loads, the embed is off \u2192 stays hidden.\r\n  var tries = 0;\r\n  var timer = setInterval(function () {\r\n    if (window.Maestrooo) {\r\n      reveal();\r\n      clearInterval(timer);\r\n    } else if (++tries >= 40) {\r\n      clearInterval(timer); // ~10s with no app \u2192 leave hidden\r\n    }\r\n  }, 250);\r\n})();\r\n\r\n// === Rich Text: \"Read more\" expandable text (KAN-113) ===\r\n// Opt-in per section (sections/rich-text.liquid). The content is collapsed to a\r\n// set height with a fade; we reveal the toggle + fade ONLY when the content\r\n// actually overflows that height, then toggle .is-expanded on click.\r\n(function () {\r\n  function initReadMore(el) {\r\n    if (el.__rtReadMore) return;\r\n    el.__rtReadMore = true;\r\n\r\n    var content = el.querySelector('.rt-readmore__content');\r\n    var toggle = el.querySelector('.rt-readmore__toggle');\r\n    if (!content || !toggle) return;\r\n\r\n    var moreLabel = el.getAttribute('data-more') || 'Read more';\r\n    var lessLabel = el.getAttribute('data-less') || 'Read less';\r\n\r\n    function collapsedHeight() {\r\n      return parseFloat(getComputedStyle(el).getPropertyValue('--rt-collapsed-height')) || 160;\r\n    }\r\n\r\n    // Only show the toggle/fade when the content is taller than the collapsed\r\n    // height; shorter content shows in full (max-height doesn't clip it).\r\n    function measure() {\r\n      var overflowing = content.scrollHeight > collapsedHeight() + 4;\r\n      el.classList.toggle('has-overflow', overflowing);\r\n      if (overflowing) {\r\n        toggle.hidden = false;\r\n      } else {\r\n        toggle.hidden = true;\r\n        el.classList.remove('is-expanded');\r\n      }\r\n    }\r\n\r\n    toggle.addEventListener('click', function () {\r\n      var expanded = el.classList.toggle('is-expanded');\r\n      toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');\r\n      toggle.textContent = expanded ? lessLabel : moreLabel;\r\n    });\r\n\r\n    measure();\r\n    var t;\r\n    window.addEventListener('resize', function () {\r\n      clearTimeout(t);\r\n      t = setTimeout(measure, 150);\r\n    });\r\n    // Re-measure once webfonts finish loading (line height can shift).\r\n    if (document.fonts && document.fonts.ready) document.fonts.ready.then(measure);\r\n  }\r\n\r\n  function init() {\r\n    document.querySelectorAll('[data-rt-readmore]').forEach(initReadMore);\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    init();\r\n  }\r\n  // Re-init when the section is (re)rendered in the theme editor.\r\n  document.addEventListener('shopify:section:load', init);\r\n})();\r\n\r\n// === Collection quiz \u2014 progressive filter wizard (sections/collection-quiz.liquid) ===\r\n// One question is visible at a time. Picking an answer merges its filter\r\n// query params into the collection's current filters and dispatches the\r\n// same `facet:update` event the native facets engine listens for\r\n// (assets/theme.js), so results refresh through the existing AJAX/Section\r\n// Rendering API path \u2014 no full page reload. An answer left without filter\r\n// params (\"show me everything\") just advances to the next question.\r\n(function () {\r\n  if (window.customElements.get('collection-quiz')) return;\r\n\r\n  // Question block IDs already answered. Deliberately kept in module scope\r\n  // rather than on the element: theme.js's facet:update handler swaps the\r\n  // whole collection section via replaceChildren (Section Rendering API), so\r\n  // this element is destroyed and rebuilt from server markup on every filter\r\n  // \u2014 and that markup always flags the FIRST question active. Holding this\r\n  // out here lets the rebuilt element restore the right question, while a\r\n  // genuine page load re-runs this script and starts the quiz over.\r\n  //\r\n  // Tracked by block ID, not by index: the section drops answers (and whole\r\n  // questions) whose filters would return no products, so a question's\r\n  // position shifts between renders and an index would point at the wrong one.\r\n  var answeredQuestionIds = [];\r\n\r\n  // Same lookup assets/theme.js's facet:update handler relies on\r\n  // (`shopifySection.querySelector(\".collection\")`) \u2014 the product grid\r\n  // section always has this element, whether or not filters are enabled.\r\n  function getMainCollectionSectionId() {\r\n    var el = document.querySelector('.collection');\r\n    var section = el && el.closest('.shopify-section');\r\n    return section && section.id.replace('shopify-section-', '');\r\n  }\r\n\r\n  // After every facet update theme.js scrolls the product grid to the top of\r\n  // the viewport (`.collection`.scrollIntoView). That's right for the filter\r\n  // bar, but for the quiz it pushes the next question off-screen. Swallow that\r\n  // one scroll by patching scrollIntoView just for the grid element, for the\r\n  // duration of the update \u2014 filter-bar clicks never go through here, so their\r\n  // scroll behaviour is untouched.\r\n  function suppressNextGridScroll() {\r\n    if (Element.prototype.scrollIntoView.__quizPatched) return;\r\n\r\n    var original = Element.prototype.scrollIntoView;\r\n\r\n    function restore() {\r\n      Element.prototype.scrollIntoView = original;\r\n    }\r\n\r\n    function patched() {\r\n      if (this.classList && this.classList.contains('collection')) {\r\n        restore();\r\n        return;\r\n      }\r\n      return original.apply(this, arguments);\r\n    }\r\n\r\n    patched.__quizPatched = true;\r\n    Element.prototype.scrollIntoView = patched;\r\n    // Fail-safe: never leave the prototype patched if the fetch fails or a\r\n    // future theme version stops scrolling here.\r\n    setTimeout(restore, 2000);\r\n  }\r\n\r\n  function hasActiveFilters() {\r\n    var params = new URLSearchParams(window.location.search);\r\n    var found = false;\r\n    params.forEach(function (value, key) {\r\n      if (key.indexOf('filter.') === 0) found = true;\r\n    });\r\n    return found;\r\n  }\r\n\r\n  window.customElements.define('collection-quiz', class extends HTMLElement {\r\n    connectedCallback() {\r\n      // \"Clear all\" (and removing the last active filter chip) means the visitor\r\n      // is starting over, so the quiz has to go back to question one. Those go\r\n      // through the same AJAX section swap as everything else \u2014 there's no page\r\n      // load to reset on \u2014 so detect the empty-filter state from the URL, which\r\n      // theme.js has already updated via history.replaceState by this point.\r\n      if (!hasActiveFilters()) {\r\n        answeredQuestionIds = [];\r\n      }\r\n\r\n      this.showCurrentStep();\r\n      this.addEventListener('click', this.onAnswerClick.bind(this));\r\n    }\r\n\r\n    showCurrentStep() {\r\n      var questions = Array.prototype.slice.call(this.querySelectorAll('.collection-quiz__question'));\r\n      var next = null;\r\n\r\n      for (var i = 0; i < questions.length; i++) {\r\n        if (answeredQuestionIds.indexOf(questions[i].dataset.questionId) === -1) {\r\n          next = questions[i];\r\n          break;\r\n        }\r\n      }\r\n\r\n      questions.forEach(function (question) {\r\n        question.classList.toggle('is-active', question === next);\r\n      });\r\n\r\n      // Nothing left unanswered \u2014 hide the quiz so the filtered grid takes over.\r\n      this.classList.toggle('is-complete', next === null);\r\n    }\r\n\r\n    onAnswerClick(event) {\r\n      // KAN-142: the answers row is a draggable carousel, and the theme cancels\r\n      // the click that ends a drag rather than stopping it propagating. Without\r\n      // this guard, dragging to the next pair of answers would also pick whichever\r\n      // answer the drag happened to start on.\r\n      if (event.defaultPrevented) return;\r\n\r\n      var btn = event.target.closest('.collection-quiz__answer');\r\n      if (!btn) return;\r\n\r\n      // Mark answered before dispatching: the section may be replaced as soon\r\n      // as the fetch resolves, and the fresh element reads this on connect.\r\n      var question = btn.closest('.collection-quiz__question');\r\n      var questionId = question && question.dataset.questionId;\r\n      if (questionId && answeredQuestionIds.indexOf(questionId) === -1) {\r\n        answeredQuestionIds.push(questionId);\r\n      }\r\n\r\n      // The skip control ships with empty filter params, so it falls through the\r\n      // \"show me everything\" path below on its own: mark the question answered,\r\n      // move to the next, touch no filters.\r\n      var answerParams = (btn.dataset.filterParams || '').trim();\r\n      var sectionId = answerParams ? getMainCollectionSectionId() : null;\r\n\r\n      if (!sectionId) {\r\n        // \"Show me everything\" answer (or no grid to target): nothing to\r\n        // filter, just move to the next question in place.\r\n        this.showCurrentStep();\r\n        return;\r\n      }\r\n\r\n      var params = new URLSearchParams(window.location.search);\r\n      params.delete('section_id');\r\n      new URLSearchParams(answerParams).forEach(function (value, key) {\r\n        params.append(key, value);\r\n      });\r\n      params.set('section_id', sectionId);\r\n\r\n      var url = new URL(window.location.pathname, window.location.origin);\r\n      url.search = params.toString();\r\n\r\n      suppressNextGridScroll();\r\n      btn.dispatchEvent(new CustomEvent('facet:update', { bubbles: true, detail: { url: url } }));\r\n    }\r\n  });\r\n})();\r\n\r\n// === Collection quiz \u2014 animate the answer carousel when an arrow is used ===\r\n// The theme already asks for a smooth scroll (ScrollCarousel.select passes\r\n// behavior: \"smooth\"), but scroll-snap-type: mandatory makes the browser discard\r\n// the animation and jump straight to the snap position. The theme hits the same\r\n// problem on mouse drags and works around it by turning snapping off for the\r\n// duration; the arrow path never got that treatment.\r\n//\r\n// Hooking the carousel's own carousel:select rather than the buttons means this\r\n// covers any programmatic move, not just a click on the arrow. The event does not\r\n// bubble, so it is caught in the capture phase \u2014 that still fires for ancestors.\r\n(function () {\r\n  var SNAP_RESTORE_FALLBACK_MS = 700;\r\n\r\n  document.addEventListener(\r\n    'carousel:select',\r\n    function (event) {\r\n      var carousel = event.target;\r\n      if (!carousel.classList || !carousel.classList.contains('collection-quiz__answers')) return;\r\n\r\n      carousel.style.setProperty('scroll-snap-type', 'none');\r\n\r\n      var restored = false;\r\n      function restoreSnap() {\r\n        if (restored) return;\r\n        restored = true;\r\n        carousel.style.removeProperty('scroll-snap-type');\r\n      }\r\n\r\n      // scrollend is the real signal; the timeout is a backstop so snapping can\r\n      // never be left switched off if the event is missed or the scroll is\r\n      // interrupted mid-flight.\r\n      carousel.addEventListener('scrollend', restoreSnap, { once: true });\r\n      setTimeout(restoreSnap, SNAP_RESTORE_FALLBACK_MS);\r\n    },\r\n    true\r\n  );\r\n})();\r\n\r\n\r\n// === LimeSpot: translate the strings the app writes into its own widgets (KAN-182) ===\r\n// LimeSpot renders box titles and every label inside its widgets from its own Designer,\r\n// and the app has no translation feature, so all of it stayed English on every market.\r\n// KAN-170 is about getting app content to where Shopify's translation layer can reach it.\r\n//\r\n// This replaces text and nothing else. The reverted commit earlier in this branch tried\r\n// rendering our own heading in a real section and hiding LimeSpot's with CSS; on the\r\n// preview their box laid itself out on top of the words, because their stylesheet and the\r\n// theme's .section-header width cap interact in ways reading the repo does not predict.\r\n// Their elements, their layout, their styling - only the words change, so in English the\r\n// page is pixel-identical.\r\n//\r\n// Every replacement is keyed by the English the app currently renders, declared in\r\n// js-variables.liquid. Two consequences worth knowing: the store's twelve boxes are\r\n// covered without having to know each one's internal box type, and a title someone edits\r\n// in the Designer simply stops being translated rather than being overwritten with a\r\n// translation of different words.\r\n//\r\n// Two kinds of rule, because not every string is fixed:\r\n//   map      - exact match, for labels that never vary.\r\n//   patterns - a regex whose capture groups come back as [1], [2] in the replacement,\r\n//              for the labels that carry a number or a product name. Kai's request\r\n//              covered \"the rest of the section\", and the counted labels are the ones a\r\n//              plain lookup table silently misses: the bundle button reads\r\n//              \"Add Selected to Cart\" with nothing chosen and \"Add 3 items to Cart:\"\r\n//              once something is, and the mobile bundle has its own \"Buy all 3 items\".\r\n// Exact matches are tried first, so \"Add bundle to cart\" is taken by the map and never\r\n// falls through to the \"Add (.+) to cart\" pattern that covers the product cards.\r\n//\r\n// Read off the live DOM rather than guessed - captured from a product page and from the\r\n// cart drawer, which is a different box (CrossSell, slider layout) with a whole set of\r\n// slider controls the product page does not render:\r\n//   <h3 class=\"ls-box-title\">Complete the Look</h3>\r\n//   <span class=\"ls-bundle-price-text\">Total Price:</span>\r\n//   <button class=\"ls-bundle-add-to-cart\" aria-label=\"Add bundle to cart\">Add Selected to Cart</button>\r\n//   <span class=\"ls-bundle-mobile-compact__button-text\">Buy all 3 items</span>\r\n//   <a class=\"ls-bundle-add-to-cart-select\">Add 3 items to Cart:<span>...</span></a>\r\n//   <div class=\"ls-custom-flag\">New</div>\r\n//   <span class=\"ls-sr-only\">Brand:</span>\r\n//   <input class=\"ls-checkbox\" aria-label=\"Include PRODUCT in bundle\">\r\n//   <button class=\"ls-button--select ls-add-to-cart\" aria-label=\"Add PRODUCT to cart\">\r\n//   <div class=\"ls-gallery\" aria-label=\"Product gallery\">\r\n//   <div class=\"ls-slide-show-dots\" aria-label=\"Slide 1 of 6\">\r\n//   <button class=\"ls-slide-show-dots__item\" aria-label=\"Go to slide 2\">\r\n//   <button class=\"ls-slide-show-arrows__button\" aria-label=\"Next slide\">\r\n//   <button class=\"variant-arrow\" aria-label=\"Next variants\">\r\n//\r\n// The aria-labels are worth as much as the visible text here, and on the product page\r\n// they are worth more: custom.css deliberately collapses the Related and RecentViews\r\n// add-to-cart buttons to a 35px \"+\" icon with font-size 0, so the only label a screen\r\n// reader has left on those cards is the aria-label.\r\n//\r\n// The uppercase in Kai's ticket is text-transform in LimeSpot's stylesheet, not content.\r\n//\r\n// Still out of reach, and not fixable from the theme: bundleThisItemLabel, which LimeSpot\r\n// injects as a CSS custom property rather than as text, and the \"{{price}}\" title on the\r\n// cart drawer box, which is an unresolved template token in their own Designer config -\r\n// that one is a fix in the app's panel.\r\n(function () {\r\n  var rules =\r\n    (window.themeVariables &&\r\n      window.themeVariables.strings &&\r\n      window.themeVariables.strings.limespotStrings) ||\r\n    null;\r\n  if (!rules || !rules.length) return;\r\n\r\n  // [1], [2] ... stand for the pattern's capture groups, so a product name or an item\r\n  // count survives translation while the words around it change. Done with split/join\r\n  // rather than a replacement regex, so a translation containing a dollar sign cannot be\r\n  // read as a replacement pattern.\r\n  function expand(template, match) {\r\n    var out = template;\r\n    for (var n = 1; n < match.length; n++) {\r\n      out = out.split('[' + n + ']').join(match[n] === undefined ? '' : match[n]);\r\n    }\r\n    return out;\r\n  }\r\n\r\n  // Patterns arrive as source strings and are compiled once, on first use, rather than\r\n  // rebuilt per node on every pass.\r\n  function compile(list) {\r\n    var out = [];\r\n    for (var i = 0; i < list.length; i++) {\r\n      out.push({ re: new RegExp(list[i].re), to: list[i].to });\r\n    }\r\n    return out;\r\n  }\r\n\r\n  // The replacement for a string, or null when nothing applies.\r\n  function translate(value, map, patterns) {\r\n    var current = value.trim();\r\n    if (!current) return null;\r\n\r\n    if (map) {\r\n      var mapped = map[current];\r\n      if (mapped) return mapped === current ? null : mapped;\r\n    }\r\n\r\n    if (patterns) {\r\n      for (var i = 0; i < patterns.length; i++) {\r\n        var m = current.match(patterns[i].re);\r\n        if (m) {\r\n          var next = expand(patterns[i].to, m);\r\n          return next === current ? null : next;\r\n        }\r\n      }\r\n    }\r\n\r\n    return null;\r\n  }\r\n\r\n  function apply() {\r\n    // One cheap query before fourteen document-wide ones. Watching aria-label means a\r\n    // pass can be scheduled by any carousel on the page, including the theme's own, so\r\n    // pages and moments with no LimeSpot widget in them cost a single failed lookup\r\n    // instead of a full sweep. Every element these rules target sits inside a\r\n    // limespot-box - the cart drawer box included, that is its root element too.\r\n    if (!document.querySelector('limespot-box')) return;\r\n\r\n    for (var i = 0; i < rules.length; i++) {\r\n      var rule = rules[i];\r\n\r\n      if (rule.patterns && !rule.compiledText) rule.compiledText = compile(rule.patterns);\r\n      if (rule.ariaPatterns && !rule.compiledAria) rule.compiledAria = compile(rule.ariaPatterns);\r\n\r\n      var nodes = document.querySelectorAll(rule.selector);\r\n\r\n      for (var j = 0; j < nodes.length; j++) {\r\n        var node = nodes[j];\r\n\r\n        // Write to the text node, not to the element's textContent. Some of these carry\r\n        // element children alongside their label - .ls-bundle-add-to-cart-select wraps a\r\n        // nested span holding the price - and assigning textContent would delete that\r\n        // markup. The whitespace around the label is put back untouched, because\r\n        // LimeSpot's sr-only spans pad their text with it.\r\n        if (rule.map || rule.compiledText) {\r\n          var children = node.childNodes;\r\n\r\n          for (var k = 0; k < children.length; k++) {\r\n            var child = children[k];\r\n            if (child.nodeType !== 3) continue;\r\n\r\n            var raw = child.nodeValue;\r\n            var next = translate(raw, rule.map, rule.compiledText);\r\n            if (next === null) continue;\r\n\r\n            var trimmed = raw.trim();\r\n            var start = raw.indexOf(trimmed);\r\n            child.nodeValue = raw.slice(0, start) + next + raw.slice(start + trimmed.length);\r\n          }\r\n        }\r\n\r\n        if (rule.aria || rule.compiledAria) {\r\n          var label = node.getAttribute('aria-label');\r\n\r\n          if (label) {\r\n            var nextLabel = translate(label, rule.aria, rule.compiledAria);\r\n            if (nextLabel !== null) node.setAttribute('aria-label', nextLabel);\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  // The widgets arrive over the network, and a variant change or a cart update brings\r\n  // more, so this cannot be a one-shot. One observer, coalesced into a single pass per\r\n  // frame so a burst of mutations does not become a burst of full-document queries, and\r\n  // disconnected once the page has been quiet long enough that anything still to come\r\n  // would be a fresh navigation anyway.\r\n  //\r\n  // aria-label is watched as well as the tree, because the slider rewrites its own\r\n  // \"Slide 1 of 6\" every time it advances. Our own writes do retrigger the observer, but\r\n  // the value we leave behind matches no key and no pattern, so the following pass\r\n  // changes nothing and the cascade stops one frame later. On the English storefront it\r\n  // never starts: the expansion equals the text already there, translate returns null,\r\n  // and nothing is written at all.\r\n  //\r\n  // No need to mark processed nodes, for the same reason.\r\n  var scheduled = false;\r\n\r\n  function schedule() {\r\n    if (scheduled) return;\r\n    scheduled = true;\r\n    requestAnimationFrame(function () {\r\n      scheduled = false;\r\n      apply();\r\n    });\r\n  }\r\n\r\n  apply();\r\n\r\n  var observer = new MutationObserver(schedule);\r\n  var idleTimer = null;\r\n\r\n  // Watching is re-armable rather than one-shot. The window still closes, so the page does\r\n  // not carry a whole-document observer for the life of the visit, but anything that can\r\n  // put a fresh LimeSpot box on the page opens it again.\r\n  function watch(duration) {\r\n    observer.observe(document.body, {\r\n      childList: true,\r\n      subtree: true,\r\n      attributes: true,\r\n      attributeFilter: ['aria-label'],\r\n    });\r\n\r\n    if (idleTimer) clearTimeout(idleTimer);\r\n    idleTimer = setTimeout(function () {\r\n      idleTimer = null;\r\n      observer.disconnect();\r\n    }, duration);\r\n  }\r\n\r\n  watch(20000);\r\n\r\n  // KAN-182: the cart drawer is what the single window missed, and Kai reported it as\r\n  // \"the other section work with the translation, these two doesn't\".\r\n  //\r\n  // Its cross-sell box only exists once the shopper opens the drawer, which is almost\r\n  // always more than twenty seconds into a visit, so by then the observer had already\r\n  // disconnected and the box rendered in English. Worse, the theme replaces the drawer's\r\n  // children outright on every cart change (CartDrawer#replaceContent in theme.js), so a\r\n  // box translated earlier came back English anyway.\r\n  //\r\n  // dialog:after-show does not bubble - it is dispatched on the dialog itself - so it is\r\n  // caught in the capture phase, which runs on ancestors for non-bubbling events too. It\r\n  // fires for every dialog in the theme, hence the check for the drawer: a quick-buy modal\r\n  // holds the theme's own cards, which are already translated server-side.\r\n  function rearm() {\r\n    apply();\r\n    watch(8000);\r\n  }\r\n\r\n  ['cart:change', 'cart:refresh', 'cart-drawer:refreshed'].forEach(function (name) {\r\n    document.addEventListener(name, rearm);\r\n  });\r\n\r\n  document.addEventListener(\r\n    'dialog:after-show',\r\n    function (event) {\r\n      var target = event.target;\r\n      if (target && target.matches && target.matches('cart-drawer')) rearm();\r\n    },\r\n    true,\r\n  );\r\n})();\r\n\r\n// === Back in stock: subscribe the visitor through Klaviyo's client API (KAN-35) ===\r\n// The \"Notify me\" button and its form are the theme's own (snippets/back-in-stock.liquid),\r\n// so every string sits in locales/ and the button is the same outline button as \"Sold out\".\r\n// This is only the submit.\r\n//\r\n// Klaviyo's own widget was the original plan and was dropped for two reasons: their sign-up\r\n// forms cannot use their Smart translation feature, so the copy would have stayed English on\r\n// every market, and their documentation says installation \"is only supported for certain free\r\n// Shopify themes, and not for Shopify stores using custom themes\".\r\n//\r\n// POST https://a.klaviyo.com/client/back-in-stock-subscriptions?company_id=<public site ID>\r\n// The /client endpoints authenticate with the public site ID alone - the same key already in\r\n// the page for onsite tracking - so nothing secret is involved and this can run in the browser.\r\n//\r\n// Everything is delegated off the document rather than bound per form: the theme re-renders\r\n// the whole product-info block when the visitor switches variant, which replaces these nodes.\r\n// For the same reason the variant id is read at submit time, off the data attribute, instead\r\n// of being captured once.\r\n(function () {\r\n  var config = (window.themeVariables && window.themeVariables.backInStock) || null;\r\n  var strings = (window.themeVariables && window.themeVariables.strings) || {};\r\n\r\n  if (!config || !config.companyId) return;\r\n\r\n  var ENDPOINT = 'https://a.klaviyo.com/client/back-in-stock-subscriptions';\r\n  var SUBSCRIBE_ENDPOINT = 'https://a.klaviyo.com/client/subscriptions';\r\n\r\n  // Shopify variant ids reach Klaviyo's catalog under a composite key:\r\n  // integration:::catalog:::external id.\r\n  function catalogVariantId(variantId) {\r\n    return '$shopify:::$default:::' + variantId;\r\n  }\r\n\r\n  // E.164 without a regex, so nothing here depends on escape sequences surviving: a leading\r\n  // plus, then 8 to 15 digits and nothing else. Deliberately permissive - Klaviyo does the\r\n  // real validation, this only catches the obvious typo before spending a request on it.\r\n  function looksLikePhone(value) {\r\n    if (value.charAt(0) !== '+') return false;\r\n\r\n    var digits = 0;\r\n\r\n    for (var i = 1; i < value.length; i++) {\r\n      var c = value.charAt(i);\r\n      if (c === ' ' || c === '-' || c === '(' || c === ')') continue;\r\n      if (c < '0' || c > '9') return false;\r\n      digits++;\r\n    }\r\n\r\n    return digits >= 8 && digits <= 15;\r\n  }\r\n\r\n  function showError(form, message) {\r\n    var el = form.querySelector('.back-in-stock__error');\r\n    if (!el) return;\r\n    el.textContent = message;\r\n    el.hidden = false;\r\n  }\r\n\r\n  function clearError(form) {\r\n    var el = form.querySelector('.back-in-stock__error');\r\n    if (!el) return;\r\n    el.textContent = '';\r\n    el.hidden = true;\r\n  }\r\n\r\n  // The marketing opt-in, sent to Klaviyo's own subscribe endpoint.\r\n  //\r\n  // The first attempt at this went through Shopify's /contact instead, so that no Klaviyo\r\n  // list would be needed - Kai had asked whether the status could change without one. It\r\n  // cannot, from a browser. Klaviyo requires a list on the endpoint a public key can reach,\r\n  // and the endpoint that does not require one needs a private key and a server. Shopify\r\n  // looked like the way round it, and the consent does reach Klaviyo through the\r\n  // integration, but the store has spam protection on customer forms: a hand-built POST to\r\n  // /contact is answered with 400 \"Missing CAPTCHA token\", because the token is injected\r\n  // only into Shopify's own rendered forms. A dedicated list is the honest answer.\r\n  //\r\n  // The list is only the entry point. Consent is set on the profile, under\r\n  // subscriptions.email.marketing, so these people count as subscribers account-wide and\r\n  // not merely as members of one list.\r\n  //\r\n  // Fire and forget, deliberately. The visitor came for the stock alert; if the marketing\r\n  // sign-up fails there is nothing they could do about it and nothing to fix from this form,\r\n  // so it must not be able to turn a successful subscription into an error message.\r\n  function subscribeToEmailList(email, listId) {\r\n    if (!listId) return;\r\n\r\n    fetch(SUBSCRIBE_ENDPOINT + '?company_id=' + encodeURIComponent(config.companyId), {\r\n      method: 'POST',\r\n      headers: {\r\n        'Content-Type': 'application/vnd.api+json',\r\n        revision: config.revision,\r\n      },\r\n      body: JSON.stringify({\r\n        data: {\r\n          type: 'subscription',\r\n          attributes: {\r\n            custom_source: 'back-in-stock-form',\r\n            profile: {\r\n              data: {\r\n                type: 'profile',\r\n                attributes: {\r\n                  email: email,\r\n                  subscriptions: {\r\n                    email: { marketing: { consent: 'SUBSCRIBED' } },\r\n                  },\r\n                },\r\n              },\r\n            },\r\n          },\r\n          relationships: {\r\n            list: { data: { type: 'list', id: listId } },\r\n          },\r\n        },\r\n      }),\r\n    }).catch(function () {});\r\n  }\r\n\r\n  // The phone field only exists when the SMS setting is on, and only matters once the\r\n  // visitor asks for it.\r\n  document.addEventListener('change', function (event) {\r\n    var checkbox = event.target;\r\n    if (!checkbox.name || checkbox.name !== 'sms_opt_in') return;\r\n\r\n    var form = checkbox.closest('.back-in-stock__form');\r\n    if (!form) return;\r\n\r\n    var block = form.querySelector('.back-in-stock__sms');\r\n    if (!block) return;\r\n\r\n    block.hidden = !checkbox.checked;\r\n  });\r\n\r\n  document.addEventListener('submit', function (event) {\r\n    var form = event.target;\r\n    if (!form.classList || !form.classList.contains('back-in-stock__form')) return;\r\n\r\n    event.preventDefault();\r\n\r\n    var root = form.closest('back-in-stock');\r\n    if (!root) return;\r\n\r\n    var variantId = root.getAttribute('data-variant-id');\r\n    if (!variantId) return;\r\n\r\n    var emailInput = form.querySelector('input[type=\"email\"]');\r\n    var smsCheckbox = form.querySelector('input[name=\"sms_opt_in\"]');\r\n    var phoneInput = form.querySelector('input[type=\"tel\"]');\r\n    var submitButton = form.querySelector('button[type=\"submit\"]');\r\n\r\n    if (!emailInput || !emailInput.validity.valid || !emailInput.value.trim()) {\r\n      showError(form, strings.backInStockErrorEmail);\r\n      emailInput && emailInput.focus();\r\n      return;\r\n    }\r\n\r\n    var channels = ['EMAIL'];\r\n    var profile = { email: emailInput.value.trim() };\r\n\r\n    if (smsCheckbox && smsCheckbox.checked) {\r\n      var phone = phoneInput ? phoneInput.value.trim() : '';\r\n\r\n      if (!looksLikePhone(phone)) {\r\n        showError(form, strings.backInStockErrorPhone);\r\n        phoneInput && phoneInput.focus();\r\n        return;\r\n      }\r\n\r\n      channels.push('SMS');\r\n      profile.phone_number = phone;\r\n    }\r\n\r\n    clearError(form);\r\n\r\n    // Sent alongside the stock subscription rather than after it: they are independent, and\r\n    // this one is not allowed to affect what the visitor sees either way.\r\n    var listCheckbox = form.querySelector('input[name=\"email_list_opt_in\"]');\r\n\r\n    if (listCheckbox && listCheckbox.checked) {\r\n      subscribeToEmailList(profile.email, root.getAttribute('data-list-id'));\r\n    }\r\n\r\n    // A second click while the first request is in flight would create a duplicate\r\n    // subscription, which Klaviyo rejects - so the visitor would see an error for having\r\n    // been too quick.\r\n    if (submitButton) submitButton.disabled = true;\r\n\r\n    fetch(ENDPOINT + '?company_id=' + encodeURIComponent(config.companyId), {\r\n      method: 'POST',\r\n      headers: {\r\n        'Content-Type': 'application/vnd.api+json',\r\n        revision: config.revision,\r\n      },\r\n      body: JSON.stringify({\r\n        data: {\r\n          type: 'back-in-stock-subscription',\r\n          attributes: {\r\n            channels: channels,\r\n            profile: {\r\n              data: {\r\n                type: 'profile',\r\n                attributes: profile,\r\n              },\r\n            },\r\n          },\r\n          relationships: {\r\n            variant: {\r\n              data: {\r\n                type: 'catalog-variant',\r\n                id: catalogVariantId(variantId),\r\n              },\r\n            },\r\n          },\r\n        },\r\n      }),\r\n    })\r\n      .then(function (response) {\r\n        // 202 with no body is the documented success. 409 is not documented for this\r\n        // endpoint, but a repeat of the same profile and variant is rejected rather than\r\n        // accepted, so it is worth telling the visitor they are already on the list instead\r\n        // of showing them a generic failure.\r\n        if (response.status === 202) {\r\n          var success = root.querySelector('.back-in-stock__success');\r\n          form.hidden = true;\r\n\r\n          if (success) {\r\n            success.hidden = false;\r\n            var heading = success.querySelector('.h5');\r\n            if (heading) {\r\n              heading.setAttribute('tabindex', '-1');\r\n              heading.focus();\r\n            }\r\n          }\r\n\r\n          return;\r\n        }\r\n\r\n        if (submitButton) submitButton.disabled = false;\r\n\r\n        if (response.status === 409) {\r\n          showError(form, strings.backInStockErrorDuplicate);\r\n          return;\r\n        }\r\n\r\n        showError(form, strings.backInStockErrorGeneric);\r\n      })\r\n      .catch(function () {\r\n        // Offline, blocked by an extension, or Klaviyo unreachable. No detail to give that\r\n        // the visitor could act on, and nothing is logged: the payload carries their email.\r\n        if (submitButton) submitButton.disabled = false;\r\n        showError(form, strings.backInStockErrorGeneric);\r\n      });\r\n  });\r\n})();\r\n\n/*\n * Predictive search in languages Shopify does not support. (KAN-168)\n *\n * The header search asks /{locale}/search/suggest for results whenever the\n * shopify-features script says predictiveSearch is true, and Shopify says\n * true on /zh too. But the Predictive Search API only serves the buyer locales\n * listed at shopify.dev/docs/api/ajax/reference/predictive-search, and Chinese\n * is not one of them: /zh/search/suggest answers 417 \"Unsupported buyer\n * locale\", the theme finds no section in the response, and the dropdown stays\n * empty.\n *\n * The theme already has a fallback for this case: when the flag is false it\n * renders the same predictive-search section through ordinary search\n * (/search?section_id=predictive-search), which works in every language. This\n * only corrects the flag for languages outside Shopify's list. theme.js is a\n * compiled upstream bundle, so the method is patched on the element's\n * prototype rather than edited there.\n */\n(function () {\n  var SUPPORTED = [\n    'af', 'sq', 'hy', 'bs', 'bg', 'ca', 'hr', 'cs', 'da', 'nl', 'en', 'et', 'fo', 'fi', 'fr', 'gd',\n    'de', 'el', 'hu', 'is', 'id', 'it', 'la', 'lv', 'lt', 'mk', 'mo', 'no', 'nb', 'nn', 'pl', 'pt',\n    'ro', 'ru', 'sr', 'sh', 'sk', 'sl', 'es', 'sv', 'tr', 'uk', 'vi', 'cy',\n  ];\n  var locale = String((window.Shopify && window.Shopify.locale) || document.documentElement.lang || 'en').toLowerCase();\n  if (SUPPORTED.indexOf(locale.split('-')[0]) !== -1) return;\n  if (!window.customElements) return;\n\n  window.customElements.whenDefined('predictive-search').then(function () {\n    var PredictiveSearch = window.customElements.get('predictive-search');\n    if (!PredictiveSearch || typeof PredictiveSearch.prototype.supportsPredictiveApi !== 'function') return;\n    PredictiveSearch.prototype.supportsPredictiveApi = function () {\n      return false;\n    };\n  });\n})();\n\n// === Judge.me widgets: theme adjustments that need the rendered markup ===\r\n// Judge.me renders with Vue after load and re-renders on sort / paging, so everything\r\n// here is idempotent and re-applied on DOM changes (batched to one pass per frame).\r\n//  1. Stars: same sharp star as the theme cards. Each star gets --ab-star-fill from the\r\n//     rating's aria-label (\"4.78 out of 5 stars\") and its own colour; CSS draws it.\r\n//  2. AI summary highlights: only quotes that are cut off open a popup, so the rest\r\n//     get .ab-jm-hl-static (no chevron, not clickable).\r\n//  3. Product page sort menu: Safari ignores display:none on <option>, so the options we\r\n//     hide in CSS also get hidden + disabled here.\r\n//  4. Reviews linked to a product that's gone (draft / archived / deleted): checked once\r\n//     per product via /products/<handle>.js; the link is disabled and labelled.\r\n(function () {\r\n  var HIDDEN_SORTS = ['videos_first', 'most_helpful', 'with_pictures', 'pictures_first'];\r\n  var productStatus = {}; // handle -> 'ok' | 'gone' | Promise\r\n\r\n  function score(rating) {\r\n    var label = rating.getAttribute('aria-label') || '';\r\n    var m = label.match(/([0-9]+(?:[.,][0-9]+)?)/);\r\n    var s = m ? parseFloat(m[1].replace(',', '.')) : parseFloat(rating.getAttribute('data-score'));\r\n    return isNaN(s) ? null : s;\r\n  }\r\n\r\n  function stars(root) {\r\n    root.querySelectorAll('.jm-star-rating').forEach(function (rating) {\r\n      var s = score(rating);\r\n      if (s === null) return;\r\n      var icons = rating.querySelectorAll('.jm-star-rating__font-icon');\r\n      icons.forEach(function (icon, i) {\r\n        var fill = Math.max(0, Math.min(1, s - i)) * 100 + '%';\r\n        if (!icon.classList.contains('ab-jm-star')) {\r\n          // Keep Judge.me's star colour (set inline / via their variables) before hiding the glyph\r\n          icon.style.setProperty('--ab-star-color', getComputedStyle(icon).color);\r\n          icon.classList.add('ab-jm-star');\r\n        }\r\n        if (icon.style.getPropertyValue('--ab-star-fill') !== fill) icon.style.setProperty('--ab-star-fill', fill);\r\n      });\r\n    });\r\n  }\r\n\r\n  function highlights(root) {\r\n    root.querySelectorAll('.jm-review-highlights__row').forEach(function (row) {\r\n      var text = row.querySelector('.jm-review-highlights__text') || row;\r\n      var cut = text.scrollWidth > text.clientWidth + 1 || text.scrollHeight > text.clientHeight + 1;\r\n      row.classList.toggle('ab-jm-hl-static', !cut);\r\n    });\r\n  }\r\n\r\n  function sorts(root) {\r\n    root.querySelectorAll('.jdgm-review-widget .jm-sort-filter__select option').forEach(function (opt) {\r\n      if (HIDDEN_SORTS.indexOf(opt.value) !== -1 && !opt.hidden) {\r\n        opt.hidden = true;\r\n        opt.disabled = true;\r\n      }\r\n    });\r\n  }\r\n\r\n  function handleOf(href) {\r\n    try {\r\n      var m = new URL(href, location.origin).pathname.match(/\\/products\\/([^\\/?#]+)/);\r\n      return m ? decodeURIComponent(m[1]) : null;\r\n    } catch (e) {\r\n      return null;\r\n    }\r\n  }\r\n\r\n  function markGone(link) {\r\n    if (link.classList.contains('ab-jm-gone')) return;\r\n    link.classList.add('ab-jm-gone');\r\n    link.removeAttribute('href');\r\n    link.setAttribute('aria-disabled', 'true');\r\n    var label = document.createElement('span');\r\n    label.className = 'ab-jm-gone-label';\r\n    label.textContent = (window.abStrings && window.abStrings.productUnavailable) || 'No longer available';\r\n    link.insertAdjacentElement('afterend', label);\r\n  }\r\n\r\n  // One HEAD request per product (no body downloaded), remembered for the browsing session.\r\n  // Anything other than a clear 404 counts as available, so a link is never wrongly disabled.\r\n  var CACHE_KEY = 'abJmProductStatus';\r\n  try {\r\n    productStatus = JSON.parse(sessionStorage.getItem(CACHE_KEY)) || {};\r\n  } catch (e) {\r\n    productStatus = {};\r\n  }\r\n  function remember(handle, status) {\r\n    productStatus[handle] = status;\r\n    try {\r\n      var plain = {};\r\n      Object.keys(productStatus).forEach(function (k) {\r\n        if (typeof productStatus[k] === 'string') plain[k] = productStatus[k];\r\n      });\r\n      sessionStorage.setItem(CACHE_KEY, JSON.stringify(plain));\r\n    } catch (e) {}\r\n    return status;\r\n  }\r\n  function check(handle) {\r\n    if (!productStatus[handle]) {\r\n      productStatus[handle] = fetch('/products/' + encodeURIComponent(handle) + '.js', { method: 'HEAD', credentials: 'same-origin' })\r\n        .then(function (r) {\r\n          return remember(handle, r.status === 404 ? 'gone' : 'ok');\r\n        })\r\n        .catch(function () {\r\n          return remember(handle, 'ok');\r\n        });\r\n    }\r\n    return Promise.resolve(productStatus[handle]);\r\n  }\r\n\r\n  function productLinks(root) {\r\n    var links = root.querySelectorAll(\r\n      '.jm-review-widget a[href*=\"/products/\"], .jdgm-review-snippet-widget-v2 a[href*=\"/products/\"], .jdgm-modal a[href*=\"/products/\"]'\r\n    );\r\n    links.forEach(function (link) {\r\n      if (link.dataset.abJmChecked) return;\r\n      link.dataset.abJmChecked = '1';\r\n      var handle = handleOf(link.getAttribute('href'));\r\n      if (!handle) return;\r\n      check(handle).then(function (status) {\r\n        if (status === 'gone') markGone(link);\r\n      });\r\n    });\r\n  }\r\n\r\n  // 5. Popup close button: on desktop Judge.me places the X outside the panel. Pin it\r\n  //    to the panel's top-right corner, whatever their markup nesting is.\r\n  function closeButton() {\r\n    document.querySelectorAll('.jdgm-modal').forEach(function (modal) {\r\n      var panel = modal.querySelector('.jm-slide, .jdgm-rev-snippet-lightbox');\r\n      var btn = modal.querySelector('button[aria-label*=\"lose\" i], button[class*=\"close\" i], [class*=\"close\" i][role=\"button\"]');\r\n      if (!panel || !btn) return;\r\n      if (window.innerWidth < 700) {\r\n        btn.classList.remove('ab-jm-close');\r\n        btn.style.removeProperty('top');\r\n        btn.style.removeProperty('left');\r\n        return;\r\n      }\r\n      var p = panel.getBoundingClientRect();\r\n      if (!p.width) return;\r\n      var size = btn.offsetWidth || 40;\r\n      // Measure again once the opening animation has finished.\r\n      if (!btn.classList.contains('ab-jm-close')) setTimeout(schedule, 400);\r\n      btn.classList.add('ab-jm-close');\r\n      btn.style.top = Math.round(p.top + 12) + 'px';\r\n      btn.style.left = Math.round(p.right - size - 12) + 'px';\r\n    });\r\n  }\r\n\r\n  var scheduled = false;\r\n  function run() {\r\n    scheduled = false;\r\n    if (!document.querySelector('.jm-review-widget, .jdgm-review-snippet-widget-v2, .jdgm-modal')) return;\r\n    stars(document);\r\n    highlights(document);\r\n    sorts(document);\r\n    productLinks(document);\r\n    closeButton();\r\n  }\r\n  function schedule() {\r\n    if (scheduled) return;\r\n    scheduled = true;\r\n    requestAnimationFrame(run);\r\n  }\r\n\r\n  var JM = '.jm-review-widget, .jdgm-widget, .jdgm-modal';\r\n  function touchesJudgeMe(records) {\r\n    for (var i = 0; i < records.length; i++) {\r\n      var r = records[i];\r\n      var el = r.target.nodeType === 1 ? r.target : r.target.parentElement;\r\n      if (el && el.closest(JM)) return true;\r\n      for (var j = 0; j < r.addedNodes.length; j++) {\r\n        var n = r.addedNodes[j];\r\n        if (n.nodeType === 1 && (n.matches(JM) || n.querySelector(JM))) return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  function start() {\r\n    run();\r\n    // The whole page is watched because Judge.me mounts late, but only changes inside its\r\n    // widgets trigger a pass - other carousels and apps don't cost anything here.\r\n    new MutationObserver(function (records) {\r\n      if (touchesJudgeMe(records)) schedule();\r\n    }).observe(document.body, { childList: true, subtree: true });\r\n    window.addEventListener('resize', schedule);\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', start);\r\n  } else {\r\n    start();\r\n  }\r\n})();\r\n\r\n// === Judge.me review snippet: pagination dots ===\n// Judge.me's snippet carousel has no dots. Adds one per review, synced to the\n// track's scroll position; clicking a dot scrolls to that review.\n(function () {\n  function setup(widget) {\n    var track = widget.querySelector('.jm-carousel__track');\n    var carousel = widget.querySelector('.jm-carousel');\n    if (!track || !carousel) return;\n\n    var cards = track.querySelectorAll('.jdgm-rev-snippet-card');\n    var existing = widget.querySelector('.ab-snippet-dots');\n    if (existing && existing.children.length === cards.length) return;\n    if (existing) existing.remove();\n    if (cards.length < 2) return;\n\n    var dots = document.createElement('div');\n    dots.className = 'ab-snippet-dots';\n\n    function step() {\n      return cards[1].offsetLeft - cards[0].offsetLeft || track.clientWidth;\n    }\n\n    function update() {\n      var i = Math.round(track.scrollLeft / step());\n      Array.prototype.forEach.call(dots.children, function (dot, n) {\n        dot.setAttribute('aria-current', n === i ? 'true' : 'false');\n      });\n    }\n\n    Array.prototype.forEach.call(cards, function (card, n) {\n      var dot = document.createElement('button');\n      dot.type = 'button';\n      var strings = (window.themeVariables && window.themeVariables.strings) || {};\n      var label = (strings.reviewSlide || '{{ index }} / {{ count }}')\n        .replace('{{ index }}', n + 1)\n        .replace('{{ count }}', cards.length);\n      dot.setAttribute('aria-label', label);\n      dot.addEventListener('click', function () {\n        track.scrollTo({ left: n * step(), behavior: 'smooth' });\n      });\n      dots.appendChild(dot);\n    });\n\n    carousel.insertAdjacentElement('afterend', dots);\n    if (!track.dataset.abDots) {\n      track.dataset.abDots = '1';\n      track.addEventListener('scroll', function () {\n        requestAnimationFrame(update);\n      }, { passive: true });\n    }\n    update();\n  }\n\n  var scheduled = false;\n  function scan() {\n    scheduled = false;\n    document.querySelectorAll('.jdgm-review-snippet-widget-v2').forEach(setup);\n  }\n\n  function start() {\n    scan();\n    new MutationObserver(function () {\n      if (scheduled) return;\n      scheduled = true;\n      setTimeout(scan, 100);\n    }).observe(document.body, { childList: true, subtree: true });\n  }\n\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', start);\n  } else {\n    start();\n  }\n})();\n// === Product card wishlist: next-to-title placement and saved state (Theme settings > Product card) ===\n// Wishlist Power injects its button into .product-card__figure (top right of the image). Cards rendered\n// with the \"next to title\" position carry .product-card--wishlist-info; move the button into the\n// card's info strip, where custom.css places it beside the title.\n(function () {\n  var queued = false;\n  // Desktop shows the icon on hover only (custom.css); a saved product keeps it visible. The saved\n  // state lives on the app's button inside its shadow root, so mirror it onto the wrapper as .is-saved.\n  var watched = new WeakSet();\n  function syncSaved(wrap) {\n    var host = wrap.querySelector('ooo-wl-product-card-button');\n    var button = host && host.shadowRoot && host.shadowRoot.querySelector('button[role=\"checkbox\"]');\n    if (!button) return;\n    var update = function () { wrap.classList.toggle('is-saved', button.getAttribute('aria-checked') === 'true'); };\n    update();\n    if (watched.has(button)) return;\n    watched.add(button);\n    new MutationObserver(update).observe(button, { attributes: true, attributeFilter: ['aria-checked'] });\n  }\n  function place() {\n    queued = false;\n    document.querySelectorAll('.product-card--wishlist-info > .product-card__figure > ooo-wl-access-button').forEach(function (wrap) {\n      var info = wrap.closest('.product-card').querySelector('.product-card__info');\n      if (info) info.appendChild(wrap);\n    });\n    document.querySelectorAll('.product-card ooo-wl-access-button').forEach(syncSaved);\n  }\n  function queue() {\n    if (queued) return;\n    queued = true;\n    requestAnimationFrame(place);\n  }\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', queue);\n  else queue();\n  new MutationObserver(queue).observe(document.documentElement, { childList: true, subtree: true });\n  // The app fills its shadow roots after load, which the observer above can't see; catch up a few times.\n  [1500, 4000, 8000].forEach(function (delay) { setTimeout(queue, delay); });\n})();\n\r\n// === Navigation helpers (replace the old ab-clear-menu.js) ===\r\n// 1. Unpublished preview themes: Shopify drops ?preview_theme_id on some navigations, which silently\r\n//    lands a reviewer on the live theme. Keep it on same-store links while browsing a preview.\r\n// 2. Mobile menu search bar (snippets/header-sidebar.liquid, data-sidebar-search): close the sidebar,\r\n//    then open the header search drawer (the Searchanise-powered one).\r\n(function () {\r\n  var theme = window.Shopify && window.Shopify.theme;\r\n  var previewId = theme && theme.role === 'unpublished' ? String(theme.id) : null;\r\n\r\n  if (previewId) {\r\n    var current = new URL(location.href);\r\n    if (current.searchParams.get('preview_theme_id') !== previewId) {\r\n      current.searchParams.set('preview_theme_id', previewId);\r\n      history.replaceState(history.state, '', current.href);\r\n    }\r\n  }\r\n\r\n  document.addEventListener(\r\n    'click',\r\n    function (event) {\r\n      var link = event.target.closest && event.target.closest('a[href]');\r\n\r\n      if (previewId && link && link.getAttribute('href').charAt(0) !== '#') {\r\n        try {\r\n          var url = new URL(link.href);\r\n          if (url.origin === location.origin && /^\\/(?:$|collections|products|pages|search|cart)/.test(url.pathname)) {\r\n            url.searchParams.set('preview_theme_id', previewId);\r\n            link.href = url.href;\r\n          }\r\n        } catch (e) {}\r\n      }\r\n\r\n      var search = event.target.closest && event.target.closest('[data-sidebar-search]');\r\n      if (search) {\r\n        var sidebar = search.closest('header-sidebar');\r\n        var drawer = document.getElementById(search.getAttribute('aria-controls'));\r\n        if (sidebar && sidebar.hide && drawer && drawer.show) {\r\n          event.preventDefault();\r\n          event.stopImmediatePropagation();\r\n          Promise.resolve(sidebar.hide()).then(function () {\r\n            drawer.show();\r\n          });\r\n        }\r\n      }\r\n    },\r\n    true\r\n  );\r\n})();\r\n\r\n// === #filter-<name> links (snippets/facets.liquid marks each filter with data-facet-group) ===\r\n// A URL ending in #filter-stone opens the Stone filter - the filter drawer first on mobile - and\r\n// focuses its search box (added by assets/collection-filter-search.js when the filter is long).\r\n(function () {\r\n  function isShown(el) {\r\n    return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);\r\n  }\r\n\r\n  function openFilterFromHash() {\r\n    var m = location.hash.match(/^#filter-([a-z0-9_-]+)$/i);\r\n    if (!m) return;\r\n    var name = m[1].toLowerCase();\r\n    var anchors = Array.prototype.filter.call(document.querySelectorAll('[data-facet-group]'), function (a) {\r\n      var param = a.getAttribute('data-facet-group').toLowerCase();\r\n      return param === name || param.slice(-(name.length + 1)) === '.' + name;\r\n    });\r\n    if (!anchors.length) return;\r\n\r\n    // Desktop: the copy in the visible sidebar. Mobile: the copy inside the (closed) filter drawer.\r\n    var desktop = window.matchMedia('(min-width: 1000px)').matches;\r\n    var anchor = anchors.filter(function (a) {\r\n      var details = a.closest('details');\r\n      var host = details ? details.parentElement : a;\r\n      return desktop ? isShown(host) : !!a.closest('facets-drawer');\r\n    })[0] || anchors[0];\r\n\r\n    var details = anchor.closest('details');\r\n    var drawer = anchor.closest('facets-drawer');\r\n\r\n    function reveal() {\r\n      // Grid-first layout tucks some filters behind \"More filters\" - expand that too.\r\n      var more = anchor.closest('[data-abgf-collapsed]');\r\n      if (more) {\r\n        more.removeAttribute('data-abgf-collapsed');\r\n        var toggle = document.querySelector('[aria-controls=\"' + more.id + '\"]');\r\n        if (toggle) toggle.setAttribute('aria-expanded', 'true');\r\n      }\r\n      if (details && !details.open) details.open = true;\r\n      var input = details && details.querySelector('[data-filter-value-search]');\r\n      var target = details || anchor.parentElement;\r\n      // Brief gold pulse so a repeat click on the same page visibly does something.\r\n      var flash = (input && input.closest('.filter-value-search')) || (details && details.querySelector('summary'));\r\n      if (flash) {\r\n        flash.classList.remove('ab-flash');\r\n        void flash.offsetWidth;\r\n        flash.classList.add('ab-flash');\r\n        setTimeout(function () { flash.classList.remove('ab-flash'); }, 1800);\r\n      }\r\n      if (!drawer) {\r\n        var sticky = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--sticky-area-height')) || 0;\r\n        skbSmoothScroll(Math.max(0, window.pageYOffset + target.getBoundingClientRect().top - sticky - 16), 500);\r\n      }\r\n      if (input) setTimeout(function () { input.focus({ preventScroll: true }); }, drawer ? 350 : 520);\r\n    }\r\n\r\n    if (drawer && !desktop && drawer.show) {\r\n      Promise.resolve(drawer.show()).then(reveal);\r\n    } else {\r\n      reveal();\r\n    }\r\n  }\r\n\r\n  window.addEventListener('hashchange', openFilterFromHash);\r\n\r\n  // Same page, same hash (e.g. \"Browse all stones\" clicked again while already on the collection):\r\n  // the browser fires no hashchange, so handle the click directly.\r\n  document.addEventListener('click', function (event) {\r\n    var link = event.target.closest && event.target.closest('a[href*=\"#filter-\"]');\r\n    if (!link || event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\r\n    var url = new URL(link.href, location.href);\r\n    if (url.pathname !== location.pathname || !/^#filter-/i.test(url.hash)) return;\r\n    if (!document.querySelector('[data-facet-group]')) return;\r\n    event.preventDefault();\r\n    if (location.hash !== url.hash) history.replaceState(history.state, '', url.hash);\r\n    // Let an open header dropdown / mobile menu close first.\r\n    var sidebar = document.getElementById('sidebar-menu');\r\n    if (sidebar && sidebar.hide && sidebar.hasAttribute('open')) {\r\n      Promise.resolve(sidebar.hide()).then(openFilterFromHash);\r\n    } else {\r\n      if (document.activeElement && document.activeElement.blur) document.activeElement.blur();\r\n      document.querySelectorAll('.header__menu-disclosure[open]').forEach(function (d) { d.open = false; });\r\n      openFilterFromHash();\r\n    }\r\n  });\r\n  if (document.readyState === 'complete') openFilterFromHash();\r\n  else window.addEventListener('load', openFilterFromHash);\r\n})();\r\n"],
  "mappings": "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",
  "names": ["t", "details"]
}
