{
  "version": 3,
  "sources": ["/cdn/shop/t/30/assets/sticky-atc.js?probe=1777380971104"],
  "sourcesContent": ["/* Sticky mobile add-to-cart\n   Project: Veryplants CRO fixes (Apr 2026)\n   Subscribes to the theme's pubsub for variant changes (constants.js: PUB_SUB_EVENTS).\n*/\n\n(function () {\n  if (customElements.get('sticky-atc')) return;\n\n  class StickyATC extends HTMLElement {\n    constructor() {\n      super();\n      this.priceEl = this.querySelector('[data-price]');\n      this.variantEl = this.querySelector('[data-variant-title]');\n      this.addBtn = this.querySelector('[data-add-to-cart]');\n      this.addLabel = this.querySelector('.sticky-atc__add-label');\n      this.scrollBtn = this.querySelector('[data-scroll-to-top]');\n      this.productHandle = this.dataset.productHandle;\n      this.productUrl = this.dataset.productUrl;\n      this.showAfter = Number(this.dataset.showAfter) || 250;\n      this.currentVariantId = this.addBtn?.dataset.variantId\n        ? Number(this.addBtn.dataset.variantId)\n        : null;\n      this.product = null;\n      this.isVisible = false;\n      this.unsubscribe = null;\n    }\n\n    connectedCallback() {\n      // If another <sticky-atc> already exists earlier in the DOM, this duplicate\n      // should silently disappear. Prevents \"ADDADD\" double-render when a section\n      // update or app re-injects a second instance.\n      const existing = document.querySelectorAll('sticky-atc');\n      if (existing.length > 1 && existing[0] !== this) {\n        try { this.remove(); } catch (e) {}\n        return;\n      }\n      this.dedupeSlots();\n      this.fetchProduct();\n      this.bindEvents();\n      this.observeMainATC();\n      this.toggleVisible(false);\n    }\n\n    disconnectedCallback() {\n      if (typeof this.unsubscribe === 'function') this.unsubscribe();\n    }\n\n    async fetchProduct() {\n      try {\n        const r = await fetch(`${this.productUrl}.js`);\n        if (r.ok) this.product = await r.json();\n      } catch (e) {\n        // Bar still works using the server-rendered initial values.\n      }\n      // Sync once on init so the bar reflects the variant pre-selected via URL\n      // (e.g. Klaviyo Notify-me links land with ?variant=<sold-out-id>).\n      // Without this, the bar stays in the default ADD state for sold-out\n      // variants and creates rage clicks when users tap a non-functional button.\n      this.syncFromMainSelector();\n    }\n\n    bindEvents() {\n      this.addBtn.addEventListener('click', (e) => this.handleAdd(e));\n      this.scrollBtn.addEventListener('click', () => {\n        window.scrollTo({ top: 0, behavior: 'smooth' });\n      });\n\n      // Subscribe to the theme's variant-change pub/sub if present (constants.js + pubsub.js).\n      if (typeof window.subscribe === 'function' && window.PUB_SUB_EVENTS) {\n        this.unsubscribe = window.subscribe(\n          window.PUB_SUB_EVENTS.variantChange,\n          (data) => {\n            const v = data && (data.data?.variant || data.variant);\n            if (v) this.updateVariant(v);\n          }\n        );\n      }\n\n      // Belt-and-braces: also poll the main form's variant input.\n      const mainForm = document.querySelector('product-info form[action*=\"/cart/add\"]');\n      if (mainForm) {\n        const idInput = mainForm.querySelector('input[name=\"id\"]');\n        if (idInput) {\n          new MutationObserver(() => this.syncFromMainSelector())\n            .observe(idInput, { attributes: true, attributeFilter: ['value'] });\n        }\n      }\n    }\n\n    syncFromMainSelector() {\n      const idInput = document.querySelector('product-info form[action*=\"/cart/add\"] input[name=\"id\"]');\n      if (!idInput || !this.product) return;\n      const id = Number(idInput.value);\n      if (!id) return;\n      const variant = this.product.variants.find((v) => v.id === id);\n      if (variant) this.updateVariant(variant);\n    }\n\n    updateVariant(variant) {\n      this.currentVariantId = variant.id;\n      this.addBtn.dataset.variantId = variant.id;\n      // Defensive: re-resolve element refs in case DOM was re-rendered by a\n      // section update (cart drawer refresh, app re-render). Stale refs would\n      // mean updates land on detached nodes while a fresh duplicate sits visible.\n      this.priceEl = this.querySelector('[data-price]');\n      this.variantEl = this.querySelector('[data-variant-title]');\n      this.addLabel = this.querySelector('.sticky-atc__add-label');\n      // Clean any duplicate slots a 3rd-party script may have injected. Keep the first\n      // of each slot, remove any siblings with the same selector. This is the fix for\n      // the \"ADDADD\"/\"$22.99$74.99\"/concatenated-variant-titles bug seen in Propel\n      // session 2602353356 on in-app browsers.\n      this.dedupeSlots();\n      if (this.priceEl) this.priceEl.replaceChildren(document.createTextNode(this.formatMoney(variant.price)));\n      if (this.variantEl) {\n        this.variantEl.replaceChildren(document.createTextNode(variant.public_title || variant.title || ''));\n      }\n      const available = variant.available;\n      this.addBtn.disabled = !available;\n      this.addBtn.setAttribute('aria-disabled', String(!available));\n      if (this.addLabel) this.addLabel.replaceChildren(document.createTextNode(available ? 'ADD' : 'SOLD OUT'));\n    }\n\n    dedupeSlots() {\n      // If multiple [data-price] / [data-variant-title] / .sticky-atc__add-label\n      // exist (shouldn't, but defensive), remove all but the first.\n      ['[data-price]', '[data-variant-title]', '.sticky-atc__add-label'].forEach((sel) => {\n        const matches = this.querySelectorAll(sel);\n        if (matches.length > 1) {\n          for (let i = 1; i < matches.length; i++) matches[i].remove();\n        }\n      });\n      // If multiple [data-add-to-cart] buttons inside sticky-atc, keep first\n      const buttons = this.querySelectorAll('[data-add-to-cart]');\n      if (buttons.length > 1) {\n        for (let i = 1; i < buttons.length; i++) buttons[i].remove();\n      }\n    }\n\n    async handleAdd(event) {\n      event.preventDefault();\n\n      if (!this.currentVariantId) {\n        const sizePicker = document.querySelector(\n          'variant-radios, fieldset[name=\"Size\"], .product-form__input'\n        );\n        if (sizePicker) {\n          sizePicker.scrollIntoView({ behavior: 'smooth', block: 'center' });\n        }\n        return;\n      }\n\n      this.setLoading(true);\n      try {\n        // Pull section IDs to refresh so the cart drawer updates.\n        const sectionsToBundle = [];\n        document.documentElement.dispatchEvent(\n          new CustomEvent('cart:before-add', { bubbles: true, detail: { sectionsToBundle } })\n        );\n        const cartDrawer = document.querySelector('cart-drawer');\n        if (cartDrawer && typeof cartDrawer.getSectionsToRender === 'function') {\n          cartDrawer.getSectionsToRender().forEach((s) => sectionsToBundle.push(s.id));\n        }\n\n        const body = { items: [{ id: this.currentVariantId, quantity: 1 }] };\n        if (sectionsToBundle.length) body.sections = sectionsToBundle.join(',');\n\n        const res = await fetch('/cart/add.js', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n          body: JSON.stringify(body),\n        });\n        if (!res.ok) throw new Error('add-to-cart failed');\n        const json = await res.json();\n\n        // Push new sections into the cart drawer (Dawn pattern).\n        if (cartDrawer && json.sections && typeof cartDrawer.renderContents === 'function') {\n          cartDrawer.renderContents(json);\n        }\n\n        // Theme pubsub event so other listeners refresh.\n        if (typeof window.publish === 'function' && window.PUB_SUB_EVENTS) {\n          window.publish(window.PUB_SUB_EVENTS.cartUpdate, {\n            source: 'sticky-atc',\n            productVariantId: this.currentVariantId,\n            cartData: json,\n          });\n        }\n\n        // Open the cart drawer if present.\n        if (cartDrawer && typeof cartDrawer.open === 'function') {\n          cartDrawer.open();\n        }\n\n        // Brief success state.\n        if (this.addLabel) {\n          const original = this.addLabel.textContent;\n          this.addLabel.textContent = 'ADDED \u2713';\n          setTimeout(() => (this.addLabel.textContent = original), 1200);\n        }\n      } catch (err) {\n        if (this.addLabel) {\n          this.addLabel.textContent = 'TRY AGAIN';\n          setTimeout(() => (this.addLabel.textContent = 'ADD'), 1500);\n        }\n      } finally {\n        this.setLoading(false);\n      }\n    }\n\n    setLoading(isLoading) {\n      this.addBtn.classList.toggle('is-loading', isLoading);\n      this.addBtn.disabled = isLoading;\n    }\n\n    observeMainATC() {\n      const mainAtc = document.querySelector(\n        'product-info button[name=\"add\"], product-form button[name=\"add\"], button[name=\"add\"][type=\"submit\"]'\n      );\n      if (!mainAtc || typeof IntersectionObserver === 'undefined') {\n        // Fallback: show after the user scrolls past the configured threshold.\n        const onScroll = () => this.toggleVisible(window.scrollY > this.showAfter);\n        window.addEventListener('scroll', onScroll, { passive: true });\n        onScroll();\n        return;\n      }\n      const observer = new IntersectionObserver(\n        (entries) => {\n          this.toggleVisible(!entries[0].isIntersecting);\n        },\n        { threshold: 0.1 }\n      );\n      observer.observe(mainAtc);\n    }\n\n    toggleVisible(show) {\n      if (show === this.isVisible) return;\n      this.isVisible = show;\n      this.classList.toggle('is-visible', show);\n      document.body.classList.toggle('has-sticky-atc-visible', show);\n    }\n\n    formatMoney(cents) {\n      if (window.Shopify && Shopify.formatMoney) {\n        try {\n          return Shopify.formatMoney(cents, window.theme?.moneyFormat || '${{amount}}');\n        } catch (e) {}\n      }\n      return '$' + (cents / 100).toFixed(2);\n    }\n  }\n\n  customElements.define('sticky-atc', StickyATC);\n})();\n"],
  "mappings": "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",
  "names": []
}
