{
  "version": 3,
  "sources": ["/cdn/shop/t/28/assets/bling-customization-v2.js?bling=fix-unconfigured-buy-v4"],
  "sourcesContent": ["/* BLING_NONE_FIX=11 */\n/* MEETING_SECTION_V2_20260811 */\n/* overlapfix2-restore-flow + dropdown-stack-fix */\n\n/**\n * Bling Customization Form - Inline Version with AI Preview\n * Shows customization fields inline above Add to Cart button\n * Includes AI-powered preview generation\n */\nclass BlingCustomizationForm extends HTMLElement {\n  static CFG_CACHE_VERSION = 12;\n  static CFG_CACHE_TTL_MS = 15 * 1000;\n\n  constructor() {\n    super();\n    this.config = null;\n    this.fields = [];\n    this.sessionId = null;\n    this.uploads = new Map();\n    this.isLoading = false;\n    this.formSubmitHandler = null;\n    this.abortController = null;\n    this.cssInjected = false;\n    this.isSubmitting = false;\n    this.isBuyNow = false;\n    this.addToCartButtonListeners = new Map();\n    this.paymentButtonListeners = new Map();\n    this.formVisible = false;\n    this.previewSettings = null;\n    this.previewCount = this.getPreviewCount();\n    this.generatedPreviews = [];\n    this._shouldSwitchToMainOnInput = false;\n  }\n\n  connectedCallback() {\n    this.init();\n  }\n\n  disconnectedCallback() {\n    this.cleanup();\n  }\n\n  cleanupFormInterceptors() {\n    if (this.formSubmitHandler) {\n      const form = this._findCartForm();\n      if (form) {\n        form.removeEventListener('submit', this.formSubmitHandler, true);\n      }\n      this.formSubmitHandler = null;\n    }\n\n    this.addToCartButtonListeners.forEach((handler, button) => {\n      button.removeEventListener('click', handler, true);\n    });\n    this.addToCartButtonListeners.clear();\n\n    this.paymentButtonListeners.forEach((handler, button) => {\n      button.removeEventListener('click', handler, true);\n    });\n    this.paymentButtonListeners.clear();\n\n    if (this.formObserver) {\n      this.formObserver.disconnect();\n      this.formObserver = null;\n    }\n  }\n\n  cleanup() {\n    this.cleanupFormInterceptors();\n\n    if (this.abortController) {\n      this.abortController.abort();\n      this.abortController = null;\n    }\n\n    this.teardownZoneOverlay();\n\n    this.uploads.clear();\n\n    if (this._variantInterval) {\n      clearInterval(this._variantInterval);\n      this._variantInterval = null;\n    }\n    if (this._blingVariantHandler) {\n      document.removeEventListener('bling:variant-changed', this._blingVariantHandler);\n      this._blingVariantHandler = null;\n    }\n    if (this._liveSyncInterval) {\n      clearInterval(this._liveSyncInterval);\n      this._liveSyncInterval = null;\n    }\n    if (this._visibilityChangeHandler) {\n      document.removeEventListener('visibilitychange', this._visibilityChangeHandler);\n      this._visibilityChangeHandler = null;\n    }\n    if (this._windowFocusHandler) {\n      window.removeEventListener('focus', this._windowFocusHandler);\n      this._windowFocusHandler = null;\n    }\n    if (this._broadcastChannel) {\n      try { this._broadcastChannel.close(); } catch {}\n      this._broadcastChannel = null;\n    }\n  }\n\n  /** HTML-safe id for inputs (logical field id may contain spaces). */\n  fieldDomId(fieldId) {\n    const s = String(fieldId ?? 'field');\n    const safe = s.replace(/[^a-zA-Z0-9_-]/g, '_').replace(/_+/g, '_').slice(0, 96);\n    return `bling-field-${safe || 'x'}`;\n  }\n\n  fieldRadioName(fieldId) {\n    return `${this.fieldDomId(fieldId)}-radio`;\n  }\n\n  fieldCheckboxName(fieldId) {\n    return `${this.fieldDomId(fieldId)}-check`;\n  }\n\n  /**\n   * Field type as rendered. Any field whose label says \"charm\" (or carries charm_type) is drawn as a\n   * radio grid even when the API types it 'dropdown', so value reads must follow the rendered widget.\n   */\n  effectiveFieldType(field) {\n    if (!field) return '';\n    const normLabel = String(field.label || '').toLowerCase();\n    if (normLabel.includes('charm') || normLabel.includes('cham') || field.charm_type) return 'charm';\n    return field.field_type;\n  }\n\n  /** True when the field is rendered as a radio group (radio or charm grid). */\n  usesRadioInput(field) {\n    const t = this.effectiveFieldType(field);\n    return t === 'radio' || t === 'charm';\n  }\n\n  getFieldInput(fieldOrId) {\n    const logical =\n      fieldOrId && typeof fieldOrId === 'object' ? fieldOrId.id : fieldOrId;\n    const lid = String(logical ?? '');\n    if (!lid) return null;\n    const esc = CSS.escape(lid);\n    const byData = this.querySelector(`[data-field-id=\"${esc}\"].bling-field-input`);\n    if (byData) return byData;\n    const hidden = this.querySelector(\n      `.bling-imgselect[data-field-id=\"${esc}\"] .bling-field-input`,\n    );\n    if (hidden) return hidden;\n    return this.querySelector(`#${CSS.escape(this.fieldDomId(lid))}`);\n  }\n\n  async init() {\n    const configId = this.dataset.config;\n    if (!configId) {\n      console.error('[Bling] Missing data-config attribute');\n      return;\n    }\n\n    const configEl = document.getElementById(configId);\n    if (!configEl) {\n      console.error(`[Bling] Config element not found: ${configId}`);\n      return;\n    }\n\n    try {\n      this.config = JSON.parse(configEl.textContent);\n    } catch (err) {\n      console.error('[Bling] Failed to parse config JSON:', err);\n      return;\n    }\n\n    this.abortController = new AbortController();\n\n    try {\n      const form = this._findCartForm();\n      const initialVariant = form ? form.querySelector('[name=\"id\"]')?.value : null;\n      let finalApiUrl = this.config.api_url;\n      if (initialVariant) {\n        try {\n          const u = new URL(finalApiUrl);\n          u.searchParams.set('variant_id', initialVariant);\n          finalApiUrl = u.toString();\n        } catch (e) {}\n      }\n\n      // Attempt to warm the UI immediately from sessionStorage cache.\n      // hasCachedForm tracks whether the customer already sees a working form\n      // so that a transient background-revalidation failure does NOT destroy it.\n      const cached = this._readCfgCache(initialVariant);\n      let hasCachedForm = false;\n      if (cached) {\n        this._hydrateFromApiData(cached);\n        if (this._shouldShowCustomization(cached)) {\n          this._bootstrapFromFields({ warmOverlay: true });\n          hasCachedForm = true;\n        }\n      }\n\n      // Live fetch with one automatic retry (1.5 s apart) before giving up.\n      // _fetchWithRetry returns the parsed JSON or null \u2014 it never throws.\n      const json = await this._fetchWithRetry(finalApiUrl);\n\n      if (json === null) {\n        // Network/timeout failure after both attempts.\n        if (hasCachedForm) {\n          // Form is already visible and working from cache \u2014 keep it, stay silent.\n          console.warn('[Bling] Live revalidation failed (cached form retained).');\n          return;\n        }\n        // Nothing was shown to the customer \u2014 show the error box.\n        this.renderFieldsLoadError();\n        return;\n      }\n\n      if (json.error) {\n        // Platform returned a business-logic error.\n        if (hasCachedForm) {\n          console.warn('[Bling] Platform error on revalidation (cached form retained):', json.error);\n          return;\n        }\n        this.renderFieldsLoadError();\n        return;\n      }\n\n      const data = json?.data || {};\n      this._writeCfgCache(initialVariant, data);\n      this._hydrateFromApiData(data);\n\n      if (!this._shouldShowCustomization(data)) {\n        if (!this.fields.length) {\n          console.log('[Bling] No customization fields found for this product.');\n        }\n        this.innerHTML = '';\n        this._fieldsLoaded = false;\n        this.style.display = 'none';\n        const parentBlock = this.closest('.bling-customization-block');\n        if (parentBlock) parentBlock.style.display = 'none';\n        return;\n      }\n\n      void this.fetchPreviewSettings();\n      this._bootstrapFromFields({ warmOverlay: false });\n\n    } catch (error) {\n      if (error.name === 'AbortError') {\n        console.log('[Bling] Request aborted');\n        return;\n      }\n      // Unexpected synchronous error (e.g. JSON.parse on config element).\n      console.error('[Bling] Unexpected error during init:', error);\n      this.renderFieldsLoadError();\n    }\n  }\n\n  /**\n   * Fetch the given URL and return the parsed JSON on success, or null on any\n   * failure (network error, non-2xx status).  Retries once after 1.5 s when\n   * the AbortController has not yet been signalled.  Never throws.\n   */\n  async _fetchWithRetry(url, retries = 1, delayMs = 1500) {\n    for (let attempt = 0; attempt <= retries; attempt++) {\n      try {\n        if (attempt > 0) {\n          // Wait before the retry, but abort immediately if the page navigates away.\n          await new Promise((resolve, reject) => {\n            const t = setTimeout(resolve, delayMs);\n            const onAbort = () => { clearTimeout(t); reject(new DOMException('Aborted', 'AbortError')); };\n            this.abortController?.signal.addEventListener('abort', onAbort, { once: true });\n          });\n        }\n        const res = await fetch(url, {\n          signal: this.abortController?.signal,\n          cache: 'no-store',\n        });\n        if (!res.ok) {\n          console.warn(`[Bling] Fetch attempt ${attempt + 1} failed with HTTP ${res.status}`);\n          continue;\n        }\n        return await res.json();\n      } catch (err) {\n        if (err.name === 'AbortError') throw err; // propagate so caller sees the abort\n        console.warn(`[Bling] Fetch attempt ${attempt + 1} error:`, err.message || err);\n      }\n    }\n    return null; // all attempts exhausted\n  }\n\n  renderFieldsLoadError() {\n    this._fieldsLoaded = false;\n    this.innerHTML = `\n      <div class=\"bling-error-fallback\" role=\"alert\" style=\"padding: 12px 16px; margin: 12px 0; background: #fff5f5; border: 1px solid #fed7d7; border-radius: 8px; font-size: 13px; color: #c53030; display: flex; align-items: center; gap: 8px;\">\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n          <path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\" clip-rule=\"evenodd\"/>\n        </svg>\n        <span>Unable to load personalization options right now. Please <a href=\"javascript:location.reload()\" style=\"text-decoration: underline; font-weight: 600; color: #9b2c2c;\">refresh</a> the page or contact support.</span>\n      </div>\n    `;\n  }\n\n  async fetchPreviewSettings() {\n    try {\n      const res = await fetch(`${this.config.platform_url}/api/customization/preview`);\n      if (res.ok) {\n        const json = await res.json();\n        this.previewSettings = json.data || json;\n      }\n    } catch (err) {\n      console.log('[Bling] Preview settings not available');\n    }\n  }\n\n  getPreviewCount() {\n    try {\n      const stored = localStorage.getItem('bling_preview_limits');\n      return stored ? JSON.parse(stored) : { products: {}, total: 0, today: { date: new Date().toISOString().split('T')[0], count: 0 } };\n    } catch {\n      return { products: {}, total: 0, today: { date: new Date().toISOString().split('T')[0], count: 0 } };\n    }\n  }\n\n  savePreviewCount() {\n    try {\n      localStorage.setItem('bling_preview_limits', JSON.stringify(this.previewCount));\n    } catch (err) {\n      console.error('[Bling] Failed to save preview count:', err);\n    }\n  }\n\n  canGeneratePreview() {\n    if (!this.previewSettings || !this.previewSettings.enabled) {\n      return { can: false, reason: 'Preview feature is disabled' };\n    }\n\n    // Test mode: no limits (staging/QA).\n    if (this.previewSettings.test_mode) {\n      return { can: true };\n    }\n\n    const productId = this.config.product_id;\n    const today = new Date().toISOString().split('T')[0];\n\n    // Reset daily count if new day\n    if (this.previewCount.today.date !== today) {\n      this.previewCount.today = { date: today, count: 0 };\n    }\n\n    const perProduct = this.previewCount.products[productId] || 0;\n    const perUser = this.previewCount.total;\n    const perDay = this.previewCount.today.count;\n\n    if (perProduct >= this.previewSettings.max_previews_per_product) {\n      return { can: false, reason: `You've reached the limit of ${this.previewSettings.max_previews_per_product} previews for this product` };\n    }\n\n    if (perUser >= this.previewSettings.max_previews_per_user) {\n      return { can: false, reason: `You've reached your preview limit of ${this.previewSettings.max_previews_per_user} previews` };\n    }\n\n    if (perDay >= this.previewSettings.max_previews_per_day_per_user) {\n      return { can: false, reason: `You've reached the daily limit of ${this.previewSettings.max_previews_per_day_per_user} previews` };\n    }\n\n    return { can: true };\n  }\n\n  incrementPreviewCount() {\n    const productId = this.config.product_id;\n    this.previewCount.products[productId] = (this.previewCount.products[productId] || 0) + 1;\n    this.previewCount.total += 1;\n    this.previewCount.today.count += 1;\n    this.savePreviewCount();\n  }\n\n  _cfgCacheKey(variantId) {\n    const pid = String(this.config?.product_id || '').replace(/\\D/g, '') || '0';\n    const vid = variantId ? String(variantId).replace(/\\D/g, '') : '0';\n    return `bling_cfg_${pid}_${vid}_v${BlingCustomizationForm.CFG_CACHE_VERSION}`;\n  }\n\n  _readCfgCache(variantId) {\n    try {\n      const raw = sessionStorage.getItem(this._cfgCacheKey(variantId));\n      if (!raw) return null;\n      const parsed = JSON.parse(raw);\n      if (!parsed || parsed.v !== BlingCustomizationForm.CFG_CACHE_VERSION) return null;\n      if (!parsed.ts || Date.now() - parsed.ts > BlingCustomizationForm.CFG_CACHE_TTL_MS) return null;\n      return parsed.data || null;\n    } catch {\n      return null;\n    }\n  }\n\n  _writeCfgCache(variantId, data) {\n    try {\n      sessionStorage.setItem(\n        this._cfgCacheKey(variantId),\n        JSON.stringify({\n          v: BlingCustomizationForm.CFG_CACHE_VERSION,\n          ts: Date.now(),\n          data,\n        }),\n      );\n    } catch {\n      /* quota / private mode */\n    }\n  }\n\n  _normalizeField(f) {\n    if (!f || typeof f !== 'object') return f;\n    const typeMap = { name: 'text', image: 'file', audio: 'file' };\n    const rawType = String(f.field_type || '').toLowerCase();\n    const normalizedType = typeMap[rawType] || f.field_type;\n    return {\n      ...f,\n      field_type: normalizedType,\n    };\n  }\n\n  _hydrateFromApiData(data) {\n    const raw = Array.isArray(data?.fields) ? data.fields.map(f => this._normalizeField(f)) : [];\n    this.fields = raw.slice().sort((a, b) => {\n      const oa = Number(a?.field_order);\n      const ob = Number(b?.field_order);\n      const na = Number.isFinite(oa) ? oa : 0;\n      const nb = Number.isFinite(ob) ? ob : 0;\n      if (na !== nb) return na - nb;\n      return String(a?.id || '').localeCompare(String(b?.id || ''));\n    });\n    this.configId = data?.config_id || null;\n    this.templateId = data?.template_id || null;\n    if (!this._logosByField) this._logosByField = new Map();\n    if (!this._logoUrlByField) this._logoUrlByField = new Map();\n    this.canvasConfig = data?.canvas || null;\n    this.livePreviewOn = this.hasLiveCanvasPreview();\n\n    const isVariantOwnLayout = Boolean(this.canvasConfig && this.canvasConfig.is_variant_own_layout);\n    const activeMediaIndex = typeof this._getActiveMediaIndex === 'function' ? this._getActiveMediaIndex() : 0;\n    const mainMediaIndex = typeof this._canvasBaseIndex === 'function' ? this._canvasBaseIndex() : 0;\n    const isMainImageActive = activeMediaIndex === mainMediaIndex;\n\n    if (this.canvasConfig && !isVariantOwnLayout && !isMainImageActive) {\n      this._shouldSwitchToMainOnInput = true;\n      if (this._zoneCanvas) {\n        this._zoneCanvas.style.display = 'none';\n      }\n    } else {\n      this._shouldSwitchToMainOnInput = false;\n      if (this._zoneCanvas) {\n        this._zoneCanvas.style.display = 'block';\n      }\n    }\n\n    this._observeVariantChanges();\n    if (!this._liveSyncObserved) {\n      this._liveSyncObserved = true;\n      this._observeLiveConfigChanges();\n    }\n  }\n\n  _shouldShowCustomization(data) {\n    return (\n      this.fields.length > 0 &&\n      !!data?.is_enabled &&\n      !!this.configId\n    );\n  }\n\n  _bootstrapFromFields({ warmOverlay }) {\n    this._fieldsLoaded = true;\n    this.injectStyles();\n    this.injectImgSelectStyles();\n    this.interceptAddToCartButton();\n    this.showInlineForm();\n    if (this.canvasConfig && this.hasLiveCanvasPreview()) {\n      const paint = () => {\n        this.setupZoneOverlay();\n        if (this._shouldSwitchToMainOnInput && this._zoneCanvas) {\n          const ctx = this._zoneCanvas.getContext('2d');\n          if (ctx) ctx.clearRect(0, 0, this._zoneCanvas.width, this._zoneCanvas.height);\n          this._zoneCanvas.style.display = 'none';\n        } else {\n          this.ensurePlaceholderImages().then(() => this.redrawLivePreview());\n        }\n      };\n      if (warmOverlay) requestAnimationFrame(paint);\n      else paint();\n    }\n  }\n\n  applyDefaultCharmSelections() {\n    for (const field of this.fields || []) {\n      if (!this.isCharmField(field)) continue;\n      const cur = this.getFieldValue(field);\n      if (cur != null && String(cur).trim() !== '') continue;\n      const opts = this.getOptions(field).filter((o) => o && o.image);\n      const pick =\n        opts.find((o) => String(o.value) === 'charm_01') ||\n        opts.find((o) => /^charm\\s*0?1$/i.test(String(o.label || ''))) ||\n        opts[0];\n      if (!pick) continue;\n      if (this.usesRadioInput(field)) {\n        const radio = this.querySelector(\n          `input[name=\"${CSS.escape(this.fieldRadioName(field.id))}\"][value=\"${CSS.escape(String(pick.value))}\"]`,\n        );\n        if (radio) radio.checked = true;\n      } else {\n        const input = this.getFieldInput(field);\n        if (input) input.value = String(pick.value);\n        const box = this.querySelector(`.bling-imgselect[data-field-id=\"${CSS.escape(String(field.id))}\"]`);\n        const trigger = box?.querySelector('.bling-imgselect-current');\n        if (trigger) {\n          const imgUrl = this.optionImageUrl(pick.image);\n          trigger.innerHTML = imgUrl\n            ? `<img class=\"bling-imgselect-thumb\" src=\"${imgUrl}\" alt=\"\" loading=\"lazy\"><span>${pick.label || pick.value}</span>`\n            : `${pick.label || pick.value}`;\n        }\n      }\n    }\n    this.syncImageOptionLogos();\n    this.redrawLivePreview();\n  }\n\n  getOrCreateSessionId() {\n    if (!this.sessionId) {\n      this.sessionId = `bling_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n    }\n    return this.sessionId;\n  }\n\n  injectStyles() {\n    if (this.cssInjected) return;\n    \n    if (this.config && this.config.css_url) {\n      const link = document.createElement('link');\n      link.rel = 'stylesheet';\n      link.href = this.config.css_url;\n      document.head.appendChild(link);\n    }\n    \n    const style = document.createElement('style');\n    style.id = 'bling-luxury-light-mode-styles';\n    style.textContent = `\n      bling-customization-form .bling-field-input,\n      bling-customization-form .bling-imgselect-trigger {\n        border-radius: 10px !important;\n        border: 1.5px solid #e2e8f0 !important;\n        background: #ffffff !important;\n        color: #0f172a !important;\n        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04) !important;\n      }\n      bling-customization-form .bling-field-input:focus,\n      bling-customization-form .bling-imgselect-trigger:focus {\n        border-color: #0f172a !important;\n        box-shadow: 0 0 0 3px rgba(15, 23, 42, 0.08) !important;\n        outline: none !important;\n      }\n      .bling-file-dropzone-wrapper {\n        position: relative;\n        width: 100%;\n      }\n      .bling-file-hidden-input {\n        position: absolute !important;\n        width: 1px !important;\n        height: 1px !important;\n        padding: 0 !important;\n        margin: -1px !important;\n        overflow: hidden !important;\n        clip: rect(0, 0, 0, 0) !important;\n        border: 0 !important;\n        opacity: 0 !important;\n      }\n      .bling-file-dropzone-label {\n        display: flex !important;\n        flex-direction: column !important;\n        align-items: center !important;\n        justify-content: center !important;\n        padding: 20px 14px !important;\n        border: 1.5px dashed #cbd5e1 !important;\n        border-radius: 12px !important;\n        background: #f8fafc !important;\n        cursor: pointer !important;\n        transition: all 0.2s ease !important;\n        text-align: center !important;\n        margin: 0 !important;\n      }\n      .bling-file-dropzone-label:hover {\n        border-color: #94a3b8 !important;\n        background: #f1f5f9 !important;\n      }\n      .bling-file-dropzone-icon {\n        width: 24px;\n        height: 24px;\n        color: #64748b;\n        margin-bottom: 5px;\n      }\n      .bling-file-dropzone-text {\n        font-size: 13px !important;\n        font-weight: 600 !important;\n        color: #1e293b !important;\n      }\n      .bling-file-dropzone-sub {\n        font-size: 11px !important;\n        color: #94a3b8 !important;\n        margin-top: 2px !important;\n      }\n      .bling-file-selected-name {\n        font-size: 12px !important;\n        font-weight: 600 !important;\n        color: #0284c7 !important;\n        margin-top: 6px !important;\n        background: #e0f2fe;\n        padding: 2px 8px;\n        border-radius: 6px;\n        border: 1px solid #bae6fd;\n      }\n      .bling-charm-grid .bling-radio-label {\n        border-radius: 8px !important;\n        border: 1.5px solid #e2e8f0 !important;\n        background: #ffffff !important;\n        transition: all 0.15s ease !important;\n      }\n      .bling-charm-grid .bling-radio-label:hover {\n        border-color: #cbd5e1 !important;\n        background: #f8fafc !important;\n      }\n      .bling-charm-grid .bling-radio-label:has(input:checked) {\n        border-color: #d97706 !important;\n        background: #fffbeb !important;\n        box-shadow: 0 0 0 2px rgba(217, 119, 6, 0.25) !important;\n      }\n      .bling-submit-button {\n        background: rgb(var(--color-button, var(--color-foreground, 18 18 18))) !important;\n        color: rgb(var(--color-button-text, var(--color-background, 255 255 255))) !important;\n        border-radius: var(--buttons-radius, 0px) !important;\n        border: var(--buttons-border-thickness, 0.1rem) solid rgba(var(--color-button-border, var(--color-foreground, 18 18 18)), var(--buttons-border-opacity, 0.2)) !important;\n        font-family: var(--font-button-family, var(--font-body-family)) !important;\n        font-weight: 600 !important;\n        box-shadow: none !important;\n        cursor: pointer !important;\n        transition: all 0.2s ease !important;\n      }\n      .bling-submit-button:hover:not(:disabled) {\n        opacity: 0.9 !important;\n        filter: brightness(1.05) !important;\n      }\n    `;\n    document.head.appendChild(style);\n    \n    this.cssInjected = true;\n  }\n\n  _findCartForm() {\n    if (this.config && this.config.section_id) {\n      const sectionForm = document.getElementById('PdpForm-' + this.config.section_id);\n      if (sectionForm) return sectionForm;\n    }\n    return (\n      document.querySelector('form[action=\"/cart/add\"]') ||\n      document.querySelector('form[action*=\"cart/add\"]') ||\n      document.querySelector('product-form form')\n    );\n  }\n\n  interceptAddToCartButton() {\n    if (!this._fieldsLoaded) return;\n    this.injectStyles();\n\n    this.formSubmitHandler = async (e) => {\n      const sessionInput = e.target.querySelector('input[name=\"properties[_bling_session]\"]');\n      if (sessionInput && sessionInput.value) {\n        return;\n      }\n      e.preventDefault();\n      e.stopPropagation();\n      this.isBuyNow = false;\n      await this.submitCustomizationAndContinue();\n    };\n\n    const form = this._findCartForm();\n    if (form) {\n      this._bindFormHandlers(form);\n    } else {\n      const observer = new MutationObserver(() => {\n        const f = this._findCartForm();\n        if (f) {\n          observer.disconnect();\n          this._bindFormHandlers(f);\n        }\n      });\n      observer.observe(document.body, { childList: true, subtree: true });\n      this.formObserver = observer;\n    }\n\n    this.showInlineForm();\n  }\n\n  _bindFormHandlers(form) {\n    form.addEventListener('submit', this.formSubmitHandler, true);\n\n    const nativeBuyNow = document.getElementById('PdpBuyNowBtn-' + this.config.section_id);\n    if (nativeBuyNow) {\n      const handler = async (e) => {\n        if (nativeBuyNow.disabled || nativeBuyNow.hasAttribute('disabled')) {\n          return;\n        }\n        e.preventDefault();\n        e.stopPropagation();\n        this.isBuyNow = true;\n        await this.submitCustomizationAndContinue();\n      };\n      this.paymentButtonListeners.set(nativeBuyNow, handler);\n      nativeBuyNow.addEventListener('click', handler, true);\n    }\n  }\n\n  showInlineForm() {\n    if (!this.fields || this.fields.length === 0) {\n      this.innerHTML = '';\n      return;\n    }\n    if (this.formVisible) return;\n    \n    this.formVisible = true;\n    this.sessionId = this.getOrCreateSessionId();\n    this.render();\n  }\n\n  render() {\n    if (!this.fields || this.fields.length === 0) {\n      this.innerHTML = '';\n      return;\n    }\n    const hasRequiredFields = this.fields.some(f => f.is_required);\n    \n    this.innerHTML = `\n      <div class=\"bling-inline-form bling-collapsible-card\">\n        <div class=\"bling-collapse-header\" id=\"bling-collapse-toggle\" role=\"button\" tabindex=\"0\" aria-expanded=\"${this._defaultExpanded()}\">\n          <div class=\"bling-collapse-title-wrap\">\n            <span class=\"bling-collapse-sparkle\">\u2726</span>\n            <span class=\"bling-collapse-title\">Customize Your Order</span>\n            <span class=\"bling-collapse-badge\">Personalize</span>\n          </div>\n          <div class=\"bling-collapse-icon-wrap\">\n            <svg class=\"bling-collapse-chevron\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n              <polyline points=\"6 9 12 15 18 9\"></polyline>\n            </svg>\n          </div>\n        </div>\n\n        <div class=\"bling-collapse-content${this._defaultExpanded() === 'true' ? '' : ' is-collapsed'}\" id=\"bling-collapse-body\">\n          <div class=\"bling-fields-container\">\n            ${this.canvasConfig && this.hasLiveCanvasPreview() ? `\n            <label class=\"bling-live-toggle bling-field-group--wide bling-field-group--full\">\n              <input type=\"checkbox\" id=\"bling-live-toggle\" checked>\n              <span>Live preview on product image</span>\n            </label>\n            ` : ''}\n            ${(function() {\n              this._fieldSpanMap = this._computeFieldLayoutSpans(this.fields);\n              return this.fields.map(field => {\n                field.displayLabel = field.label;\n                return this.renderField(field);\n              }).join('');\n            }).call(this)}\n          </div>\n          \n          <div class=\"bling-form-actions\">\n            <button type=\"button\" class=\"bling-submit-button\" id=\"bling-submit-btn\" ${hasRequiredFields ? 'disabled' : ''}>\n              ${this.isBuyNow ? 'Continue to Checkout' : 'Add to Cart'}\n            </button>\n          </div>\n          \n          <div class=\"bling-error-message\" id=\"bling-error\" style=\"display: none;\"></div>\n        </div>\n      </div>\n    `;\n    \n    this.setupCollapsibleToggle();\n    this.loadGoogleFonts();\n    this.attachEventListeners();\n    this.applyDefaultCharmSelections();\n    this.setupLivePreview();\n  }\n\n  /** Shopify section setting \"Customize Your Order: open by default\" (data-config `default_expanded`; absent => open). */\n  _defaultExpanded() {\n    const v = this.config && this.config.default_expanded;\n    return v === false || v === 'false' || v === 0 ? 'false' : 'true';\n  }\n\n  setupCollapsibleToggle() {\n    const toggle = this.querySelector('#bling-collapse-toggle');\n    const content = this.querySelector('#bling-collapse-body');\n    if (!toggle || !content) return;\n    const doToggle = () => {\n      const isExpanded = toggle.getAttribute('aria-expanded') === 'true';\n      toggle.setAttribute('aria-expanded', String(!isExpanded));\n      if (isExpanded) {\n        content.classList.add('is-collapsed');\n      } else {\n        content.classList.remove('is-collapsed');\n      }\n    };\n    toggle.addEventListener('click', doToggle);\n    toggle.addEventListener('keydown', (e) => {\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        doToggle();\n      }\n    });\n  }\n\n  renderField(field) {\n    const isRequired = field.is_required ? 'required' : '';\n    const requiredLabel = field.is_required ? '<span class=\"bling-required\">*</span>' : '';\n    const domId = this.fieldDomId(field.id);\n    const radioName = this.fieldRadioName(field.id);\n    const checkboxName = this.fieldCheckboxName(field.id);\n    \n    let inputHtml = '';\n    \n    // Protect charm fields: if label includes 'charm' or 'cham', it must NEVER render as a file upload!\n    const effectiveType = this.effectiveFieldType(field);\n    \n    switch (effectiveType) {\n      case 'text':\n      case 'name':\n      case 'email':\n      case 'phone': {\n        const maxLen = this.getMaxLength(field);\n        inputHtml = `\n          <div class=\"bling-input-wrapper\">\n            <input\n              type=\"${field.field_type === 'email' ? 'email' : field.field_type === 'phone' ? 'tel' : 'text'}\"\n              id=\"${domId}\"\n              class=\"bling-field-input\"\n              placeholder=\"${field.placeholder || field.displayLabel || field.label || ''}\"\n              ${maxLen ? `maxlength=\"${maxLen}\"` : ''}\n              ${isRequired}\n              data-field-id=\"${field.id}\"\n            />\n            ${maxLen ? `<span class=\"bling-charcount-badge\" data-counter-for=\"${field.id}\" data-max=\"${maxLen}\">0/${maxLen}</span>` : ''}\n          </div>\n        `;\n        break;\n      }\n        \n      case 'textarea': {\n        const maxLen = this.getMaxLength(field);\n        inputHtml = `\n          <div class=\"bling-input-wrapper bling-input-wrapper--textarea\">\n            <textarea\n              id=\"${domId}\"\n              class=\"bling-field-input\"\n              placeholder=\"${field.placeholder || field.displayLabel || field.label || ''}\"\n              rows=\"3\"\n              ${maxLen ? `maxlength=\"${maxLen}\"` : ''}\n              ${isRequired}\n              data-field-id=\"${field.id}\"\n            ></textarea>\n            ${maxLen ? `<span class=\"bling-charcount-badge\" data-counter-for=\"${field.id}\" data-max=\"${maxLen}\">0/${maxLen}</span>` : ''}\n          </div>\n        `;\n        break;\n      }\n        \n      case 'font':\n      case 'dropdown': {\n        const options = this.getOptions(field);\n        const hasImages = options.some(o => o && o.image);\n        const hasFonts = options.some(o => o && o.font);\n        \n        if (hasImages || hasFonts) {\n          inputHtml = `\n            <div class=\"bling-imgselect${hasFonts ? ' bling-fontselect' : ''}\" data-field-id=\"${field.id}\">\n              <input type=\"hidden\" id=\"${domId}\" class=\"bling-field-input\" data-field-id=\"${field.id}\" value=\"\" />\n              <button type=\"button\" class=\"bling-imgselect-trigger\" aria-haspopup=\"listbox\" aria-expanded=\"false\">\n                <span class=\"bling-imgselect-current\">Select...</span>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M5 8l5 5 5-5\"/></svg>\n              </button>\n              <ul class=\"bling-imgselect-menu\" role=\"listbox\">\n                ${options.map(opt => `\n                  <li class=\"bling-imgselect-option\" role=\"option\" data-value=\"${opt.value}\">\n                    ${opt.image ? `<img class=\"bling-imgselect-thumb\" src=\"${this.optionImageUrl(opt.image)}\" alt=\"${opt.label || ''}\" loading=\"lazy\">` : ''}\n                    <span${opt.font ? ` class=\"bling-font-preview\" style=\"font-family: ${this.cssFontFamily(opt.font)};\"` : ''}>${opt.label || opt.value || opt.font || \"Option\"}</span>\n                  </li>`).join('')}\n              </ul>\n            </div>\n          `;\n        } else {\n          inputHtml = `\n            <select\n              id=\"${domId}\"\n              class=\"bling-field-input\"\n              ${isRequired}\n              data-field-id=\"${field.id}\"\n            >\n              <option value=\"\">Select...</option>\n              ${options.map(opt => `<option value=\"${opt.value}\" ${opt.font ? `style=\"font-family: ${this.cssFontFamily(opt.font)};\"` : ''}>${opt.label || opt.value || opt.font || \"Option\"}</option>`).join('')}\n            </select>\n          `;\n        }\n        break;\n      }\n        \n      case 'charm':\n      case 'radio': {\n        const radioOptions = this.getOptions(field);\n        const hasImages = radioOptions.some((o) => o && o.image);\n        const noneValue = hasImages\n          ? (radioOptions.find((o) => o && (!o.image || /^none$/i.test(String(o.label || '')) || /^none$/i.test(String(o.value || ''))))?.value)\n          : null;\n        inputHtml = `\n          <div class=\"bling-radio-group${hasImages ? ' bling-charm-grid' : ''}\">\n            ${radioOptions.map(opt => `\n              <label class=\"bling-radio-label${opt.image ? ' bling-has-image' : ''}\" title=\"${(opt.label || '').replace(/\"/g, '&quot;')}\">\n                ${opt.image ? `<img class=\"bling-option-image\" src=\"${this.optionImageUrl(opt.image)}\" alt=\"${opt.label || ''}\" loading=\"lazy\">` : ''}\n                <input\n                  type=\"radio\"\n                  name=\"${radioName}\"\n                  value=\"${opt.value}\"\n                  ${isRequired}\n                  data-field-id=\"${field.id}\"\n                  ${noneValue != null && String(opt.value) === String(noneValue) ? 'checked' : ''}\n                />\n                <span class=\"bling-option-label\">${opt.label || opt.value || opt.font || \"Option\"}</span>\n              </label>\n            `).join('')}\n          </div>\n        `;\n        break;\n      }\n        \n      case 'checkbox': {\n        const checkboxOptions = this.getOptions(field);\n        inputHtml = `\n          <div class=\"bling-checkbox-group\">\n            ${checkboxOptions.map(opt => `\n              <label class=\"bling-checkbox-label${opt.image ? ' bling-has-image' : ''}\">\n                ${opt.image ? `<img class=\"bling-option-image\" src=\"${this.optionImageUrl(opt.image)}\" alt=\"${opt.label || ''}\" loading=\"lazy\">` : ''}\n                <input\n                  type=\"checkbox\"\n                  name=\"${checkboxName}\"\n                  value=\"${opt.value}\"\n                  data-field-id=\"${field.id}\"\n                />\n                <span>${opt.label || opt.value || opt.font || \"Option\"}</span>\n              </label>\n            `).join('')}\n          </div>\n        `;\n        break;\n      }\n        \n      case 'image':\n      case 'file':\n        inputHtml = `\n          <div class=\"bling-file-dropzone-wrapper\">\n            <input\n              type=\"file\"\n              id=\"${domId}\"\n              class=\"bling-field-input bling-file-hidden-input\"\n              accept=\"${field.field_type === 'image' ? 'image/*' : '*/*'}\"\n              ${isRequired}\n              data-field-id=\"${field.id}\"\n            />\n            <label for=\"${domId}\" class=\"bling-file-dropzone-label\">\n              <svg class=\"bling-file-dropzone-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/>\n                <polyline points=\"17 8 12 3 7 8\"/>\n                <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"/>\n              </svg>\n              <span class=\"bling-file-dropzone-text\">Click to upload or drag & drop</span>\n              <span class=\"bling-file-dropzone-sub\">PNG, JPG, SVG up to 25MB</span>\n              <span class=\"bling-file-selected-name\" id=\"bling-filename-${domId}\" style=\"display: none;\"></span>\n            </label>\n            <div class=\"bling-upload-progress\" id=\"bling-progress-${domId}\" style=\"display: none;\"></div>\n          </div>\n        `;\n        break;\n        \n      default:\n        inputHtml = `\n          <input\n            type=\"text\"\n            id=\"${domId}\"\n            class=\"bling-field-input\"\n            placeholder=\"${field.placeholder || field.displayLabel || field.label || ''}\"\n            ${isRequired}\n            data-field-id=\"${field.id}\"\n          />\n        `;\n    }\n    \n    const groupClass = ['bling-field-group'];\n    if (this._isTextGridField(field)) groupClass.push('bling-field-group--text');\n    if (this._isWideField(field)) groupClass.push('bling-field-group--wide', 'bling-field-group--full');\n    const spanType = this._fieldSpanMap ? this._fieldSpanMap.get(String(field.id)) : null;\n    if (spanType === 'span-full') {\n      groupClass.push('bling-field-group--span-full');\n    } else if (spanType === 'span-half') {\n      groupClass.push('bling-field-group--span-half');\n    }\n    const label = String(field.label || '').toLowerCase();\n    if (label.includes('font')) groupClass.push('bling-field-group--font');\n    if (label.includes('charm') || field.field_type === 'charm') groupClass.push('bling-field-group--charm');\n    if (field.field_type === 'dropdown' || field.field_type === 'radio') groupClass.push('bling-field-group--dropdown');\n    if (field.field_type === 'file' || field.field_type === 'image') groupClass.push('bling-field-group--file');\n\n    return `\n      <div class=\"${groupClass.join(' ')}\">\n        <label class=\"bling-field-label\" for=\"${domId}\">\n          ${field.displayLabel || field.label}${requiredLabel}\n        </label>\n        ${field.help_text ? `<p class=\"bling-field-help\">${field.help_text}</p>` : ''}\n        ${inputHtml}\n      </div>\n    `;\n  }\n\n  _isTextGridField(field) {\n    const t = field.field_type;\n    return t === 'text' || t === 'name' || t === 'email' || t === 'phone';\n  }\n\n  _isWideField(_field) {\n    return false;\n  }\n\n  _computeFieldLayoutSpans(fields) {\n    // If field explicitly specifies is_half_width, honor it (half = 1 col; full = 2 cols).\n    // Otherwise fall back to shared pairs side by side layout.\n    const compactFields = Array.isArray(fields) ? [...fields] : [];\n    const hasExplicitSpan = compactFields.some((f) => f && typeof f.is_half_width === 'boolean');\n    if (hasExplicitSpan) {\n      const spanMap = new Map();\n      const count = compactFields.length;\n      for (let i = 0; i < count; i++) {\n        const f = compactFields[i];\n        const id = String(f.id);\n        if (f.is_half_width === true) {\n          spanMap.set(id, 'span-half');\n        } else if (f.is_half_width === false) {\n          spanMap.set(id, 'span-full');\n        } else {\n          if (count === 1 || (count % 2 === 1 && i === count - 1)) {\n            spanMap.set(id, 'span-full');\n          } else {\n            spanMap.set(id, 'span-half');\n          }\n        }\n      }\n      return spanMap;\n    }\n    const layout = window.BlingFieldLayout;\n    if (layout && typeof layout.computeFieldLayoutSpans === 'function') {\n      const raw = layout.computeFieldLayoutSpans(fields);\n      if (typeof layout.toStorefrontSpanMap === 'function') {\n        return layout.toStorefrontSpanMap(raw);\n      }\n      const spanMap = new Map();\n      raw.forEach((span, id) => {\n        spanMap.set(id, span === 'span-1' ? 'span-half' : span);\n      });\n      return spanMap;\n    }\n    const spanMap = new Map();\n    const count = compactFields.length;\n    for (let i = 0; i < count; i++) {\n      if (count === 1 || (count % 2 === 1 && i === count - 1)) {\n        spanMap.set(String(compactFields[i].id), 'span-full');\n      } else {\n        spanMap.set(String(compactFields[i].id), 'span-half');\n      }\n    }\n    return spanMap;\n  }\n\n  getOptions(field) {\n    let opts = [];\n    if (Array.isArray(field.options)) opts = field.options;\n    else if (field.options_json) {\n      try { opts = JSON.parse(field.options_json); } catch { opts = []; }\n    }\n    const isFont = field.field_type === 'font' || String(field.label || '').toLowerCase().includes('font');\n    if (isFont && (!opts || opts.length === 0)) {\n      return [\n        { label: 'Playfair Display (Serif)', value: 'Playfair Display', font: 'Playfair Display' },\n        { label: 'Montserrat (Modern Sans)', value: 'Montserrat', font: 'Montserrat' },\n        { label: 'Dancing Script (Cursive)', value: 'Dancing Script', font: 'Dancing Script' },\n        { label: 'Cinzel (Engraved / Formal)', value: 'Cinzel', font: 'Cinzel' },\n        { label: 'Great Vibes (Calligraphy)', value: 'Great Vibes', font: 'Great Vibes' },\n        { label: 'Pacifico (Casual Handwriting)', value: 'Pacifico', font: 'Pacifico' },\n        { label: 'Oswald (Bold Compact)', value: 'Oswald', font: 'Oswald' },\n        { label: 'Roboto Slab (Slab Serif)', value: 'Roboto Slab', font: 'Roboto Slab' },\n        { label: 'Sacramento (Fine Script)', value: 'Sacramento', font: 'Sacramento' },\n        { label: 'Satisfy (Smooth Brush)', value: 'Satisfy', font: 'Satisfy' },\n        { label: 'Allura (Flowing Script)', value: 'Allura', font: 'Allura' },\n        { label: 'Lobster (Bold Script)', value: 'Lobster', font: 'Lobster' },\n      ];\n    }\n    const isCharm = field.field_type === 'charm' || String(field.label || '').toLowerCase().includes('charm');\n    if (isCharm && (!opts || opts.length === 0)) {\n      const charmOpts = [];\n      const SHOP_CDN = 'https://cdn.shopify.com/s/files/1/0614/2902/2833/files';\n      for (let n = 1; n <= 50; n++) {\n        const pad = String(n).padStart(2, '0');\n        charmOpts.push({\n          label: `Charm ${pad}`,\n          value: `charm_${pad}`,\n          image: `${SHOP_CDN}/All_Charms_image_${n}.png`,\n        });\n      }\n      return charmOpts;\n    }\n    return opts;\n  }\n\n  // Build a viewable URL for an option image (stored as an R2 key on the platform).\n  optionImageUrl(key) {\n    if (!key) return '';\n    if (/^https?:\\/\\//i.test(key)) return key;\n    // `cors=1`: distinct URL so browsers never reuse a copy cached before the endpoint sent CORS headers\n    // (needed to draw the charm on the live-preview canvas).\n    return `${this.config.platform_url}/api/uploads/file?key=${encodeURIComponent(key)}&cors=1`;\n  }\n\n  // Max character length for a field. Templates except T-shirts default to 15.\n  getMaxLength(field) {\n    let parsed = field && field.validation;\n    if (!parsed && field && field.validation_json) {\n      try { parsed = JSON.parse(field.validation_json); } catch { parsed = null; }\n    }\n    // 9999 or higher means admin explicitly chose NO character limit (unlimited).\n    if (parsed && typeof parsed.maxLength === 'number' && parsed.maxLength >= 9999) {\n      return null;\n    }\n    let max = null;\n    if (parsed && typeof parsed.maxLength === 'number' && parsed.maxLength > 0) {\n      max = parsed.maxLength;\n    }\n    const template = String(this.templateId || '').toLowerCase();\n    const unlimited = template === 'tpl_tshirt' || template === 'tpl_tshirts';\n    const isText = field && ['text', 'textarea', 'name'].includes(field.field_type);\n    if (isText && !unlimited && max == null) max = 15;\n    return max;\n  }\n\n  // Safe CSS font-family value with a sensible fallback for live previews.\n  cssFontFamily(name) {\n    const safe = String(name).replace(/[\"\\\\]/g, '');\n    return `'${safe}', cursive, sans-serif`;\n  }\n\n  // Load every Google Font referenced by dropdown options so previews render in-font.\n  loadGoogleFonts() {\n    const families = new Set();\n    for (const f of this.fields) {\n      for (const o of this.getOptions(f)) {\n        if (o && o.font) families.add(String(o.font));\n      }\n    }\n    if (families.size === 0) return;\n    const query = [...families]\n      .map(fam => 'family=' + encodeURIComponent(fam).replace(/%20/g, '+'))\n      .join('&');\n    const href = `https://fonts.googleapis.com/css2?${query}&display=swap`;\n    let link = document.getElementById('bling-google-fonts');\n    if (!link) {\n      link = document.createElement('link');\n      link.id = 'bling-google-fonts';\n      link.rel = 'stylesheet';\n      document.head.appendChild(link);\n    }\n    if (link.getAttribute('href') !== href) link.setAttribute('href', href);\n  }\n\n  // ---------- Free live canvas preview (no AI / no cost) ----------\n\n  hasTextPersonalization() {\n    return this.fields.some(f => ['text', 'name', 'textarea'].includes(f.field_type));\n  }\n\n  hasLogoPersonalization() {\n    return this.fields.some((f) => {\n      if (f.field_type === 'image' || f.field_type === 'file') return true;\n      if (f.field_type === 'radio' || f.field_type === 'dropdown') {\n        return this.getOptions(f).some((o) => o && o.image);\n      }\n      return false;\n    });\n  }\n\n  /** Overlay when canvas zones exist and at least one placeable field type is present. */\n  hasLiveCanvasPreview() {\n    return Boolean(\n      this.canvasConfig &&\n      Array.isArray(this.canvasConfig.zones) &&\n      this.canvasConfig.zones.length > 0\n    );\n  }\n\n  // Pull the main product photo from the storefront DOM.\n  getProductImageUrl() {\n    const img =\n      document.querySelector('.product__media img') ||\n      document.querySelector('[data-media-id] img') ||\n      document.querySelector('.product img');\n    return img ? (img.currentSrc || img.src) : '';\n  }\n\n  // Combine all text/name personalization values for the overlay.\n  gatherPreviewText() {\n    const parts = [];\n    for (const f of this.fields) {\n      if (['text', 'name', 'textarea'].includes(f.field_type)) {\n        const el = this.getFieldInput(f);\n        const v = el ? el.value.trim() : '';\n        if (v) parts.push(v);\n      }\n    }\n    return parts.join('  ');\n  }\n\n  // The font chosen in a font dropdown (option with a `font` property), if any.\n  getSelectedFont() {\n    for (const f of this.fields) {\n      const opts = this.getOptions(f);\n      if (!opts.some(o => o && o.font)) continue;\n      const val = this.getFieldValue(f);\n      const sel = opts.find(o => o && String(o.value) === String(val));\n      if (sel && sel.font) return sel.font;\n    }\n    return null;\n  }\n\n  setupLivePreview() {\n    if (!this.hasLiveCanvasPreview()) return;\n\n    // Multi-zone overlay drawn directly on the main product image.\n    if (this.canvasConfig && Array.isArray(this.canvasConfig.zones) && this.canvasConfig.zones.length) {\n      this.setupZoneOverlay();\n      this.syncImageOptionLogos();\n      return;\n    }\n\n    const url = this.getProductImageUrl();\n    const canvas = this.querySelector('#bling-live-canvas');\n    if (!url || !canvas) return;\n\n    const img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.onload = () => {\n      this._previewImg = img;\n      const maxW = 720;\n      const scale = img.naturalWidth > maxW ? maxW / img.naturalWidth : 1;\n      canvas.width = Math.round(img.naturalWidth * scale) || 600;\n      canvas.height = Math.round(img.naturalHeight * scale) || 600;\n      this.redrawLivePreview();\n    };\n    img.onerror = () => {\n      // Likely a CORS-tainted image: still draw via a non-sampling fallback path.\n      this._previewImg = null;\n    };\n    img.src = url;\n\n    if (document.fonts && document.fonts.ready) {\n      document.fonts.ready.then(() => this.drawLivePreview()).catch(() => {});\n    }\n  }\n\n  // Ensure the selected web font is loaded before drawing (canvas needs the real glyphs).\n  redrawLivePreview() {\n    const draw = () => {\n      if (this.canvasConfig && this._zoneCanvas) {\n        this.drawZones();\n        this.redrawThumbOverlays();\n      } else {\n        this.drawLivePreview();\n      }\n    };\n    const font = this.getSelectedFont();\n    if (font && document.fonts && document.fonts.load) {\n      document.fonts\n        .load(`32px '${String(font).replace(/['\\\\]/g, '')}'`)\n        .then(draw)\n        .catch(draw);\n    } else {\n      draw();\n    }\n  }\n\n  // ---------- Multi-zone overlay on the main product image ----------\n\n  /** Find the currently active gallery image, fallback to first image if none active. */\n  findMainGalleryImg() {\n    const active =\n      document.querySelector('.pdp-main-viewer .pdp-media-slide.active img') ||\n      document.querySelector('.pdp-main-viewer .pdp-media-slide.is-active img') ||\n      document.querySelector('.product__media-item.is-active img') ||\n      document.querySelector('.product__media-item.active img');\n      \n    if (active) return active;\n    \n    return (\n      document.querySelector('.pdp-main-viewer .pdp-media-slide[data-media-index=\"0\"] img') ||\n      document.querySelector('.pdp-main-viewer .pdp-media-slide:first-child img') ||\n      document.querySelector('.product__media-item[data-media-index=\"0\"] img') ||\n      document.querySelector('.product__media-item:first-child img') ||\n      document.querySelector('.pdp-main-viewer img') ||\n      document.querySelector('.product__media img') ||\n      null\n    );\n  }\n\n  findHeroImg() {\n    return this.findMainGalleryImg();\n  }\n\n  /** Strip Shopify CDN sizing/query so gallery URLs compare reliably. */\n  _normalizeImageUrl(url) {\n    if (!url) return '';\n    try {\n      const u = new URL(url, window.location.origin);\n      let p = u.pathname.toLowerCase();\n      p = p.replace(/_\\d+x\\d+(@2x)?(?=\\.[a-z]+$)/i, '');\n      return p;\n    } catch {\n      return String(url).split('?')[0].toLowerCase();\n    }\n  }\n\n  _filenameKey(url) {\n    const n = this._normalizeImageUrl(url);\n    const base = n.split('/').pop() || '';\n    return base.replace(/\\.[a-z0-9]+$/i, '');\n  }\n\n  _collectGallerySlides() {\n    const nodes = document.querySelectorAll(\n      '.pdp-main-viewer .pdp-media-slide, .product__media-item',\n    );\n    return Array.from(nodes).map((slide, fallbackIdx) => {\n      const img = slide.querySelector('img');\n      const rawIdx = slide.getAttribute('data-media-index');\n      const index =\n        rawIdx != null && rawIdx !== '' ? parseInt(rawIdx, 10) : fallbackIdx;\n      return {\n        index,\n        slide,\n        img,\n        url: img ? this._normalizeImageUrl(img.currentSrc || img.src) : '',\n        mediaId: slide.getAttribute('data-media-id'),\n      };\n    });\n  }\n\n  _resolveMediaIndexForUrl(imageUrl, notFound = 0) {\n    if (!imageUrl) return notFound;\n    const target = this._normalizeImageUrl(imageUrl);\n    const targetKey = this._filenameKey(imageUrl);\n    const slides = this._collectGallerySlides();\n    for (const s of slides) {\n      if (!s.url) continue;\n      if (s.url === target) return s.index;\n      if (targetKey && s.url.includes(targetKey)) return s.index;\n    }\n    return notFound;\n  }\n\n  /** Which gallery slide a zone (or canvas default) is authored for. */\n  /** Shopify renames re-uploaded files `name_<uuid>.jpg`; the gallery may hold either form. */\n  _stripDuplicateUploadSuffix(url) {\n    const out = String(url || '').replace(/_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?=\\.[a-z0-9]+(\\?|$))/i, '');\n    return out !== url ? out : null;\n  }\n\n  /** Gallery index of the canvas base image (the image legacy zones were authored on). Never -1. */\n  _canvasBaseIndex() {\n    const baseUrl = this.canvasConfig && this.canvasConfig.base_image_url;\n    if (!baseUrl) return 0;\n    let idx = this._resolveMediaIndexForUrl(baseUrl, -1);\n    if (idx < 0) {\n      const stripped = this._stripDuplicateUploadSuffix(baseUrl);\n      if (stripped) idx = this._resolveMediaIndexForUrl(stripped, -1);\n    }\n    return idx >= 0 ? idx : 0;\n  }\n\n  /**\n   * Gallery index a zone belongs to. Order: its own image URL, the URL without Shopify's\n   * duplicate-upload suffix, its saved index, then the canvas base image \u2014 most saved zones carry\n   * no image info and belong to the base image. Non-recursive by design.\n   */\n  _zoneImageIndex(zone) {\n    if (!zone) return this._canvasBaseIndex();\n    if (zone.image_url) {\n      let idx = this._resolveMediaIndexForUrl(zone.image_url, -1);\n      if (idx >= 0) return idx;\n      const stripped = this._stripDuplicateUploadSuffix(zone.image_url);\n      if (stripped) {\n        idx = this._resolveMediaIndexForUrl(stripped, -1);\n        if (idx >= 0) return idx;\n      }\n    }\n    if (typeof zone.media_index === 'number' && !Number.isNaN(zone.media_index) && zone.media_index >= 0) {\n      return zone.media_index;\n    }\n    return this._canvasBaseIndex();\n  }\n\n  /** Which gallery slide a zone (or, with no zone, the customization as a whole) is shown on. */\n  _getPreviewMediaIndex(zone) {\n    if (typeof zone === 'number' && !Number.isNaN(zone)) return zone;\n    if (zone) return this._zoneImageIndex(zone);\n    // No zone given: the base image if something is authored on it, else the first image that is.\n    const zs = ((this.canvasConfig && this.canvasConfig.zones) || []).filter((z) => z && !z.is_form_only);\n    const base = this._canvasBaseIndex();\n    if (!zs.length || zs.some((z) => this._zoneImageIndex(z) === base)) return base;\n    return this._zoneImageIndex(zs[0]);\n  }\n\n  _getActiveMediaIndex() {\n    const active =\n      document.querySelector('.pdp-main-viewer .pdp-media-slide.active') ||\n      document.querySelector('.pdp-main-viewer .pdp-media-slide.is-active') ||\n      document.querySelector('.product__media-item.active') ||\n      document.querySelector('.product__media-item.is-active');\n    if (!active) return 0;\n    const raw = active.getAttribute('data-media-index');\n    return raw != null && raw !== '' ? parseInt(raw, 10) : 0;\n  }\n\n  navigateGalleryToIndex(index) {\n    if (index == null || Number.isNaN(index)) return false;\n    const sectionId = this.config?.section_id;\n    const api =\n      sectionId && window.__blingPdpGallery && window.__blingPdpGallery[sectionId];\n    if (api && typeof api.goTo === 'function') {\n      api.goTo(index);\n      return true;\n    }\n    const thumb = document.querySelector(`.pdp-thumb[data-media-index=\"${index}\"]`);\n    if (thumb) {\n      thumb.click();\n      return true;\n    }\n    return false;\n  }\n\n  _zoneForField(field) {\n    if (!field || !this.canvasConfig?.zones) return null;\n    const id = String(field.id);\n    return (\n      this.canvasConfig.zones.find(\n        (z) =>\n          z &&\n          (String(z.id) === id ||\n            String(z.field || '') === id ||\n            String(z.template_field_id || '') === id),\n      ) || null\n    );\n  }\n\n  switchToPreviewForField(field) {\n    const zone = this._zoneForField(field);\n    this.switchToPreviewImage(zone || undefined);\n  }\n\n  /** Reposition overlay on the configured preview slide; navigate gallery when needed. */\n  switchToPreviewImage(zoneOrIndex) {\n    if (this._shouldSwitchToMainOnInput) {\n      this._shouldSwitchToMainOnInput = false;\n    }\n    if (this._zoneCanvas) {\n      this._zoneCanvas.style.display = 'block';\n    }\n    let targetIndex =\n      typeof zoneOrIndex === 'number'\n        ? zoneOrIndex\n        : this._getPreviewMediaIndex(zoneOrIndex);\n    this._activePreviewIndex = targetIndex;\n\n    const activeIndex = this._getActiveMediaIndex();\n    if (activeIndex !== targetIndex) {\n      this.navigateGalleryToIndex(targetIndex);\n    }\n\n    const apply = () => {\n      const img = this.findMainGalleryImg();\n      if (!img) return;\n      if (img !== this._heroImg) {\n        if (this._zoneRO && img) {\n          try {\n            this._zoneRO.disconnect();\n          } catch (_) {}\n          this._zoneRO.observe(img);\n          const host = this.getOverlayHost(img);\n          if (host) this._zoneRO.observe(host);\n        }\n        this._heroImg = img;\n      }\n      this.positionZoneOverlay();\n    };\n\n    setTimeout(apply, activeIndex !== targetIndex ? 90 : 0);\n  }\n\n  setupZoneOverlay() {\n    if (!this.hasLiveCanvasPreview()) return;\n    const img = this.findMainGalleryImg();\n    if (!img) {\n      if ((this._zoneRetries = (this._zoneRetries || 0) + 1) <= 20) {\n        setTimeout(() => this.setupZoneOverlay(), 250);\n      }\n      return;\n    }\n    this._heroImg = img;\n\n    const host = this.getOverlayHost(img);\n    let canvas = document.getElementById('bling-zone-canvas');\n    if (!canvas) {\n      canvas = document.createElement('canvas');\n      canvas.id = 'bling-zone-canvas';\n      canvas.setAttribute('aria-hidden', 'true');\n    }\n    if (host && canvas.parentElement !== host) {\n      host.appendChild(canvas);\n    } else if (!host && canvas.parentElement !== document.body) {\n      document.body.appendChild(canvas);\n    }\n    this._zoneCanvas = canvas;\n    Object.assign(canvas.style, {\n      position: 'absolute',\n      left: '0',\n      top: '0',\n      right: '0',\n      bottom: '0',\n      width: '100%',\n      height: '100%',\n      maxWidth: '100%',\n      maxHeight: '100%',\n      pointerEvents: 'none',\n      zIndex: '3',\n      display: this.livePreviewOn ? 'block' : 'none',\n      background: 'transparent',\n    });\n    if (host) {\n      const cs = getComputedStyle(host);\n      if (cs.position === 'static') host.style.position = 'relative';\n    }\n\n    if (!this._zoneInit) {\n      this._zoneInit = true;\n      this._reposition = () => {\n        if (this._repositionRaf) return;\n        this._repositionRaf = requestAnimationFrame(() => {\n          this._repositionRaf = 0;\n          this.positionZoneOverlay();\n        });\n      };\n      window.addEventListener('resize', this._reposition);\n      if (window.ResizeObserver) {\n        this._zoneRO = new ResizeObserver(() => this._reposition());\n        this._zoneRO.observe(img);\n        if (host) this._zoneRO.observe(host);\n      }\n\n      document.querySelectorAll('.pdp-thumb').forEach((thumb) => {\n        thumb.addEventListener('click', () => {\n          setTimeout(() => this.positionZoneOverlay(), 50);\n        });\n      });\n\n      if (window.MutationObserver) {\n        const viewer =\n          document.getElementById(`PdpViewer-${this.config.section_id || ''}`) ||\n          document.querySelector('.pdp-main-viewer');\n        if (viewer) {\n          this._galleryObserver = new MutationObserver(() => {\n            this.positionZoneOverlay();\n          });\n          this._galleryObserver.observe(viewer, {\n            attributes: true,\n            subtree: true,\n            attributeFilter: ['class'],\n          });\n        }\n      }\n    } else if (this._zoneRO) {\n      try {\n        this._zoneRO.disconnect();\n      } catch (_) {}\n      this._zoneRO.observe(img);\n      if (host) this._zoneRO.observe(host);\n    }\n    if (document.fonts && document.fonts.ready) {\n      document.fonts.ready.then(() => this.positionZoneOverlay()).catch(() => {});\n    }\n    if (!img.complete || !img.naturalWidth) {\n      img.addEventListener('load', () => this.positionZoneOverlay(), { once: true });\n    }\n    [0, 200, 600, 1200].forEach((t) =>\n      setTimeout(() => {\n        this.positionZoneOverlay();\n        this.setupThumbOverlays();\n      }, t),\n    );\n  }\n\n  /** Use the currently active media slide as containing block for the overlay canvas. */\n  getOverlayHost(img) {\n    if (!img) return null;\n    const hoverWrap =\n      img.closest('.product-media-container, .product-media, .media, .pcard-img') ||\n      img.parentElement;\n    // Use the closest active slide first (follows the variant's image, not just slide 0)\n    return (\n      hoverWrap ||\n      img.closest('.pdp-media-slide.active') ||\n      img.closest('.pdp-media-slide.is-active') ||\n      img.closest('.product__media-item.is-active') ||\n      img.closest('.product__media-item.active') ||\n      img.closest('.pdp-media-slide') ||\n      img.closest('.product__media-item') ||\n      img.parentElement\n    );\n  }\n\n  isMainFeaturedImageVisible() {\n    const previewIndex = this._getPreviewMediaIndex();\n    return this._getActiveMediaIndex() === previewIndex;\n  }\n\n  /** Gallery index of a thumbnail button. */\n  _thumbMediaIndex(thumb) {\n    const idx = thumb && thumb.getAttribute('data-media-index');\n    if (idx != null && idx !== '') return parseInt(idx, 10);\n    const all = Array.from(document.querySelectorAll('.pdp-thumb'));\n    return Math.max(0, all.indexOf(thumb));\n  }\n\n  /** True when at least one zone is authored on this thumbnail's image. */\n  isThumbFeaturedImage(thumb) {\n    if (!thumb || !this.canvasConfig || !Array.isArray(this.canvasConfig.zones)) return false;\n    const idx = this._thumbMediaIndex(thumb);\n    return this.canvasConfig.zones.some((z) => z && !z.is_form_only && this._getPreviewMediaIndex(z) === idx);\n  }\n\n  /** Mini overlay only on the first gallery thumbnail (matches image #1). */\n  setupThumbOverlays() {\n    if (!this.canvasConfig || !this.livePreviewOn) {\n      document.querySelectorAll('.bling-thumb-zone-canvas').forEach((c) => {\n        c.style.display = 'none';\n      });\n      return;\n    }\n    let st = document.getElementById('bling-thumb-overlay-styles');\n    if (!st) {\n      st = document.createElement('style');\n      st.id = 'bling-thumb-overlay-styles';\n      document.head.appendChild(st);\n    }\n    st.textContent = `\n      .pdp-thumb{\n        position:relative!important;\n        overflow:hidden!important;\n        isolation:isolate;\n      }\n      .bling-thumb-zone-canvas{\n        position:absolute!important;\n        left:0!important;\n        top:0!important;\n        right:auto!important;\n        bottom:auto!important;\n        inset:auto!important;\n        width:100%!important;\n        height:100%!important;\n        max-width:100%!important;\n        max-height:100%!important;\n        pointer-events:none!important;\n        z-index:2!important;\n        border-radius:inherit;\n        display:block!important;\n        background:transparent!important;\n      }\n    `;\n\n    // Keep overlays only on the variant's featured thumbnail\n    document.querySelectorAll('.pdp-thumb').forEach((thumb) => {\n      const isFeatured = this.isThumbFeaturedImage(thumb);\n      let c = thumb.querySelector(':scope > .bling-thumb-zone-canvas');\n      if (!isFeatured) {\n        if (c) c.remove();\n        return;\n      }\n      if (!c) {\n        c = document.createElement('canvas');\n        c.className = 'bling-thumb-zone-canvas';\n        c.setAttribute('aria-hidden', 'true');\n        thumb.appendChild(c);\n      }\n      thumb.style.position = 'relative';\n      thumb.style.overflow = 'hidden';\n      c.style.position = 'absolute';\n      c.style.left = '0';\n      c.style.top = '0';\n      c.style.right = 'auto';\n      c.style.bottom = 'auto';\n      c.style.width = '100%';\n      c.style.height = '100%';\n      c.style.maxWidth = '100%';\n      c.style.maxHeight = '100%';\n      c.style.pointerEvents = 'none';\n      c.style.zIndex = '2';\n      c.style.background = 'transparent';\n      c.style.display = '';\n    });\n    document.querySelectorAll('.bling-thumb-zone-canvas').forEach((c) => {\n      if (!c.closest('.pdp-thumb')) c.remove();\n    });\n    this.redrawThumbOverlays();\n  }\n\n  redrawThumbOverlays() {\n    if (!this.canvasConfig) return;\n    document.querySelectorAll('.pdp-thumb > .bling-thumb-zone-canvas').forEach((canvas) => {\n      const thumb = canvas.parentElement;\n      const isFeatured = this.isThumbFeaturedImage(thumb);\n      if (!this.livePreviewOn || !isFeatured) {\n        canvas.style.display = 'none';\n        return;\n      }\n      canvas.style.display = 'block';\n      if (!thumb) return;\n      const w = Math.max(1, thumb.clientWidth || 0);\n      const h = Math.max(1, thumb.clientHeight || 0);\n      if (w < 2 || h < 2) return;\n      const drawW = Math.min(w, 120);\n      const drawH = Math.min(h, 120);\n      const dpr = Math.min(window.devicePixelRatio || 1, 2);\n      canvas.width = Math.round(drawW * dpr);\n      canvas.height = Math.round(drawH * dpr);\n      canvas.style.width = '100%';\n      canvas.style.height = '100%';\n      const ctx = canvas.getContext('2d');\n      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n      ctx.clearRect(0, 0, drawW, drawH);\n      this.paintZones(ctx, drawW, drawH, {\n        mediaIndex: this._thumbMediaIndex(thumb),\n        img: thumb.querySelector('img'),\n      });\n    });\n  }\n\n  positionZoneOverlay() {\n    const img = this.findMainGalleryImg() || this._heroImg;\n    const canvas = this._zoneCanvas;\n    if (!img || !canvas) return;\n    this._heroImg = img;\n\n    const host = this.getOverlayHost(img);\n    if (host && canvas.parentElement !== host) {\n      host.appendChild(canvas);\n      const cs = getComputedStyle(host);\n      if (cs.position === 'static') host.style.position = 'relative';\n    }\n\n    if (!this.livePreviewOn || !this.isMainFeaturedImageVisible()) {\n      canvas.style.display = 'none';\n      this.redrawThumbOverlays();\n      return;\n    }\n\n    const w = Math.max(1, host ? host.clientWidth : img.clientWidth || 0);\n    const h = Math.max(1, host ? host.clientHeight : img.clientHeight || 0);\n    if (w < 2 || h < 2) {\n      canvas.style.display = 'none';\n      return;\n    }\n\n    canvas.style.display = 'block';\n    canvas.style.position = 'absolute';\n    canvas.style.left = '0';\n    canvas.style.top = '0';\n    canvas.style.width = '100%';\n    canvas.style.height = '100%';\n    this._cssW = w;\n    this._cssH = h;\n    const dpr = Math.min(window.devicePixelRatio || 1, 2);\n    this._dpr = dpr;\n    const nextW = Math.round(w * dpr);\n    const nextH = Math.round(h * dpr);\n    // Avoid wiping the bitmap every scroll/resize tick when size is unchanged\n    if (canvas.width !== nextW || canvas.height !== nextH) {\n      canvas.width = nextW;\n      canvas.height = nextH;\n    }\n    const ctx = canvas.getContext('2d');\n    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n    this.drawZones();\n    this.redrawThumbOverlays();\n  }\n\n  drawZones() {\n    const canvas = this._zoneCanvas;\n    if (!canvas || !this.canvasConfig) return;\n    const dpr = this._dpr || Math.min(window.devicePixelRatio || 1, 2);\n    const W = this._cssW || canvas.width / dpr;\n    const H = this._cssH || canvas.height / dpr;\n    const ctx = canvas.getContext('2d');\n    ctx.clearRect(0, 0, W, H);\n    if (!this.livePreviewOn) return;\n    this.paintZones(ctx, W, H);\n  }\n\n  /** object-fit: cover \u2014 map admin coords to visible image rect inside W\u00D7H box. */\n  getCoverMappedRect(W, H, img) {\n    const nw = img?.naturalWidth > 0 ? img.naturalWidth : W;\n    const nh = img?.naturalHeight > 0 ? img.naturalHeight : H;\n    const imgRatio = nw / nh;\n    const boxRatio = W / H;\n    let rw = W;\n    let rh = H;\n    let ox = 0;\n    let oy = 0;\n    if (imgRatio > boxRatio) {\n      rw = H * imgRatio;\n      ox = (W - rw) / 2;\n    } else if (imgRatio < boxRatio) {\n      rh = W / imgRatio;\n      oy = (H - rh) / 2;\n    }\n    return { rw, rh, ox, oy };\n  }\n\n  _getActiveVariantId() {\n    // First priority: section-specific PDP variant input\n    if (this.config && this.config.section_id) {\n      const pdpInput = document.getElementById('PdpVariantId-' + this.config.section_id);\n      if (pdpInput && pdpInput.value) return String(pdpInput.value);\n    }\n    // Second priority: form input\n    const forms = document.querySelectorAll('form[action^=\"/cart/add\"]');\n    for (const form of forms) {\n      const input = form.querySelector('[name=\"id\"]');\n      if (input && input.value) return String(input.value);\n    }\n    // Fallback: URL param\n    const urlParams = new URLSearchParams(window.location.search);\n    if (urlParams.has('variant')) return urlParams.get('variant');\n    return null;\n  }\n\n  _observeVariantChanges() {\n    // PRIMARY: listen for the custom event dispatched by the liquid variant picker.\n    // This is the only 100% reliable signal \u2014 replaceState doesn't fire popstate,\n    // and .value property writes don't trigger MutationObserver attribute watchers.\n    this._blingVariantHandler = (e) => {\n      const variantId = e.detail && e.detail.variantId ? String(e.detail.variantId) : null;\n      if (variantId) {\n        console.log('[Bling] Variant changed via event:', variantId);\n        this.reloadConfigForVariant(variantId);\n      }\n    };\n    document.addEventListener('bling:variant-changed', this._blingVariantHandler);\n\n    // SECONDARY: polling fallback for any other theme or non-standard integrations\n    let lastVariant = this._getActiveVariantId();\n    this._variantInterval = setInterval(() => {\n      const currentVariant = this._getActiveVariantId();\n      if (currentVariant && currentVariant !== lastVariant) {\n        lastVariant = currentVariant;\n        console.log('[Bling] Variant changed via poll:', currentVariant);\n        this.reloadConfigForVariant(currentVariant);\n      }\n    }, 500);\n  }\n\n  _observeLiveConfigChanges() {\n    this._visibilityChangeHandler = () => {\n      if (document.visibilityState === 'visible') {\n        this.checkForLiveConfigUpdates();\n      }\n    };\n    document.addEventListener('visibilitychange', this._visibilityChangeHandler);\n\n    this._windowFocusHandler = () => {\n      this.checkForLiveConfigUpdates();\n    };\n    window.addEventListener('focus', this._windowFocusHandler);\n\n    this._tabId = this._tabId || 'tab_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8);\n\n    // W3C BroadcastChannel for 0ms inter-tab sync across same-origin tabs\n    if (typeof BroadcastChannel !== 'undefined') {\n      try {\n        this._broadcastChannel = new BroadcastChannel('bling_customization_sync');\n        this._broadcastChannel.onmessage = (event) => {\n          if (event.data?.senderId === this._tabId) return; // Ignore own echo\n          const pid = String(this.config?.product_id || '').replace(/\\D/g, '');\n          const eventPid = String(event.data?.productId || '').replace(/\\D/g, '');\n          if (!eventPid || eventPid === pid) {\n            console.log('[Bling BroadcastChannel] Instant inter-tab sync received for product:', eventPid);\n            this.checkForLiveConfigUpdates({ fromBroadcast: true });\n          }\n        };\n      } catch (err) {\n        console.warn('[Bling BroadcastChannel] Not supported:', err);\n      }\n    }\n\n    // Periodic heartbeat check every 15 seconds while active\n    this._liveSyncInterval = setInterval(() => {\n      if (document.visibilityState === 'visible') {\n        this.checkForLiveConfigUpdates();\n      }\n    }, 15000);\n  }\n\n  _canonicalFieldsDigest(fields) {\n    if (!Array.isArray(fields)) return '[]';\n    const clean = fields.map(f => ({\n      id: String(f?.id || ''),\n      label: String(f?.label || ''),\n      field_type: String(f?.field_type || ''),\n      field_order: Number.isFinite(Number(f?.field_order)) ? Number(f?.field_order) : 0,\n      is_required: Boolean(f?.is_required),\n      options: Array.isArray(f?.options) ? f.options.map(o => ({\n        label: String(o?.label || o?.name || ''),\n        value: String(o?.value || o?.id || '')\n      })) : null,\n      max_length: f?.max_length ? Number(f.max_length) : null,\n      charm_type: f?.charm_type || null,\n      placeholder: f?.placeholder || null,\n      default_value: f?.default_value || null,\n    })).sort((a, b) => a.field_order - b.field_order || a.id.localeCompare(b.id));\n    return JSON.stringify(clean);\n  }\n\n  _canonicalZonesDigest(zones) {\n    if (!Array.isArray(zones)) return '[]';\n    const clean = zones.map(z => ({\n      id: String(z?.id || ''),\n      name: String(z?.name || ''),\n      x: Number(z?.x || 0),\n      y: Number(z?.y || 0),\n      width: Number(z?.width || 0),\n      height: Number(z?.height || 0),\n      field_id: String(z?.field_id || ''),\n      font_id: String(z?.font_id || ''),\n      color: String(z?.color || ''),\n    })).sort((a, b) => a.id.localeCompare(b.id));\n    return JSON.stringify(clean);\n  }\n\n  async checkForLiveConfigUpdates(options = {}) {\n    if (!this.config || !this.config.api_url) return;\n    if (this.isSubmitting) return;\n\n    const variantId = this._getActiveVariantId();\n    try {\n      const url = new URL(this.config.api_url);\n      if (variantId) url.searchParams.set('variant_id', variantId);\n      url.searchParams.set('_sync', String(Date.now()));\n\n      const res = await fetch(url.toString(), {\n        cache: 'no-store',\n        headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate' },\n      });\n      if (!res.ok) return;\n\n      const json = await res.json();\n      const nextData = json?.data;\n      if (!nextData) return;\n\n      const nextConfigId = nextData.config_id || null;\n      const nextTemplateId = nextData.template_id || null;\n      const nextIsEnabled = nextData.is_enabled !== false;\n      const rawNextFields = Array.isArray(nextData.fields) ? nextData.fields.map(f => this._normalizeField(f)) : [];\n      const nextFields = rawNextFields.slice().sort((a, b) => {\n        const oa = Number(a?.field_order);\n        const ob = Number(b?.field_order);\n        const na = Number.isFinite(oa) ? oa : 0;\n        const nb = Number.isFinite(ob) ? ob : 0;\n        if (na !== nb) return na - nb;\n        return String(a?.id || '').localeCompare(String(b?.id || ''));\n      });\n      const nextCanvas = nextData.canvas || null;\n\n      const curFieldsJson = this._canonicalFieldsDigest(this.fields || []);\n      const nextFieldsJson = this._canonicalFieldsDigest(nextFields);\n      const curZonesJson = this._canonicalZonesDigest(this.canvasConfig?.zones || []);\n      const nextZonesJson = this._canonicalZonesDigest(nextCanvas?.zones || []);\n\n      const hasChanged =\n        this.configId !== nextConfigId ||\n        this.templateId !== nextTemplateId ||\n        curFieldsJson !== nextFieldsJson ||\n        curZonesJson !== nextZonesJson ||\n        (this.fields.length > 0 && !nextIsEnabled);\n\n      if (!hasChanged) {\n        return; // In sync\n      }\n\n      console.log('[Bling Live-Sync] Remote customization update detected! Synchronizing storefront...');\n      this._writeCfgCache(variantId, nextData);\n\n      const snapshot = this._snapshotFieldValues();\n      this.configId = nextConfigId;\n      this.templateId = nextTemplateId;\n      this.canvasConfig = nextCanvas;\n\n      const hasFields = nextFields.length > 0 && nextIsEnabled && this.configId;\n      if (!hasFields) {\n        this.fields = [];\n        this._fieldsLoaded = false;\n        this.formVisible = false;\n        this.innerHTML = '';\n        this.style.display = 'none';\n        const parentBlock = this.closest('.bling-customization-block');\n        if (parentBlock) parentBlock.style.display = 'none';\n        this.cleanupFormInterceptors();\n        if (this._zoneCanvas) {\n          const ctx = this._zoneCanvas.getContext('2d');\n          if (ctx) ctx.clearRect(0, 0, this._zoneCanvas.width, this._zoneCanvas.height);\n          this._zoneCanvas.style.display = 'none';\n        }\n        return;\n      }\n\n      this.style.display = 'block';\n      const parentBlock = this.closest('.bling-customization-block');\n      if (parentBlock) parentBlock.style.display = '';\n\n      this.fields = nextFields;\n      this._fieldsLoaded = true;\n\n      if (!this.formVisible) {\n        this.interceptAddToCartButton();\n        this.showInlineForm();\n      } else {\n        this.render();\n      }\n\n      this._restoreFieldValues(snapshot);\n\n      if (!options.fromBroadcast && typeof BroadcastChannel !== 'undefined' && this._broadcastChannel) {\n        try {\n          this._broadcastChannel.postMessage({\n            type: 'CONFIG_HOT_SWAPPED',\n            senderId: this._tabId,\n            productId: String(this.config?.product_id || ''),\n            configId: nextConfigId,\n            timestamp: Date.now(),\n          });\n        } catch {}\n      }\n\n      if (this.canvasConfig && this.hasLiveCanvasPreview()) {\n        const isVariantOwnLayout = Boolean(this.canvasConfig && this.canvasConfig.is_variant_own_layout);\n        if (isVariantOwnLayout || !this._shouldSwitchToMainOnInput) {\n          this.switchToPreviewImage();\n          setTimeout(() => {\n            this.positionZoneOverlay();\n            this.setupThumbOverlays();\n            this.redrawLivePreview();\n          }, 80);\n        }\n      } else if (this._zoneCanvas) {\n        const ctx = this._zoneCanvas.getContext('2d');\n        if (ctx) ctx.clearRect(0, 0, this._zoneCanvas.width, this._zoneCanvas.height);\n        this._zoneCanvas.style.display = 'none';\n      }\n    } catch (err) {\n      console.warn('[Bling Live-Sync] Background check failed:', err);\n    }\n  }\n\n  _onCustomerCustomizationInteraction() {\n    if (this._shouldSwitchToMainOnInput) {\n      console.log('[Bling] Customer started customizing \u2014 transitioning gallery to main product image');\n      this._shouldSwitchToMainOnInput = false;\n      const mainIndex = typeof this._canvasBaseIndex === 'function' ? this._canvasBaseIndex() : 0;\n      this.navigateGalleryToIndex(mainIndex);\n      setTimeout(() => {\n        if (this._zoneCanvas) {\n          this._zoneCanvas.style.display = 'block';\n        }\n        this.positionZoneOverlay();\n        this.redrawLivePreview();\n      }, 100);\n    }\n  }\n\n  async reloadConfigForVariant(variantId) {\n    if (!this.config || !this.config.api_url) return;\n\n    // Race-condition guard: track the last requested variant. If a newer request\n    // comes in before this one finishes, discard the stale response.\n    this._pendingVariantId = variantId;\n    const snapshot = this._snapshotFieldValues();\n\n    try {\n      const url = new URL(this.config.api_url);\n      url.searchParams.set('variant_id', variantId);\n\n      const res = await fetch(url.toString());\n      if (!res.ok) return;\n\n      const json = await res.json();\n\n      // Discard if a newer variant was requested while we were awaiting\n      if (this._pendingVariantId !== variantId) {\n        console.log('[Bling] Discarding stale response for variant', variantId, '(now pending:', this._pendingVariantId, ')');\n        return;\n      }\n\n      // Use the COMPLETE canvas config returned for this exact variant \u2014\n      // no merging with general, no partial overlay, full replacement.\n      this.canvasConfig = json?.data?.canvas || null;\n      this.configId = json?.data?.config_id || null;\n      this.templateId = json?.data?.template_id || null;\n      console.log('[Bling] Canvas config updated for variant', variantId, '| has zones:', !!this.canvasConfig?.zones?.length);\n\n      const nextFields = Array.isArray(json?.data?.fields) ? json.data.fields.map(f => this._normalizeField(f)) : [];\n      const hasFields = nextFields.length > 0 && json?.data?.is_enabled !== false && this.configId;\n\n      if (!hasFields) {\n        this.fields = [];\n        this._fieldsLoaded = false;\n        this.formVisible = false;\n        this.innerHTML = '';\n        this.style.display = 'none';\n        const parentBlock = this.closest('.bling-customization-block');\n        if (parentBlock) parentBlock.style.display = 'none';\n        this.cleanupFormInterceptors();\n        if (this._zoneCanvas) {\n          const ctx = this._zoneCanvas.getContext('2d');\n          if (ctx) ctx.clearRect(0, 0, this._zoneCanvas.width, this._zoneCanvas.height);\n          this._zoneCanvas.style.display = 'none';\n        }\n        return;\n      }\n\n      this.style.display = 'block';\n      const parentBlock = this.closest('.bling-customization-block');\n      if (parentBlock) parentBlock.style.display = '';\n\n      const prevIds = (this.fields || []).map((f) => String(f.id)).join(',');\n      const nextIds = nextFields.map((f) => String(f.id)).join(',');\n      this.fields = nextFields;\n      this._fieldsLoaded = true;\n\n      if (!this.formVisible) {\n        this.interceptAddToCartButton();\n      } else if (prevIds !== nextIds) {\n        this.render();\n      }\n      this._restoreFieldValues(snapshot);\n\n      const isVariantOwnLayout = Boolean(this.canvasConfig && this.canvasConfig.is_variant_own_layout);\n\n      if (this.canvasConfig && isVariantOwnLayout) {\n        // Variant has its own layout enabled:\n        // Position overlay on this variant's image and live-render this variant's zones\n        this._shouldSwitchToMainOnInput = false;\n        if (this._zoneCanvas) {\n          this._zoneCanvas.style.display = 'block';\n        }\n        setTimeout(() => {\n          this.positionZoneOverlay();\n          this.setupThumbOverlays();\n          this.redrawLivePreview();\n        }, 80);\n      } else {\n        // Variant customization is OFF (Browse Mode):\n        // Keep the variant image clean with NO customization overlay!\n        // Do NOT yank or navigate the gallery back to main image.\n        this._shouldSwitchToMainOnInput = true;\n        if (this._zoneCanvas) {\n          const ctx = this._zoneCanvas.getContext('2d');\n          if (ctx) ctx.clearRect(0, 0, this._zoneCanvas.width, this._zoneCanvas.height);\n          this._zoneCanvas.style.display = 'none';\n        }\n      }\n    } catch (e) {\n      console.error('[Bling] Failed to reload config for variant', e);\n    }\n  }\n\n  _snapshotFieldValues() {\n    const snap = {};\n    for (const field of this.fields || []) {\n      const value = this.getFieldValue(field);\n      snap[String(field.id)] = value;\n      snap['label:' + String(field.label || '').toLowerCase()] = value;\n    }\n    return snap;\n  }\n\n  _restoreFieldValues(snap) {\n    if (!snap) return;\n    for (const field of this.fields || []) {\n      const value = snap[String(field.id)] ?? snap['label:' + String(field.label || '').toLowerCase()];\n      if (value == null || value === '') continue;\n      if (this.usesRadioInput(field)) {\n        const radio = this.querySelector(\n          `input[name=\"${CSS.escape(this.fieldRadioName(field.id))}\"][value=\"${CSS.escape(String(value))}\"]`,\n        );\n        if (radio) radio.checked = true;\n        continue;\n      }\n      if (field.field_type === 'checkbox' && Array.isArray(value)) {\n        this.querySelectorAll(`input[name=\"${CSS.escape(this.fieldCheckboxName(field.id))}\"]`).forEach((el) => {\n          el.checked = value.map(String).includes(el.value);\n        });\n        continue;\n      }\n      const input = this.getFieldInput(field);\n      if (input && field.field_type !== 'image' && field.field_type !== 'file') {\n        input.value = Array.isArray(value) ? value.join(', ') : String(value);\n        const trigger = this.querySelector(`.bling-imgselect[data-field-id=\"${field.id}\"] .bling-imgselect-current`);\n        if (trigger && !Array.isArray(value)) {\n          const opt = this.getOptions(field).find((o) => String(o.value) === String(value));\n          if (opt) trigger.textContent = opt.label || opt.value;\n        }\n      }\n    }\n    this.validateForm();\n  }\n\n  _propertyNameForField(field) {\n    const label = String(field.label || '').toLowerCase();\n    if (label.includes('font')) return 'Font';\n    if (label.includes('charm')) return 'Charm';\n    if (label.includes('logo')) return 'Logo';\n    if (['text', 'name', 'textarea'].includes(field.field_type)) {\n      const textFields = (this.fields || []).filter((f) =>\n        ['text', 'name', 'textarea'].includes(f.field_type),\n      );\n      return textFields.length <= 1 ? 'Personalized Text' : (field.label || 'Personalized Text');\n    }\n    return field.label || 'Customization';\n  }\n\n  _displayFieldValue(field) {\n    const raw = this.getFieldValue(field);\n    if (raw == null || raw === '') return '';\n    if (Array.isArray(raw)) {\n      return raw.map((v) => {\n        const opt = this.getOptions(field).find((o) => String(o.value) === String(v));\n        return (opt && (opt.label || opt.value)) || v;\n      }).join(', ');\n    }\n    const opt = this.getOptions(field).find((o) => String(o.value) === String(raw));\n    return (opt && (opt.label || opt.value)) || String(raw);\n  }\n\n  _upsertCartProperty(form, name, value) {\n    if (!form || value == null || value === '') return;\n    const attr = `properties[${name}]`;\n    let input = form.querySelector(`input[name=\"${attr}\"]`);\n    if (!input) {\n      input = document.createElement('input');\n      input.type = 'hidden';\n      input.name = attr;\n      form.appendChild(input);\n    }\n    input.value = String(value);\n  }\n\n  _applyCartProperties(form, submissionId) {\n    if (!form) return;\n    for (const field of this.fields || []) {\n      const raw = this.getFieldValue(field);\n      if (raw == null || raw === '' || (Array.isArray(raw) && !raw.length)) continue;\n      const display = this._displayFieldValue(field);\n      if (!display) continue;\n      this._upsertCartProperty(form, this._propertyNameForField(field), display);\n    }\n    this._upsertCartProperty(form, '_bling_session', this.sessionId);\n    if (submissionId) this._upsertCartProperty(form, '_bling_submission_id', submissionId);\n    const preview = this.generatedPreviews && this.generatedPreviews.length\n      ? this.generatedPreviews[this.generatedPreviews.length - 1]\n      : null;\n    const previewUrl = preview && (preview.preview_url || preview.url);\n    if (previewUrl) this._upsertCartProperty(form, '_bling_preview_url', previewUrl);\n  }\n\n  _collectFieldValues() {\n    return this.fields.map((field) => ({\n      field_id: field.id,\n      label: field.label,\n      value: this.getFieldValue(field),\n    }));\n  }\n\n\n  /** Draw all placement zones into any canvas context (main hero or thumbnail). */\n  paintZones(ctx, W, H, target) {\n    if (!this.canvasConfig || !Array.isArray(this.canvasConfig.zones)) return;\n    let textZoneIndex = 1;\n    const font = (this.getSelectedFont() || 'Georgia').replace(/['\\\\]/g, '');\n    // Leave padding inside the authored zone so text doesn't fill the plate edge-to-edge.\n    // Admin zones look smaller relative to the product; live was filling ~100% of zone height.\n    const PAD = 0.96;\n    const TEXT_FIT = 0.78;\n\n    // Thumbnails pass their own image index/element so they only show zones authored on THAT image.\n    const activeMediaIndex = target && typeof target.mediaIndex === 'number' ? target.mediaIndex : this._getActiveMediaIndex();\n    const { rw, rh, ox, oy } = this.getCoverMappedRect(W, H, (target && target.img) || this._heroImg);\n\n    for (const z of this.canvasConfig.zones) {\n      if (this._getPreviewMediaIndex(z) !== activeMediaIndex) continue;\n      const bx = ox + z.cx * rw;\n      const by = oy + z.cy * rh;\n      const maxW = z.w * rw * PAD;\n      const maxH = z.h * rh * PAD;\n\n      // Safe-zone border (set per zone in the Bling canvas editor): the zone rectangle, same as admin.\n      if (z.show_border === true) {\n        ctx.save();\n        ctx.translate(bx, by);\n        ctx.rotate(((z.rot || 0) * Math.PI) / 180);\n        ctx.lineWidth = Number(z.border_width) || 1;\n        ctx.strokeStyle = z.border_color || '#2563eb';\n        ctx.strokeRect(-maxW / 2, -maxH / 2, maxW, maxH);\n        ctx.restore();\n      }\n\n      if (z.type === 'logo') {\n        const field = this.resolveFieldForZone(z);\n        const selected = this.zoneLogo(z);\n        const isCharm = field && this.isCharmField(field);\n        const noneSelected = isCharm && this.isCharmNoneSelection(field);\n        // Charm fields: never show demo/default charm \u2014 only an explicitly chosen image charm.\n        const placeholder = (!selected && !noneSelected && !isCharm)\n          ? this.zonePlaceholderLogo(z)\n          : null;\n        const logo = selected || placeholder;\n        if (isCharm && (noneSelected || !selected)) {\n          this.coverBakedCharmWithLeather(ctx, z, W, H, bx, by, maxW, maxH);\n          continue;\n        }\n        if (!logo) continue;\n        ctx.save();\n        ctx.translate(bx, by);\n        ctx.rotate(((z.rot || 0) * Math.PI) / 180);\n        const scale = Math.min(maxW / (logo.width || 1), maxH / (logo.height || 1));\n        const dw = (logo.width || 1) * scale;\n        const dh = (logo.height || 1) * scale;\n        ctx.drawImage(logo, -dw / 2, -dh / 2, dw, dh);\n        ctx.restore();\n      } else {\n        const fallbackDemo =\n          (window.BlingZoneRender && window.BlingZoneRender.demoTextForZone\n            ? window.BlingZoneRender.demoTextForZone(z)\n            : '') || '';\n        textZoneIndex++;\n        const t = this.zoneText(z) || fallbackDemo || '';\n        if (!t) continue;\n        ctx.save();\n        ctx.translate(bx, by);\n        ctx.rotate(((z.rot || 0) * Math.PI) / 180);\n        this.drawZoneText(ctx, t, font, maxW * TEXT_FIT, maxH * TEXT_FIT, z.color || '#3a2a1a', false);\n        ctx.restore();\n      }\n    }\n  }\n\n  /** Match a canvas zone to its customization field (id / field / template_field_id). */\n  resolveFieldForZone(zone) {\n    if (!zone || !Array.isArray(this.fields)) return null;\n    \n    // Check exact ID matches first (this handles mapped fields flawlessly)\n    const exactKeys = [zone.id, zone.field, zone.template_field_id].filter(Boolean).map(String);\n    for (const f of this.fields) {\n      if (exactKeys.includes(String(f.id))) return f;\n    }\n    \n    // Fallback: nth logo/text zone \u2192 nth corresponding field\n    if (zone.type === 'logo') {\n      const logoZones = (this.canvasConfig?.zones || []).filter((z) => z && z.type === 'logo');\n      const imgFields = this.fields.filter((f) => this.isImageCapableField(f));\n      const zi = logoZones.indexOf(zone);\n      if (zi >= 0 && zi < imgFields.length) return imgFields[zi];\n    } else {\n      const textZones = (this.canvasConfig?.zones || []).filter((z) => z && z.type !== 'logo');\n      const textFields = this.fields.filter((f) => ['text', 'name', 'textarea'].includes(f.field_type));\n      const ti = textZones.indexOf(zone);\n      if (ti >= 0 && ti < textFields.length) return textFields[ti];\n    }\n\n    return null; // Don't loosely match on label anymore to prevent cross-contamination\n  }\n\n  isCharmField(field) {\n    if (!field) return false;\n    if (field.field_type === 'charm') return true;\n    const label = String(field.label || '').toLowerCase();\n    if (label.includes('charm') || label.includes('cham')) return true;\n    const t = field.field_type;\n    if (t !== 'radio' && t !== 'dropdown') return false;\n    return this.getOptions(field).some((o) => o && o.image);\n  }\n\n  /** True when shopper explicitly chose None / a no-image option (do not show demo charm). */\n  isCharmNoneSelection(field) {\n    if (!field || !this.isCharmField(field)) return false;\n    if (this.usesRadioInput(field)) {\n      const checked = this.querySelector(\n        `input[name=\"${CSS.escape(this.fieldRadioName(field.id))}\"]:checked`,\n      );\n      if (!checked) return false;\n    }\n    const val = this.getFieldValue(field);\n    const valNorm = String(val == null ? '' : val).trim().toLowerCase();\n    if (valNorm === 'none' || valNorm === 'no charm' || valNorm === 'no charms') return true;\n    const opts = this.getOptions(field);\n    const sel = opts.find((o) => o && String(o.value) === String(val));\n    if (!sel) {\n      // Checked/selected empty value with no matching option still means clear.\n      return val === '' || val == null;\n    }\n    const label = String(sel.label || '').trim().toLowerCase();\n    if (label === 'none' || label === 'no charm' || label === 'no charms') return true;\n    if (!sel.image) return true;\n    return false;\n  }\n\n  /**\n   * Hide baked-in charms on the first product photo.\n   * Samples leather from a ring around the zone using the same object-fit:cover\n   * crop as the visible gallery image, then fills the zone with that tone.\n   */\n  coverBakedCharmWithLeather(ctx, zone, W, H, bx, by, maxW, maxH) {\n    const img = this._heroImg || this.findMainGalleryImg?.();\n    if (!img || !img.naturalWidth) return;\n    const pad = 1.18;\n    const rw = Math.max(10, maxW * pad);\n    const rh = Math.max(10, maxH * pad);\n    try {\n      const sc = document.createElement('canvas');\n      sc.width = Math.max(1, Math.round(W));\n      sc.height = Math.max(1, Math.round(H));\n      const sctx = sc.getContext('2d', { willReadFrequently: true });\n      this.drawImageCover(sctx, img, sc.width, sc.height);\n\n      // Only cover if the zone center on the photo looks like a baked charm/foil.\n      if (!this.zoneLooksBakedCharm(sctx, sc.width, sc.height, bx, by, maxW, maxH)) return;\n\n      const rot = ((zone.rot || 0) * Math.PI) / 180;\n      const cos = Math.cos(rot);\n      const sin = Math.sin(rot);\n      let rSum = 0, gSum = 0, bSum = 0, n = 0;\n      for (let a = 0; a < 32; a++) {\n        const t = (a / 32) * Math.PI * 2;\n        for (const rad of [0.72, 0.88, 1.05]) {\n          const lx = Math.cos(t) * (rw * rad * 0.5);\n          const ly = Math.sin(t) * (rh * rad * 0.5);\n          const px = Math.round(bx + lx * cos - ly * sin);\n          const py = Math.round(by + lx * sin + ly * cos);\n          if (px < 1 || py < 1 || px >= sc.width - 1 || py >= sc.height - 1) continue;\n          const d = sctx.getImageData(px, py, 1, 1).data;\n          const r = d[0], g = d[1], b = d[2];\n          const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n          const sat = Math.max(r, g, b) - Math.min(r, g, b);\n          if (lum > 175 || (lum > 140 && sat > 35 && r > g && r > b)) continue;\n          rSum += r; gSum += g; bSum += b; n += 1;\n        }\n      }\n      if (n < 4) return;\n      const fill = `rgb(${Math.round(rSum / n)},${Math.round(gSum / n)},${Math.round(bSum / n)})`;\n\n      ctx.save();\n      ctx.translate(bx, by);\n      ctx.rotate(rot);\n      ctx.fillStyle = fill;\n      ctx.beginPath();\n      ctx.ellipse(0, 0, rw / 2, rh / 2, 0, 0, Math.PI * 2);\n      ctx.fill();\n      ctx.restore();\n    } catch (e) {\n      /* ignore */\n    }\n  }\n\n  /** True when the product photo itself has foil/charm ink in this zone. */\n  zoneLooksBakedCharm(sctx, W, H, bx, by, maxW, maxH) {\n    try {\n      const x0 = Math.max(0, Math.floor(bx - maxW * 0.35));\n      const y0 = Math.max(0, Math.floor(by - maxH * 0.35));\n      const ww = Math.max(1, Math.min(W - x0, Math.ceil(maxW * 0.7)));\n      const hh = Math.max(1, Math.min(H - y0, Math.ceil(maxH * 0.7)));\n      const data = sctx.getImageData(x0, y0, ww, hh).data;\n      let metal = 0;\n      let n = 0;\n      for (let i = 0; i < data.length; i += 4) {\n        const r = data[i], g = data[i + 1], b = data[i + 2];\n        const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n        const sat = Math.max(r, g, b) - Math.min(r, g, b);\n        n += 1;\n        // gold / brass / bright foil\n        if ((lum > 150 && sat > 25 && r >= g && g > b) || (lum > 185 && sat < 25)) metal += 1;\n      }\n      return n > 0 && metal / n > 0.04;\n    } catch (e) {\n      return true; // if we can't read, still try to cover\n    }\n  }\n\n  /** Draw img into dw\u00D7dh with object-fit: cover (matches storefront gallery framing). */\n  drawImageCover(ctx, img, dw, dh) {\n    const iw = img.naturalWidth || img.width;\n    const ih = img.naturalHeight || img.height;\n    if (!iw || !ih) return;\n    const ir = iw / ih;\n    const dr = dw / dh;\n    let sx = 0, sy = 0, sw = iw, sh = ih;\n    if (ir > dr) {\n      sh = ih;\n      sw = ih * dr;\n      sx = (iw - sw) / 2;\n      sy = 0;\n    } else {\n      sw = iw;\n      sh = iw / dr;\n      sx = 0;\n      sy = (ih - sh) / 2;\n    }\n    ctx.drawImage(img, sx, sy, sw, sh, 0, 0, dw, dh);\n  }\n\n  isLogoUploadField(field) {\n    if (!field) return false;\n    const label = String(field.label || '').toLowerCase();\n    if (label.includes('charm') || label.includes('cham') || field.field_type === 'charm') return false;\n    return field.field_type === 'image' || field.field_type === 'file' || field.field_type === 'audio';\n  }\n\n  isImageCapableField(field) {\n    return this.isCharmField(field) || this.isLogoUploadField(field);\n  }\n\n  /** Logo-upload demo badge only \u2014 charm fields never get a default/demo charm. */\n  zonePlaceholderLogo(zone) {\n    if (!this._placeholderByKey) this._placeholderByKey = new Map();\n    const field = this.resolveFieldForZone(zone);\n    if (field && this.isCharmField(field)) return null;\n    return this._placeholderByKey.get('logo') || null;\n  }\n\n  loadImage(url) {\n    return new Promise((resolve) => {\n      if (!url) return resolve(null);\n      const img = new Image();\n      img.crossOrigin = 'anonymous';\n      img.onload = () => resolve(img);\n      img.onerror = () => resolve(null);\n      img.src = url;\n    });\n  }\n\n  /** Preload LOGO badge only (charm fields never use a demo/default charm). */\n  async ensurePlaceholderImages() {\n    if (!this._placeholderByKey) this._placeholderByKey = new Map();\n    const jobs = [];\n\n    const logoUrl =\n      (this.config && this.config.logo_placeholder_url) ||\n      (window.BLING_LOGO_PLACEHOLDER_URL || '');\n    if (logoUrl && !this._placeholderByKey.has('logo')) {\n      jobs.push(\n        this.loadImage(logoUrl).then((img) => {\n          if (!img) return;\n          const processed = this.processLogoImage(img);\n          if (processed) this._placeholderByKey.set('logo', processed);\n        }),\n      );\n    }\n\n    await Promise.all(jobs);\n  }\n\n  // Logo canvas for a zone: keyed by customization field id (tpl_N).\n  zoneLogo(zone) {\n    if (!this._logosByField) this._logosByField = new Map();\n    const field = this.resolveFieldForZone(zone);\n    if (field) {\n      const byField = this._logosByField.get(String(field.id));\n      if (byField) return byField;\n    }\n    if (zone && zone.field) {\n      const byField = this._logosByField.get(String(zone.field));\n      if (byField) return byField;\n      for (const f of this.fields) {\n        if (String(f.id) === String(zone.field) || f.label === zone.field) {\n          const byId = this._logosByField.get(String(f.id));\n          if (byId) return byId;\n        }\n      }\n    }\n    if (zone && zone.id && this._logosByField.has(String(zone.id))) {\n      return this._logosByField.get(String(zone.id));\n    }\n    return null;\n  }\n\n  // Text that feeds a zone: a specific mapped field if set, else all text fields.\n  zoneText(zone) {\n    const f = this.resolveFieldForZone(zone);\n    if (f) {\n      const el = this.getFieldInput(f);\n      return el ? String(el.value || '').trim() : '';\n    }\n    return '';\n  }\n\n  // Draw text fitted to a zone using the true glyph ink box (handles cursive/italic\n  // fonts whose visible ink is wider/taller than the measured advance width).\n  drawZoneText(ctx, text, font, maxW, maxH, ink, outline = false, outlineColor = '', outlineWidth = 1) {\n    const setFont = (s) => { ctx.font = `${s}px '${font}', cursive, serif`; };\n    const metricsAt = (s) => {\n      setFont(s);\n      const m = ctx.measureText(text);\n      const left = m.actualBoundingBoxLeft != null ? m.actualBoundingBoxLeft : 0;\n      const right = m.actualBoundingBoxRight != null ? m.actualBoundingBoxRight : m.width;\n      const asc = m.actualBoundingBoxAscent != null ? m.actualBoundingBoxAscent : s * 0.72;\n      const desc = m.actualBoundingBoxDescent != null ? m.actualBoundingBoxDescent : s * 0.22;\n      return { left, right, asc, desc, w: left + right, h: asc + desc };\n    };\n\n    // Binary-search the largest size whose ink box fits both width and height.\n    // Cap near maxH (not 2.2\u00D7) so short words don't inflate to fill the plate.\n    let lo = 6;\n    let hi = Math.max(8, Math.round(maxH * 1.05));\n    let best = lo;\n    for (let i = 0; i < 22 && lo <= hi; i++) {\n      const mid = (lo + hi) >> 1;\n      const m = metricsAt(mid);\n      if (m.w <= maxW && m.h <= maxH) {\n        best = mid;\n        lo = mid + 1;\n      } else {\n        hi = mid - 1;\n      }\n    }\n\n    const m = metricsAt(best);\n    // Center the ink box at the zone origin (0,0).\n    const ox = (m.left - m.right) / 2;\n    const oy = (m.asc - m.desc) / 2;\n\n    ctx.save();\n    ctx.textAlign = 'left';\n    ctx.textBaseline = 'alphabetic';\n    setFont(best);\n    ctx.lineJoin = 'round';\n    ctx.miterLimit = 2;\n    const lightInk = this._isLightInk(ink);\n    // Border disabled => plain fill: no stroke, no shadow. Enabled => a single thin outline.\n    ctx.shadowColor = 'transparent';\n    ctx.shadowBlur = 0;\n    if (outline) {\n      ctx.lineWidth = Math.max(0.8, best * 0.04) * (Number(outlineWidth) || 1);\n      ctx.strokeStyle = outlineColor || (lightInk ? 'rgba(0,0,0,0.55)' : 'rgba(255,255,255,0.75)');\n      ctx.strokeText(text, ox, oy);\n    }\n    ctx.shadowColor = 'transparent';\n    ctx.shadowBlur = 0;\n    ctx.fillStyle = ink;\n    ctx.fillText(text, ox, oy);\n    ctx.restore();\n  }\n\n  _isLightInk(hex) {\n    const m = /^#?([0-9a-f]{6})$/i.exec(String(hex || ''));\n    if (!m) return false;\n    const n = parseInt(m[1], 16);\n    return 0.2126 * ((n >> 16) & 255) + 0.7152 * ((n >> 8) & 255) + 0.0722 * (n & 255) > 150;\n  }\n\n  // Build a background-removed, content-cropped logo canvas from the uploaded file.\n  // Done locally on a same-origin blob (no CORS taint) so it's free and instant.\n  async buildLogoCanvas(file, fieldId) {\n    if (!file || !/^image\\//.test(file.type)) {\n      if (fieldId && this._logosByField) this._logosByField.delete(String(fieldId));\n      return;\n    }\n    const url = URL.createObjectURL(file);\n    try {\n      const img = await new Promise((res, rej) => {\n        const i = new Image();\n        i.onload = () => res(i);\n        i.onerror = rej;\n        i.src = url;\n      });\n      const canvas = this.processLogoImage(img);\n      this.setFieldLogo(fieldId, canvas, url);\n    } catch (e) {\n      if (fieldId && this._logosByField) this._logosByField.delete(String(fieldId));\n    } finally {\n      URL.revokeObjectURL(url);\n    }\n  }\n\n  /** Load an option image (charm / logo choice) into a field's logo slot. */\n  async loadLogoFromUrl(fieldId, url) {\n    if (!fieldId || !url) return;\n    if (!this._logoUrlByField) this._logoUrlByField = new Map();\n    if (this._logoUrlByField.get(String(fieldId)) === url && this._logosByField?.has(String(fieldId))) {\n      return;\n    }\n    this._logoUrlByField.set(String(fieldId), url);\n    try {\n      const img = await new Promise((res, rej) => {\n        const i = new Image();\n        i.crossOrigin = 'anonymous';\n        i.onload = () => res(i);\n        i.onerror = rej;\n        i.src = url;\n      });\n      // Bail if a newer selection replaced this URL while loading.\n      if (this._logoUrlByField.get(String(fieldId)) !== url) return;\n      const canvas = this.processLogoImage(img);\n      this.setFieldLogo(fieldId, canvas, url);\n      this.redrawLivePreview();\n    } catch (e) {\n      if (this._logoUrlByField.get(String(fieldId)) === url) {\n        this._logoUrlByField.delete(String(fieldId));\n        if (this._logosByField) this._logosByField.delete(String(fieldId));\n      }\n    }\n  }\n\n  setFieldLogo(fieldId, canvas, url) {\n    if (!this._logosByField) this._logosByField = new Map();\n    if (!this._logoUrlByField) this._logoUrlByField = new Map();\n    if (fieldId) {\n      this._logosByField.set(String(fieldId), canvas);\n      if (url) this._logoUrlByField.set(String(fieldId), url);\n    }\n  }\n\n  /** Knock out near-white backgrounds and crop to ink bounds. */\n  processLogoImage(img) {\n    if (window.BlingZoneRender && typeof window.BlingZoneRender.processLogoImage === 'function') {\n      return window.BlingZoneRender.processLogoImage(img);\n    }\n    const max = 512;\n    const scale = Math.min(1, max / Math.max(img.width, img.height));\n    const cw = Math.max(1, Math.round(img.width * scale));\n    const ch = Math.max(1, Math.round(img.height * scale));\n    const c = document.createElement('canvas');\n    c.width = cw;\n    c.height = ch;\n    const cx = c.getContext('2d');\n    cx.drawImage(img, 0, 0, cw, ch);\n\n    let minX = cw, minY = ch, maxX = 0, maxY = 0, found = false;\n    try {\n      const id = cx.getImageData(0, 0, cw, ch);\n      const d = id.data;\n      for (let i = 0; i < d.length; i += 4) {\n        const r = d[i], g = d[i + 1], b = d[i + 2];\n        const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n        const sat = Math.max(r, g, b) - Math.min(r, g, b);\n        if (lum > 232 && sat < 22) {\n          d[i + 3] = 0;\n        } else {\n          const p = i / 4;\n          const x = p % cw;\n          const y = (p / cw) | 0;\n          if (x < minX) minX = x;\n          if (x > maxX) maxX = x;\n          if (y < minY) minY = y;\n          if (y > maxY) maxY = y;\n          found = true;\n        }\n      }\n      cx.putImageData(id, 0, 0);\n    } catch (e) {\n      return c;\n    }\n\n    if (found && maxX > minX && maxY > minY) {\n      const pad = 2;\n      const sx = Math.max(0, minX - pad);\n      const sy = Math.max(0, minY - pad);\n      const sw = Math.min(cw - sx, maxX - minX + pad * 2);\n      const sh = Math.min(ch - sy, maxY - minY + pad * 2);\n      const cropped = document.createElement('canvas');\n      cropped.width = sw;\n      cropped.height = sh;\n      cropped.getContext('2d').drawImage(c, sx, sy, sw, sh, 0, 0, sw, sh);\n      return cropped;\n    }\n    return c;\n  }\n\n  /** Map radio/dropdown image options (e.g. charms) onto logo zones by field id. */\n  syncImageOptionLogos() {\n    if (!this.fields || !this.fields.length) return;\n    if (!this._logosByField) this._logosByField = new Map();\n    if (!this._logoUrlByField) this._logoUrlByField = new Map();\n\n    for (const f of this.fields) {\n      const opts = this.getOptions(f);\n      if (!opts.some((o) => o && o.image)) continue;\n      const val = this.getFieldValue(f);\n      const sel = opts.find((o) => o && String(o.value) === String(val));\n      if (!sel || !sel.image || this.isCharmNoneSelection(f)) {\n        this._logosByField.delete(String(f.id));\n        this._logoUrlByField.delete(String(f.id));\n        continue;\n      }\n      this.loadLogoFromUrl(f.id, this.optionImageUrl(sel.image));\n    }\n  }\n\n  isLightColor(hex) {\n    const m = /^#?([0-9a-f]{6})$/i.exec(String(hex));\n    if (!m) return false;\n    const n = parseInt(m[1], 16);\n    const r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;\n    return 0.2126 * r + 0.7152 * g + 0.0722 * b > 150;\n  }\n\n  teardownZoneOverlay() {\n    if (this._repositionRaf) {\n      cancelAnimationFrame(this._repositionRaf);\n      this._repositionRaf = 0;\n    }\n    if (this._reposition) {\n      window.removeEventListener('resize', this._reposition);\n      this._reposition = null;\n    }\n    if (this._zoneRO) { this._zoneRO.disconnect(); this._zoneRO = null; }\n    if (this._galleryObserver) { this._galleryObserver.disconnect(); this._galleryObserver = null; }\n    if (this._zoneCanvas && this._zoneCanvas.parentNode) {\n      this._zoneCanvas.parentNode.removeChild(this._zoneCanvas);\n    }\n    this._zoneCanvas = null;\n    this._heroImg = null;\n  }\n\n  drawLivePreview() {\n    const canvas = this.querySelector('#bling-live-canvas');\n    if (!canvas || !this._previewImg) return;\n    const ctx = canvas.getContext('2d');\n    const W = canvas.width;\n    const H = canvas.height;\n\n    ctx.clearRect(0, 0, W, H);\n    ctx.drawImage(this._previewImg, 0, 0, W, H);\n\n    const text = this.gatherPreviewText();\n    const wrap = this.querySelector('#bling-live-preview');\n    if (wrap) wrap.classList.toggle('bling-has-text', !!text);\n    if (!text) return;\n\n    const font = (this.getSelectedFont() || 'Georgia').replace(/['\\\\]/g, '');\n    const cx = W * 0.5;\n    const cy = H * 0.6;\n    const maxTextW = W * 0.62;\n\n    let size = Math.round(H * 0.14);\n    const setFont = (s) => { ctx.font = `${s}px '${font}', cursive, serif`; };\n    setFont(size);\n    while (ctx.measureText(text).width > maxTextW && size > 10) {\n      size -= 1;\n      setFont(size);\n    }\n\n    // Auto-contrast: sample the product region behind the text to pick light/dark ink.\n    let light = false;\n    try {\n      const sx = Math.max(0, Math.round(cx - maxTextW / 2));\n      const sy = Math.max(0, Math.round(cy - size / 2));\n      const sw = Math.max(1, Math.min(W - sx, Math.round(maxTextW)));\n      const sh = Math.max(1, Math.min(H - sy, Math.round(size)));\n      const data = ctx.getImageData(sx, sy, sw, sh).data;\n      let lum = 0;\n      let n = 0;\n      for (let i = 0; i < data.length; i += 16) {\n        lum += 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];\n        n++;\n      }\n      lum = n ? lum / n : 200;\n      light = lum < 130;\n    } catch (e) {\n      light = false;\n    }\n\n    ctx.textAlign = 'center';\n    ctx.textBaseline = 'middle';\n    setFont(size);\n    ctx.fillStyle = light ? '#ffffff' : '#161616';\n    ctx.fillText(text, cx, cy);\n  }\n\n  injectImgSelectStyles() {\n    let st = document.getElementById('bling-imgselect-styles');\n    if (!st) {\n      st = document.createElement('style');\n      st.id = 'bling-imgselect-styles';\n      document.head.appendChild(st);\n    }\n    st.textContent = `\n      .pdp-media-slide:hover #bling-zone-canvas{\n        transform:inherit!important;\n        transition:inherit!important;\n        transform-origin:inherit!important;\n      }\n      .pcard-img, .card__media, .resource-card__media, .media--hover-effect{\n        overflow:hidden!important;\n      }\n      .pcard-img img, .card__media img, .media--hover-effect img,\n      .pcard:hover img, .card-wrapper:hover img{\n        transform:none!important;\n      }\n      .bling-card-zone-canvas{\n        transform:none!important;\n        transition:opacity .3s ease!important;\n      }\n      .bling-imgselect{position:relative}\n      bling-customization-form{display:block!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}\n      /* Restore normal flow \u2014 never cap/scroll .pdp-info (flex collapse overlaps ATC) */\n      .pdp-info{max-height:none!important;overflow:visible!important;height:auto!important}\n      .bling-customization-block{max-height:none!important;overflow:visible!important;height:auto!important;position:relative!important}\n      .bling-imgselect-trigger{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:10px 12px;border:1px solid rgba(0,0,0,.18);border-radius:var(--inputs-radius,0);background:#fff;cursor:pointer;font:inherit;line-height:1.2;text-align:left}\n      .bling-imgselect-current{display:flex;align-items:center;gap:8px;min-height:36px}\n      .bling-imgselect-menu{position:absolute;z-index:9999;left:0;right:0;margin-top:4px;max-height:300px;overflow:auto;background:#fff;border:1px solid rgba(0,0,0,.18);border-radius:var(--inputs-radius,0);box-shadow:0 10px 28px rgba(0,0,0,.14);list-style:none;padding:4px;display:none}\n      .bling-imgselect-menu.open{display:block}\n      .bling-imgselect-option{display:flex;align-items:center;gap:10px;padding:8px;border-radius:var(--inputs-radius,0);cursor:pointer}\n      .bling-imgselect-option:hover{background:rgba(0,0,0,.06)}\n      .bling-imgselect-thumb{width:64px;height:40px;object-fit:contain;border:1px solid rgba(0,0,0,.1);border-radius:var(--inputs-radius,0);background:#fff;flex-shrink:0}\n      .bling-radio-label.bling-has-image,.bling-checkbox-label.bling-has-image{display:inline-flex;flex-direction:column;align-items:center;gap:6px;border:1px solid rgba(0,0,0,.14);border-radius:var(--inputs-radius,0);padding:8px;margin:4px;cursor:pointer}\n      .bling-radio-label.bling-has-image:has(input:checked),.bling-checkbox-label.bling-has-image:has(input:checked){border-color:rgb(var(--color-foreground,18 18 18));box-shadow:0 0 0 1px rgb(var(--color-foreground,18 18 18))}\n      .bling-option-image{display:block;max-width:96px;max-height:60px;object-fit:contain}\n      /* Charm picker: pixel caps (theme rem can be huge) + min-height:0 so flex parents don't expand the page */\n      .bling-field-group:has(.bling-charm-grid){max-width:100%;overflow:hidden}\n      .bling-radio-group.bling-charm-grid,.bling-charm-grid{\n        display:grid!important;\n        grid-template-columns:repeat(5,minmax(0,1fr))!important;\n        gap:6px!important;\n        flex-direction:unset!important;\n        max-height:220px!important;\n        height:auto!important;\n        min-height:0!important;\n        overflow-x:hidden!important;\n        overflow-y:auto!important;\n        align-content:start!important;\n        padding:2px!important;\n        margin:0!important;\n      }\n      .bling-charm-grid .bling-radio-label,\n      .bling-charm-grid .bling-radio-label.bling-has-image{\n        display:flex!important;\n        flex-direction:column!important;\n        align-items:center!important;\n        justify-content:flex-start!important;\n        margin:0!important;\n        padding:4px!important;\n        gap:2px!important;\n        min-width:0!important;\n        min-height:0!important;\n        height:auto!important;\n        font-size:10px!important;\n        line-height:1.2!important;\n        box-sizing:border-box!important;\n      }\n      .bling-charm-grid .bling-option-image{\n        display:block!important;\n        width:100%!important;\n        max-width:100%!important;\n        height:36px!important;\n        max-height:36px!important;\n        object-fit:contain!important;\n      }\n      .bling-charm-grid .bling-radio-label input{position:absolute!important;opacity:0!important;pointer-events:none!important;width:0!important;height:0!important;margin:0!important}\n      .bling-charm-grid .bling-option-label{font-size:10px!important;line-height:1.2!important;text-align:center;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n      @media (max-width:640px){.bling-radio-group.bling-charm-grid,.bling-charm-grid{grid-template-columns:repeat(4,minmax(0,1fr))!important;max-height:200px!important}}\n      .bling-imgselect{position:relative;z-index:1}\n      .bling-imgselect.is-open,.bling-imgselect:has(.bling-imgselect-menu.open){z-index:50!important}\n      .bling-customization-block:has(.bling-imgselect-menu.open),\n      .bling-customization-block:has(.bling-imgselect.is-open){z-index:40!important}\n      .bling-imgselect-menu{\n        position:absolute;\n        z-index:60;\n        left:0;right:0;margin-top:4px;\n        max-height:min(300px,50vh);\n        overflow:auto;\n        background:#ffffff!important;\n        border:1px solid rgba(0,0,0,.18);\n        border-radius:var(--inputs-radius,0);\n        box-shadow:0 10px 28px rgba(0,0,0,.18);\n        list-style:none;padding:4px;display:none;\n        isolation:isolate;\n      }\n      .bling-imgselect-menu.open{display:block!important}\n      body > .bling-imgselect-menu.open{\n        position:fixed!important;\n        z-index:2147483000!important;\n        margin-top:0!important;\n        right:auto!important;\n        background:#ffffff!important;\n      }\n      .bling-imgselect-menu .bling-imgselect-option{background:#ffffff!important}\n      .bling-fontselect .bling-imgselect-option{padding:10px 12px}\n      .bling-font-preview{font-size:15px;line-height:1.3;white-space:nowrap}\n      .bling-field-invalid .bling-field-input,.bling-field-invalid .bling-imgselect-trigger{border-color:#c0392b!important;box-shadow:0 0 0 1px #c0392b}\n      /* \u2500\u2500 Customization card (single source of truth) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n         Corners: the card clips to its radius, and header/content ALSO carry the inner radius so\n         the rounded shape holds even if a theme rule forces overflow:visible on the wrapper. */\n      bling-customization-form .bling-collapsible-card{\n        --bl-radius:16px;--bl-line:#e4e7ec;--bl-line-strong:#cdd3dd;--bl-ink:#0f172a;--bl-muted:#667085;\n        --bl-field-h:42px;--bl-gap:12px;--bl-inner:calc(var(--bl-radius) - 1px);\n        margin:1.25rem 0 1.5rem!important;padding:0!important;\n        border:1px solid var(--bl-line)!important;border-radius:var(--bl-radius)!important;\n        background:#fff!important;\n        box-shadow:0 1px 2px rgba(16,24,40,.04),0 8px 20px -12px rgba(16,24,40,.12)!important;\n        overflow:hidden!important;font-family:var(--font-body-family,inherit);\n      }\n      bling-customization-form .bling-collapsible-card:hover{box-shadow:0 1px 2px rgba(16,24,40,.05),0 10px 24px -12px rgba(16,24,40,.16)!important}\n      bling-customization-form .bling-collapse-header{display:flex!important;align-items:center!important;justify-content:space-between!important;gap:12px;padding:14px 18px!important;background:#fafbfc!important;border-bottom:1px solid var(--bl-line)!important;border-radius:var(--bl-inner) var(--bl-inner) 0 0!important;cursor:pointer!important}\n      bling-customization-form .bling-collapse-header[aria-expanded=\"false\"]{border-bottom-color:transparent!important;border-radius:var(--bl-inner)!important}\n      bling-customization-form .bling-collapse-title{font-size:15px!important;line-height:1.2!important;letter-spacing:.01em!important}\n      bling-customization-form .bling-collapse-badge{font-size:10px!important;padding:2px 9px!important;letter-spacing:.06em!important}\n      bling-customization-form .bling-collapse-sparkle{font-size:15px!important}\n      bling-customization-form .bling-collapse-content{padding:16px 18px 18px!important;background:#fff!important;border-radius:0 0 var(--bl-inner) var(--bl-inner)!important}\n      bling-customization-form .bling-collapse-content.is-collapsed{display:none!important}\n      bling-customization-form .bling-live-preview{margin:0 0 14px!important;border:1px solid var(--bl-line)!important;border-radius:12px!important;overflow:hidden!important;background:#fff!important;box-shadow:none!important}\n      .bling-live-cap{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--bl-muted,#667085);padding:8px 12px;border-bottom:1px solid #eef0f4;background:#fafbfc;font-weight:600}\n      .bling-live-preview canvas{display:block;width:100%;height:auto;background:#fff}\n      /* PDP gallery frame while the live canvas is active: same quiet depth as the card */\n      .pdp-main-viewer:has(#bling-zone-canvas),.pdp-media-slide:has(#bling-zone-canvas),.product-media-container:has(#bling-zone-canvas),.product-media:has(#bling-zone-canvas){border-radius:16px!important;box-shadow:0 1px 2px rgba(16,24,40,.04),0 8px 20px -12px rgba(16,24,40,.12)!important;overflow:hidden!important;border:1px solid #e4e7ec!important;background:#ffffff!important}\n      .bling-charcount-badge{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:#f1f5f9;border:1px solid #e2e8f0;color:#64748b;font-size:11px;font-weight:600;padding:2px 6px;border-radius:5px;pointer-events:none;user-select:none;transition:all .15s ease;line-height:1.2}\n      .bling-charcount-badge.is-near-limit{background:#fef3c7;color:#b45309;border-color:#fde68a}\n      .bling-charcount-badge.is-at-limit{background:#fee2e2;color:#dc2626;border-color:#fecaca}\n      .bling-input-wrapper{position:relative;width:100%}\n      .bling-input-wrapper--textarea .bling-charcount-badge{top:12px;transform:none}\n      /* \u2500\u2500 Field grid: equal columns, equal-height rows, control pinned to the bottom of its cell \u2500\u2500 */\n      bling-customization-form .bling-fields-container{display:grid!important;grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:var(--bl-gap,12px)!important;align-items:stretch!important;margin:0 0 4px!important;grid-auto-flow:row}\n      bling-customization-form .bling-field-group{display:flex!important;flex-direction:column!important;gap:6px!important;min-width:0!important;margin:0!important;padding:12px 14px!important;box-sizing:border-box!important;background:#fff!important;border:1px solid var(--bl-line,#e4e7ec)!important;border-radius:12px!important;box-shadow:none!important;transition:border-color .15s ease,box-shadow .15s ease!important}\n      bling-customization-form .bling-field-group>:last-child{margin-top:auto!important}\n      bling-customization-form .bling-field-group:hover{border-color:var(--bl-line-strong,#cdd3dd)!important}\n      bling-customization-form .bling-field-group:focus-within{border-color:#0f172a!important;box-shadow:0 0 0 3px rgba(15,23,42,.07)!important}\n      .bling-field-label{display:block;font-size:13px;font-weight:600;color:#0f172a;margin:0;line-height:1.3}\n      .bling-field-help{margin:0;font-size:12px;color:#667085;line-height:1.35}\n      .bling-field-group--span-half{grid-column:span 1!important}\n      .bling-field-group--span-full,.bling-field-group--full,.bling-field-group--wide,.bling-live-toggle{grid-column:1 / -1!important}\n      .bling-field-group input[type=\"file\"].bling-field-input,\n      .bling-field-group .bling-file-input{width:100%!important;min-height:var(--bl-field-h,42px)!important;height:var(--bl-field-h,42px)!important;padding:8px 12px!important;font-size:13px!important;border-radius:10px!important;border:1px solid #d5dae3!important;background:#fff!important;box-sizing:border-box!important}\n      bling-customization-form .bling-field-input{width:100%!important;height:var(--bl-field-h,42px)!important;min-height:var(--bl-field-h,42px)!important;border-radius:10px!important;border:1px solid #d5dae3!important;background:#fff!important;padding:0 12px!important;font-size:13px!important;line-height:1.2!important;color:#0f172a!important;box-shadow:none!important;transition:border-color .15s ease,box-shadow .15s ease!important;box-sizing:border-box!important}\n      bling-customization-form .bling-input-wrapper:has(.bling-charcount-badge) .bling-field-input{padding-right:52px!important}\n      bling-customization-form textarea.bling-field-input{height:auto!important;min-height:88px!important;padding:10px 12px!important}\n      bling-customization-form .bling-field-input::placeholder{color:#98a2b3!important}\n      bling-customization-form .bling-field-input:focus{border-color:#0f172a!important;outline:none!important;box-shadow:0 0 0 3px rgba(15,23,42,.08)!important}\n      bling-customization-form .bling-imgselect-trigger{width:100%!important;border-radius:10px!important;min-height:var(--bl-field-h,42px)!important;height:var(--bl-field-h,42px)!important;padding:0 12px!important;border:1px solid #d5dae3!important;background:#fff!important;box-sizing:border-box!important;font-size:13px!important}\n      bling-customization-form .bling-imgselect-trigger:focus-visible,bling-customization-form .bling-imgselect.is-open .bling-imgselect-trigger{border-color:#0f172a!important;outline:none!important;box-shadow:0 0 0 3px rgba(15,23,42,.08)!important}\n      bling-customization-form .bling-imgselect-current{min-height:0!important}\n      \n      /* Clean modern pill radio buttons (non-charm) */\n      .bling-radio-group:not(.bling-charm-grid){display:flex!important;flex-wrap:wrap!important;gap:8px!important;width:100%!important;margin-top:2px!important}\n      .bling-radio-group:not(.bling-charm-grid) .bling-radio-label{display:inline-flex!important;align-items:center!important;gap:8px!important;padding:8px 14px!important;border:1.5px solid #e2e8f0!important;border-radius:8px!important;background:#fff!important;font-size:13px!important;font-weight:500!important;color:#334155!important;cursor:pointer!important;transition:all .15s ease!important;user-select:none!important;line-height:1.2!important;margin:0!important}\n      .bling-radio-group:not(.bling-charm-grid) .bling-radio-label:hover{border-color:#cbd5e1!important;background:#f8fafc!important}\n      .bling-radio-group:not(.bling-charm-grid) .bling-radio-label:has(input:checked){border-color:#0f172a!important;background:#f8fafc!important;color:#0f172a!important;font-weight:600!important;box-shadow:0 1px 3px rgba(15,23,42,.06)!important}\n      .bling-radio-group:not(.bling-charm-grid) .bling-radio-label input[type=\"radio\"]{width:16px!important;height:16px!important;margin:0!important;accent-color:#0f172a!important;cursor:pointer!important}\n      .bling-radio-group:not(.bling-charm-grid) .bling-option-label{font-size:13px!important;color:inherit!important;white-space:nowrap!important}\n\n      /* Clean modern checkbox group */\n      .bling-checkbox-group{display:flex!important;flex-direction:column!important;gap:8px!important;width:100%!important;margin-top:2px!important}\n      .bling-checkbox-label{display:flex!important;align-items:center!important;gap:10px!important;padding:9px 14px!important;border:1.5px solid #e2e8f0!important;border-radius:8px!important;background:#fff!important;font-size:13px!important;font-weight:500!important;color:#334155!important;cursor:pointer!important;transition:all .15s ease!important;user-select:none!important;line-height:1.3!important;margin:0!important}\n      .bling-checkbox-label:hover{border-color:#cbd5e1!important;background:#f8fafc!important}\n      .bling-checkbox-label:has(input:checked){border-color:#0f172a!important;background:#f8fafc!important;color:#0f172a!important;font-weight:600!important;box-shadow:0 1px 3px rgba(15,23,42,.06)!important}\n      .bling-checkbox-label input[type=\"checkbox\"]{width:18px!important;height:18px!important;margin:0!important;accent-color:#0f172a!important;cursor:pointer!important;flex-shrink:0!important}\n      .bling-checkbox-label span{font-size:13px!important;color:inherit!important}\n\n      @media (max-width:640px){\n        bling-customization-form .bling-collapsible-card{--bl-field-h:44px;--bl-radius:14px}\n        bling-customization-form .bling-collapse-header{padding:12px 14px!important}\n        bling-customization-form .bling-collapse-content{padding:14px!important}\n        bling-customization-form .bling-fields-container{grid-template-columns:minmax(0,1fr)!important}\n        bling-customization-form .bling-field-group,bling-customization-form .bling-field-group--span-half,.bling-live-toggle{grid-column:1 / -1!important}\n      }\n      }\n      .bling-live-toggle{display:flex;align-items:center;gap:8px;margin:2px 0 8px;font-size:13px;cursor:pointer;user-select:none}\n      .bling-live-toggle input{width:18px !important;height:18px !important;margin:0 !important;padding:0 !important;cursor:pointer;appearance:auto !important;-webkit-appearance:checkbox !important;border:1px solid rgba(0,0,0,0.5) !important;border-radius:3px !important;flex-shrink:0 !important;}\n      /* \u2500\u2500 Charm picker: quiet champagne accents, unmistakable selected state \u2500\u2500 */\n      bling-customization-form .bling-field-group--charm{background:linear-gradient(180deg,#fffdf8 0%,#fff 60%)!important;border-color:#efe6d2!important}\n      bling-customization-form .bling-charm-grid{grid-auto-rows:min-content!important;padding:6px!important;border:1px solid #f1e9d6!important;border-radius:10px!important;background:#fff!important}\n      bling-customization-form .bling-charm-grid .bling-radio-label{position:relative;border:1px solid #ece7dc!important;background:#fdfcf9!important;border-radius:10px!important;transition:border-color .15s ease,background-color .15s ease,box-shadow .15s ease!important}\n      bling-customization-form .bling-charm-grid .bling-radio-label:hover{border-color:#e2cfa0!important;background:#fffaf0!important}\n      bling-customization-form .bling-charm-grid .bling-radio-label:has(input:checked){border-color:#c9973f!important;background:#fff6e0!important;box-shadow:0 0 0 3px rgba(201,151,63,.18)!important}\n      bling-customization-form .bling-charm-grid .bling-radio-label:has(input:checked)::after{content:\"\u2713\";position:absolute;top:3px;right:3px;width:14px;height:14px;border-radius:50%;background:#c9973f;color:#fff;font-size:9px;line-height:14px;text-align:center;font-weight:700}\n      bling-customization-form .bling-charm-grid .bling-radio-label:has(input:checked) .bling-option-label{color:#7a5412!important;font-weight:600!important}\n      bling-customization-form .bling-charm-grid .bling-radio-label:focus-within{outline:2px solid rgba(201,151,63,.45);outline-offset:1px}\n      .bling-form-actions{display:none!important;margin:0!important;padding:0!important;height:0!important;overflow:hidden!important}\n    `;\n  }\n\n  positionImgSelectMenu(box, menu, trigger) {\n    const r = trigger.getBoundingClientRect();\n    const gap = 4;\n    const maxH = Math.min(300, Math.round(window.innerHeight * 0.5));\n    const spaceBelow = window.innerHeight - r.bottom - gap - 8;\n    const spaceAbove = r.top - gap - 8;\n    const openUp = spaceBelow < 160 && spaceAbove > spaceBelow;\n    const height = Math.max(120, Math.min(maxH, openUp ? spaceAbove : spaceBelow));\n    menu.style.position = 'fixed';\n    menu.style.left = `${Math.round(r.left)}px`;\n    menu.style.width = `${Math.round(r.width)}px`;\n    menu.style.right = 'auto';\n    menu.style.zIndex = '2147483000';\n    menu.style.maxHeight = `${height}px`;\n    menu.style.marginTop = '0';\n    if (openUp) {\n      menu.style.top = 'auto';\n      menu.style.bottom = `${Math.round(window.innerHeight - r.top + gap)}px`;\n    } else {\n      menu.style.bottom = 'auto';\n      menu.style.top = `${Math.round(r.bottom + gap)}px`;\n    }\n  }\n\n  releaseImgSelectMenu(menu, box) {\n    if (!menu) return;\n    menu.classList.remove('open');\n    menu.style.position = '';\n    menu.style.left = '';\n    menu.style.right = '';\n    menu.style.top = '';\n    menu.style.bottom = '';\n    menu.style.width = '';\n    menu.style.zIndex = '';\n    menu.style.maxHeight = '';\n    menu.style.marginTop = '';\n    if (box && menu.parentElement !== box) box.appendChild(menu);\n  }\n\n  attachCustomDropdowns() {\n    this.injectImgSelectStyles();\n    this.querySelectorAll('.bling-imgselect').forEach(box => {\n      const trigger = box.querySelector('.bling-imgselect-trigger');\n      const menu = box.querySelector('.bling-imgselect-menu');\n      const hidden = box.querySelector('input[type=\"hidden\"]');\n      const current = box.querySelector('.bling-imgselect-current');\n      if (!trigger || !menu || !hidden || !current) return;\n      box._blingMenu = menu;\n      if (box.dataset.fieldId) menu.dataset.owner = box.dataset.fieldId;\n\n      const openMenu = () => {\n        this.closeImgSelectMenus();\n        document.body.appendChild(menu);\n        menu.classList.add('open');\n        box.classList.add('is-open');\n        trigger.setAttribute('aria-expanded', 'true');\n        this.positionImgSelectMenu(box, menu, trigger);\n        const onScroll = () => {\n          if (!menu.classList.contains('open')) return;\n          this.positionImgSelectMenu(box, menu, trigger);\n        };\n        menu._blingReposition = onScroll;\n        window.addEventListener('scroll', onScroll, true);\n        window.addEventListener('resize', onScroll);\n      };\n\n      const closeMenu = () => {\n        if (menu._blingReposition) {\n          window.removeEventListener('scroll', menu._blingReposition, true);\n          window.removeEventListener('resize', menu._blingReposition);\n          menu._blingReposition = null;\n        }\n        this.releaseImgSelectMenu(menu, box);\n        box.classList.remove('is-open');\n        trigger.setAttribute('aria-expanded', 'false');\n      };\n\n      trigger.addEventListener('click', (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n        if (menu.classList.contains('open')) closeMenu();\n        else openMenu();\n      });\n\n      menu.querySelectorAll('.bling-imgselect-option').forEach(opt => {\n        opt.addEventListener('click', () => {\n          hidden.value = opt.dataset.value;\n          hidden.dispatchEvent(new Event('change', { bubbles: true }));\n          current.innerHTML = opt.innerHTML;\n          closeMenu();\n          this.validateForm();\n          const field = this.fields.find((f) => String(f.id) === String(box.dataset.fieldId));\n          if (field) this.switchToPreviewForField(field);\n          else this.switchToPreviewImage();\n          this.syncImageOptionLogos();\n          this.redrawLivePreview();\n        });\n      });\n\n      document.addEventListener('click', (e) => {\n        if (!menu.classList.contains('open')) return;\n        if (box.contains(e.target) || menu.contains(e.target)) return;\n        closeMenu();\n      });\n    });\n  }\n\n  closeImgSelectMenus() {\n    const menus = new Set([\n      ...this.querySelectorAll('.bling-imgselect-menu.open'),\n      ...document.body.querySelectorAll(':scope > .bling-imgselect-menu.open'),\n    ]);\n    menus.forEach((menu) => {\n      const box =\n        menu.closest('.bling-imgselect') ||\n        [...this.querySelectorAll('.bling-imgselect')].find((b) => b._blingMenu === menu) ||\n        (menu.dataset.owner\n          ? this.querySelector(`.bling-imgselect[data-field-id=\"${menu.dataset.owner}\"]`)\n          : null);\n      if (menu._blingReposition) {\n        window.removeEventListener('scroll', menu._blingReposition, true);\n        window.removeEventListener('resize', menu._blingReposition);\n        menu._blingReposition = null;\n      }\n      this.releaseImgSelectMenu(menu, box);\n      if (box) {\n        box.classList.remove('is-open');\n        const trigger = box.querySelector('.bling-imgselect-trigger');\n        if (trigger) trigger.setAttribute('aria-expanded', 'false');\n      }\n    });\n  }\n\n  attachEventListeners() {\n    this._touchedFields = this._touchedFields || new Set();\n    if (!this._touchListenerAttached) {\n      this._touchListenerAttached = true;\n      const markTouched = (e) => {\n        const id = e.target && e.target.getAttribute && e.target.getAttribute('data-field-id');\n        if (!id) return;\n        this._touchedFields.add(String(id));\n        this.validateForm();\n      };\n      this.addEventListener('focusout', markTouched);\n      this.addEventListener('change', markTouched);\n    }\n\n    if (!this._interactionListenerAttached) {\n      this._interactionListenerAttached = true;\n      const onUserAction = (e) => {\n        if (e.target && (e.target.closest('button#bling-submit-btn') || e.target.closest('.bling-accordion-header'))) {\n          return;\n        }\n        this._onCustomerCustomizationInteraction();\n      };\n      this.addEventListener('focusin', onUserAction);\n      this.addEventListener('input', onUserAction);\n      this.addEventListener('change', onUserAction);\n      this.addEventListener('click', (e) => {\n        if (e.target && (e.target.closest('.bling-radio-label') || e.target.closest('.bling-imgselect') || e.target.closest('.bling-charm-grid') || e.target.closest('.bling-field-input'))) {\n          onUserAction(e);\n        }\n      });\n    }\n\n    // Validation on input\n    // Validation on input \u2014 close font menus so they never leave a layout hole\n    const inputs = this.querySelectorAll('.bling-field-input, input[type=\"radio\"], input[type=\"checkbox\"]');\n    inputs.forEach(input => {\n      input.addEventListener('focus', () => {\n        this._onCustomerCustomizationInteraction();\n        const fieldId = input.id?.replace(/^bling-field-/, '') || input.name?.replace(/^bling-field-/, '');\n        const field = this.fields.find((f) => String(f.id) === String(fieldId));\n        if (field) this.switchToPreviewForField(field);\n      });\n      input.addEventListener('input', () => {\n        this._onCustomerCustomizationInteraction();\n        this.closeImgSelectMenus();\n        this.validateForm();\n        const fieldId = input.id?.replace(/^bling-field-/, '') || input.name?.replace(/^bling-field-/, '');\n        const field = this.fields.find((f) => String(f.id) === String(fieldId));\n        if (field) this.switchToPreviewForField(field);\n        else this.switchToPreviewImage();\n        this.syncImageOptionLogos();\n        this.redrawLivePreview();\n      });\n      input.addEventListener('change', () => {\n        this._onCustomerCustomizationInteraction();\n        this.closeImgSelectMenus();\n        this.validateForm();\n        const fieldId = input.id?.replace(/^bling-field-/, '') || input.name?.replace(/^bling-field-/, '');\n        const field = this.fields.find((f) => String(f.id) === String(fieldId));\n        if (field) this.switchToPreviewForField(field);\n        else this.switchToPreviewImage();\n        this.syncImageOptionLogos();\n        this.redrawLivePreview();\n      });\n    });\n\n    // Live character counters for length-limited fields\n    this.querySelectorAll('.bling-charcount-badge').forEach((counter) => {\n      const fieldId = counter.dataset.counterFor;\n      const max = parseInt(counter.dataset.max, 10);\n      const input = this.getFieldInput(fieldId);\n      if (!input) return;\n      const update = () => {\n        const len = input.value.length;\n        counter.textContent = `${len}/${max}`;\n        counter.classList.toggle('is-near-limit', max > 0 && len >= max * 0.8 && len < max);\n        counter.classList.toggle('is-at-limit', max > 0 && len >= max);\n      };\n      input.addEventListener('input', update);\n      update();\n    });\n\n    // Live-preview on/off toggle (multi-zone overlay)\n    const liveToggle = this.querySelector('#bling-live-toggle');\n    if (liveToggle) {\n      liveToggle.addEventListener('change', () => {\n        this.livePreviewOn = liveToggle.checked;\n        if (this._zoneCanvas) {\n          this._zoneCanvas.style.display = this.livePreviewOn ? '' : 'none';\n        }\n        if (this.livePreviewOn) {\n          this.switchToPreviewImage();\n        }\n        this.setupThumbOverlays();\n        this.redrawLivePreview();\n      });\n    }\n\n    // Wire up custom image dropdowns (font/preview images)\n    this.attachCustomDropdowns();\n    \n    // File uploads\n    const fileInputs = this.querySelectorAll('input[type=\"file\"]');\n    fileInputs.forEach(input => {\n      input.addEventListener('change', (e) => this.handleFileUpload(e));\n    });\n    \n    // Preview button\n    const previewBtn = this.querySelector('#bling-preview-btn');\n    if (previewBtn) {\n      previewBtn.addEventListener('click', () => this.generatePreview());\n    }\n    \n    // Submit button\n    const submitBtn = this.querySelector('#bling-submit-btn');\n    if (submitBtn) {\n      submitBtn.addEventListener('click', () => this.handleSubmit());\n    }\n  }\n\n  validateForm() {\n    const requiredFields = this.fields.filter(f => f.is_required);\n    let allValid = true;\n    const missing = [];\n    \n    for (const field of requiredFields) {\n      const value = this.getFieldValue(field);\n      const empty = !value || (Array.isArray(value) && value.length === 0);\n      const wrap = this.getFieldInput(field)?.closest('.bling-field-group') ||\n                   this.querySelector(`[data-field-id=\"${CSS.escape(String(field.id))}\"]`)?.closest('.bling-field-group');\n      // Only flag a missing value once the customer has left that field or tried to add to cart \u2014\n      // never on page load.\n      const show = this._showAllErrors || (this._touchedFields && this._touchedFields.has(String(field.id)));\n      if (wrap) wrap.classList.toggle('bling-field-invalid', empty && !!show);\n      if (empty) {\n        allValid = false;\n        missing.push(field.label || 'Required field');\n      }\n    }\n\n    if (allValid) {\n      for (const field of this.fields) {\n        const max = this.getMaxLength(field);\n        if (!max) continue;\n        const value = this.getFieldValue(field);\n        if (typeof value === 'string' && value.length > max) {\n          allValid = false;\n          break;\n        }\n      }\n    }\n    \n    const submitBtn = this.querySelector('#bling-submit-btn');\n    const previewBtn = this.querySelector('#bling-preview-btn');\n    \n    if (submitBtn) {\n      submitBtn.disabled = !allValid;\n    }\n    \n    if (previewBtn) {\n      previewBtn.disabled = !allValid;\n    }\n\n    this._lastValidationMissing = missing;\n    \n    return allValid;\n  }\n\n  getFieldValue(field) {\n    if (this.usesRadioInput(field)) {\n      const checked = this.querySelector(\n        `input[name=\"${CSS.escape(this.fieldRadioName(field.id))}\"]:checked`,\n      );\n      return checked ? checked.value : '';\n    }\n    \n    if (field.field_type === 'checkbox') {\n      const checked = Array.from(\n        this.querySelectorAll(`input[name=\"${CSS.escape(this.fieldCheckboxName(field.id))}\"]:checked`),\n      );\n      return checked.map(c => c.value);\n    }\n    \n    if (field.field_type === 'image' || field.field_type === 'file') {\n      const upload = this.uploads.get(field.id);\n      return upload ? upload.r2_key : '';\n    }\n    \n    const input = this.getFieldInput(field);\n    return input ? String(input.value || '').trim() : '';\n  }\n\n  async handleFileUpload(event) {\n    const input = event.target;\n    const fieldId = input.dataset.fieldId;\n    const file = input.files[0];\n    \n    if (!file) return;\n\n    const nameEl = this.querySelector(`#bling-filename-${CSS.escape(this.fieldDomId(fieldId))}`);\n    if (nameEl) {\n      nameEl.textContent = `\u2713 Selected: ${file.name}`;\n      nameEl.style.display = 'inline-block';\n    }\n\n    // Live canvas: composite the (bg-removed) logo right away, in parallel with upload.\n    if (this.canvasConfig && /^image\\//.test(file.type)) {\n      this.buildLogoCanvas(file, fieldId).then(() => this.redrawLivePreview()).catch(() => {});\n    }\n    \n    const progressDiv = this.querySelector(`#bling-progress-${CSS.escape(this.fieldDomId(fieldId))}`);\n    if (!progressDiv) return;\n    \n    progressDiv.style.display = 'block';\n    progressDiv.textContent = 'Uploading...';\n    progressDiv.className = 'bling-upload-progress';\n    \n    try {\n      const presignedRes = await fetch(`${this.config.platform_url}/api/uploads/presigned`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({\n          file_name: file.name,\n          file_size: file.size,\n          mime_type: file.type,\n        }),\n      });\n      \n      if (!presignedRes.ok) {\n        throw new Error('Failed to get upload URL');\n      }\n      \n      // API responds as { data: { upload_url, r2_key }, error }. Older deploys returned a flat object.\n      const presignedJson = await presignedRes.json();\n      const presignedData = presignedJson && presignedJson.data ? presignedJson.data : presignedJson;\n      if ((presignedJson && presignedJson.error) || !presignedData || !presignedData.upload_url) {\n        throw new Error((presignedJson && presignedJson.error) || 'Failed to get upload URL');\n      }\n      \n      const xhr = new XMLHttpRequest();\n      \n      xhr.upload.addEventListener('progress', (e) => {\n        if (e.lengthComputable) {\n          const percent = Math.round((e.loaded / e.total) * 100);\n          progressDiv.textContent = `Uploading... ${percent}%`;\n        }\n      });\n      \n      const uploadPromise = new Promise((resolve, reject) => {\n        xhr.addEventListener('load', () => {\n          if (xhr.status >= 200 && xhr.status < 300) {\n            resolve(xhr.status);\n          } else {\n            reject(new Error(`Upload failed with status ${xhr.status}`));\n          }\n        });\n        xhr.addEventListener('error', () => reject(new Error('Network error during upload')));\n        xhr.addEventListener('abort', () => reject(new Error('Upload cancelled')));\n        xhr.open('PUT', presignedData.upload_url);\n        xhr.setRequestHeader('Content-Type', file.type);\n        xhr.send(file);\n      });\n      \n      await uploadPromise;\n      \n      this.uploads.set(fieldId, {\n        field_id: fieldId,\n        r2_key: presignedData.r2_key,\n        file_name: file.name,\n        file_size: file.size,\n        mime_type: file.type,\n      });\n      \n      progressDiv.textContent = 'Upload complete!';\n      progressDiv.className = 'bling-upload-progress bling-upload-success';\n      \n      this.validateForm();\n      \n    } catch (error) {\n      console.error('[Bling] Upload failed:', error);\n      progressDiv.textContent = error.message || 'Upload failed. Please try again.';\n      progressDiv.className = 'bling-upload-progress bling-upload-error';\n      this.uploads.delete(fieldId);\n    }\n  }\n\n  async generatePreview() {\n    const checkLimit = this.canGeneratePreview();\n    if (!checkLimit.can) {\n      this.showError(checkLimit.reason);\n      return;\n    }\n    \n    const previewBtn = this.querySelector('#bling-preview-btn');\n    if (!previewBtn) return;\n    \n    previewBtn.disabled = true;\n    previewBtn.innerHTML = `\n      <svg class=\"bling-spinner\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\">\n        <circle cx=\"10\" cy=\"10\" r=\"8\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" opacity=\"0.3\"/>\n        <path d=\"M10 2 A8 8 0 0 1 18 10\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"/>\n      </svg>\n      Generating...\n    `;\n    \n    try {\n      const fieldValues = this.fields.map(field => ({\n        field_id: field.id,\n        label: field.label,\n        value: this.getFieldValue(field),\n      }));\n      \n      const productImage = document.querySelector('.pdp-media-slide.is-active img')?.src ||\n                          document.querySelector('.pdp-media-slide.active img')?.src ||\n                          document.querySelector('.pdp-main-viewer img')?.src ||\n                          document.querySelector('.product__media img')?.src ||\n                          document.querySelector('[data-media-id] img')?.src ||\n                          '';\n      \n      const res = await fetch(`${this.config.platform_url}/api/customization/preview`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({\n          product_id: this.config.product_id,\n          product_title: this.config.product_title,\n          product_image_url: productImage,\n          customization_fields: fieldValues,\n          session_id: this.sessionId,\n          variant_id: this._getActiveVariantId() || null,\n        }),\n      });\n      \n      const json = await res.json();\n      \n      if (!res.ok || json.error) {\n        throw new Error(json.error || 'Failed to generate preview');\n      }\n      \n      this.incrementPreviewCount();\n      this.generatedPreviews.push(json.data || json);\n      \n      this.showPreviewModal(json.data || json);\n      \n    } catch (error) {\n      console.error('[Bling] Preview generation failed:', error);\n      this.showError(error.message || 'Failed to generate preview. Please try again.');\n    } finally {\n      previewBtn.disabled = false;\n      previewBtn.innerHTML = `\n        <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n          <path d=\"M10 0L12 8L20 10L12 12L10 20L8 12L0 10L8 8L10 0Z\" fill=\"currentColor\"/>\n        </svg>\n        See realistic AI mockup\n      `;\n    }\n  }\n\n  showPreviewModal(previewData) {\n    const overlay = document.createElement('div');\n    overlay.className = 'bling-modal-overlay';\n    \n    overlay.innerHTML = `\n      <div class=\"bling-modal bling-preview-modal\">\n        <div class=\"bling-modal-header\">\n          <h2 class=\"bling-modal-title\">AI-Generated Preview</h2>\n          <button class=\"bling-modal-close\" aria-label=\"Close\">\n            <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M2 2L18 18M18 2L2 18\"/>\n            </svg>\n          </button>\n        </div>\n        <div class=\"bling-modal-body\">\n          <div class=\"bling-preview-disclaimer\">\n            <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n              <path d=\"M8 0L9.5 6.5L16 8L9.5 9.5L8 16L6.5 9.5L0 8L6.5 6.5L8 0Z\" fill=\"currentColor\"/>\n            </svg>\n            <span>${this.previewSettings.disclaimer_text ?? ''}</span>\n          </div>\n          \n          <div class=\"bling-preview-image-container\">\n            <img src=\"${previewData.preview_url}\" alt=\"AI Preview\" class=\"bling-preview-image\" />\n          </div>\n          \n          <div class=\"bling-preview-actions\">\n            <a href=\"${previewData.preview_url}\" download=\"preview.jpg\" class=\"bling-preview-download\">\n              <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M10 2V14M10 14L6 10M10 14L14 10M2 18H18\"/>\n              </svg>\n              Download Preview\n            </a>\n            <button class=\"bling-preview-continue\" id=\"bling-preview-continue\">\n              Looks Good! Add to Cart\n            </button>\n          </div>\n        </div>\n      </div>\n    `;\n    \n    document.body.appendChild(overlay);\n    \n    const closeBtn = overlay.querySelector('.bling-modal-close');\n    const continueBtn = overlay.querySelector('#bling-preview-continue');\n    \n    const close = () => {\n      overlay.remove();\n    };\n    \n    closeBtn.addEventListener('click', close);\n    overlay.addEventListener('click', (e) => {\n      if (e.target === overlay) close();\n    });\n    \n    continueBtn.addEventListener('click', () => {\n      close();\n      this.handleSubmit();\n    });\n  }\n\n  async _addLineItemAndOpenDrawer(form) {\n    const rawVariant = (this.config && this.config.section_id && document.getElementById('PdpVariantId-' + this.config.section_id)?.value) ||\n      this._getActiveVariantId() ||\n      form.querySelector('[name=\"id\"]')?.value;\n    const variantId = rawVariant ? parseInt(String(rawVariant), 10) : NaN;\n    if (!variantId || isNaN(variantId)) throw new Error('Cannot find valid variant for product');\n\n    // Keep form hidden variant input synchronized\n    const idInput = form.querySelector('[name=\"id\"]');\n    if (idInput) idInput.value = String(variantId);\n\n    const qty = parseInt(form.querySelector('[name=\"quantity\"]')?.value || '1', 10) || 1;\n    const properties = {};\n    form.querySelectorAll('input[name^=\"properties[\"]').forEach((el) => {\n      const m = el.name.match(/^properties\\[(.+)\\]$/);\n      if (m && el.value) properties[m[1]] = el.value;\n    });\n\n    const sectionIds = [];\n    document.querySelectorAll('cart-items-component').forEach((el) => {\n      if (el.dataset.sectionId && !sectionIds.includes(el.dataset.sectionId)) {\n        sectionIds.push(el.dataset.sectionId);\n      }\n    });\n    if (!sectionIds.includes('cart-drawer-section')) sectionIds.push('cart-drawer-section');\n\n    const addRes = await fetch((window.Theme && window.Theme.routes && window.Theme.routes.cart_add_url) || '/cart/add.js', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n      body: JSON.stringify({\n        items: [{ id: variantId, quantity: qty, properties }],\n        sections: sectionIds.join(','),\n        sections_url: window.location.pathname,\n      }),\n    });\n    const added = await addRes.json();\n    if (!addRes.ok || added.status) {\n      throw new Error(added.description || added.message || 'Failed to add to cart');\n    }\n\n    await this._refreshCartDrawer(added, sectionIds);\n    this._openCartDrawer();\n    this._updateCartBubble();\n  }\n\n  async _refreshCartDrawer(addResponse, sectionIds) {\n    const ids = Array.isArray(sectionIds) && sectionIds.length ? sectionIds : ['cart-drawer-section'];\n    let sections = (addResponse && addResponse.sections) || {};\n    const missing = ids.filter((id) => !sections[id]);\n    if (missing.length) {\n      try {\n        const secRes = await fetch(`/?sections=${encodeURIComponent(missing.join(','))}`);\n        if (secRes.ok) {\n          const extra = await secRes.json();\n          sections = { ...sections, ...extra };\n        }\n      } catch (_) {}\n    }\n\n    ids.forEach((id) => {\n      const html = sections[id];\n      if (!html) return;\n      const live = document.getElementById(`shopify-section-${id}`);\n      if (!live) return;\n      const doc = new DOMParser().parseFromString(html, 'text/html');\n      const incoming = doc.getElementById(`shopify-section-${id}`) || doc.body;\n      live.innerHTML = incoming.innerHTML;\n    });\n\n    const cartItems = document.querySelector('cart-items-component');\n    if (cartItems && typeof cartItems.fetchCartData === 'function') {\n      try { await cartItems.fetchCartData(); } catch (_) {}\n    }\n  }\n\n  _openCartDrawer() {\n    const drawer = document.querySelector('theme-drawer#cart-drawer');\n    if (drawer && typeof drawer.open === 'function') {\n      drawer.open();\n      return;\n    }\n    const trigger = document.querySelector('[aria-controls=\"cart-drawer\"], [data-testid=\"cart-drawer-trigger\"]');\n    if (trigger) trigger.click();\n  }\n\n  _updateCartBubble() {\n    fetch('/cart.js')\n      .then((r) => r.json())\n      .then((cart) => {\n        const count = cart.item_count || 0;\n        document.querySelectorAll('[data-cart-count], .cart-count, .cart-bubble').forEach((el) => {\n          el.textContent = String(count);\n        });\n        document.querySelectorAll('.ch-cart-dot').forEach((dot) => {\n          dot.textContent = count > 0 ? String(count) : '';\n          dot.style.display = count > 0 ? 'flex' : 'none';\n        });\n      })\n      .catch(() => {});\n  }\n\n  async handleSubmit() {\n    this._showAllErrors = true;\n    if (!this.validateForm()) {\n      this.showError(\n        (this._lastValidationMissing && this._lastValidationMissing.length)\n          ? `Please complete: ${this._lastValidationMissing.join(', ')}`\n          : 'Please fill in all required fields',\n      );\n      return;\n    }\n    \n    if (this.isSubmitting) return;\n    this.isSubmitting = true;\n    \n    const submitBtn = this.querySelector('#bling-submit-btn');\n    if (submitBtn) {\n      submitBtn.disabled = true;\n      submitBtn.textContent = 'Processing...';\n    }\n    \n    try {\n      const fieldValues = this._collectFieldValues();\n      \n      const uploadData = Array.from(this.uploads.values());\n      \n      const res = await fetch(`${this.config.platform_url}/api/customization/submit`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({\n          config_id: this.configId,\n          shopify_product_id: this.config.product_id,\n          field_values: fieldValues,\n          uploads: uploadData,\n          session_id: this.sessionId,\n          variant_id: this._getActiveVariantId() || null,\n        }),\n      });\n      \n      const json = await res.json();\n      \n      if (!res.ok || json.error) {\n        throw new Error(json.error || 'Submission failed');\n      }\n      \n      const form = this._findCartForm();\n      if (!form) {\n        throw new Error('Cart form not found');\n      }\n\n      const submissionId = json.data?.submission_id || json.submission_id;\n      this._applyCartProperties(form, submissionId);\n      \n      this.addToCartButtonListeners.forEach((handler, button) => {\n        button.removeEventListener('click', handler, true);\n      });\n      this.paymentButtonListeners.forEach((handler, button) => {\n        button.removeEventListener('click', handler, true);\n      });\n      \n      if (this.isBuyNow) {\n        const buyNowBtn = document.querySelector('.shopify-payment-button__button');\n        if (buyNowBtn) {\n          buyNowBtn.click();\n        }\n      } else {\n        await this._addLineItemAndOpenDrawer(form);\n        this.isSubmitting = false;\n        if (submitBtn) {\n          submitBtn.disabled = false;\n          submitBtn.textContent = this.isBuyNow ? 'Continue to Checkout' : 'Add to Cart';\n        }\n      }\n      \n    } catch (error) {\n      console.error('[Bling] Submission failed:', error);\n      this.showError(error.message || 'Failed to submit. Please try again.');\n      this.isSubmitting = false;\n      \n      if (submitBtn) {\n        submitBtn.disabled = false;\n        submitBtn.textContent = this.isBuyNow ? 'Continue to Checkout' : 'Add to Cart';\n      }\n    }\n  }\n\n  async submitCustomizationAndContinue() {\n    this._showAllErrors = true;\n    if (!this.validateForm()) {\n      this.showError(\n        (this._lastValidationMissing && this._lastValidationMissing.length)\n          ? `Please complete: ${this._lastValidationMissing.join(', ')}`\n          : 'Please fill in all required fields',\n      );\n      // Re-enable native buttons\n      const nativeAtc = document.getElementById('PdpAtcBtn-' + this.config.section_id);\n      if (nativeAtc) nativeAtc.disabled = false;\n      const nativeBuyNow = document.getElementById('PdpBuyNowBtn-' + this.config.section_id);\n      if (nativeBuyNow) nativeBuyNow.disabled = false;\n      return;\n    }\n\n    if (!this.configId || !this.fields || this.fields.length === 0) {\n      console.warn('[Bling] No customization active. Bypassing customization submit.');\n      this.isSubmitting = false;\n      const nativeAtc = document.getElementById('PdpAtcBtn-' + this.config.section_id);\n      const nativeBuyNow = document.getElementById('PdpBuyNowBtn-' + this.config.section_id);\n      if (nativeAtc) nativeAtc.disabled = false;\n      if (nativeBuyNow) {\n        nativeBuyNow.disabled = false;\n        nativeBuyNow.textContent = 'Buy Now';\n      }\n      return;\n    }\n\n    if (this.isSubmitting) return;\n    this.isSubmitting = true;\n\n    const nativeAtc = document.getElementById('PdpAtcBtn-' + this.config.section_id);\n    const nativeBuyNow = document.getElementById('PdpBuyNowBtn-' + this.config.section_id);\n    let originalAtcText = '';\n    \n    if (nativeAtc) {\n      const textEl = nativeAtc.querySelector('.pdp-atc-btn__text');\n      if (textEl) {\n        originalAtcText = textEl.textContent;\n        textEl.textContent = 'Processing...';\n      }\n      nativeAtc.disabled = true;\n    }\n    if (nativeBuyNow) {\n      nativeBuyNow.textContent = 'Processing...';\n      nativeBuyNow.disabled = true;\n    }\n\n    try {\n      const fieldValues = this._collectFieldValues();\n      \n      const uploadData = Array.from(this.uploads.values());\n      \n      const res = await fetch(`${this.config.platform_url}/api/customization/submit`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({\n          config_id: this.configId,\n          shopify_product_id: this.config.product_id,\n          field_values: fieldValues,\n          uploads: uploadData,\n          session_id: this.sessionId,\n          variant_id: this._getActiveVariantId() || null,\n        }),\n      });\n      \n      const json = await res.json();\n      \n      if (!res.ok || json.error) {\n        throw new Error(json.error || 'Submission failed');\n      }\n      \n      const form = this._findCartForm();\n      if (!form) {\n        throw new Error('Cart form not found');\n      }\n\n      const submissionId = json.data?.submission_id || json.submission_id;\n      this._applyCartProperties(form, submissionId);\n      \n      if (this.isBuyNow) {\n        const rawVariant = (this.config && this.config.section_id && document.getElementById('PdpVariantId-' + this.config.section_id)?.value) ||\n          this._getActiveVariantId() ||\n          form.querySelector('[name=\"id\"]')?.value;\n        const variantId = rawVariant ? parseInt(String(rawVariant), 10) : NaN;\n        if (!variantId || isNaN(variantId)) throw new Error('Cannot find valid variant for product');\n\n        const idInput = form.querySelector('[name=\"id\"]');\n        if (idInput) idInput.value = String(variantId);\n\n        const qty = parseInt(form.querySelector('[name=\"quantity\"]')?.value || '1', 10) || 1;\n        const properties = {};\n        form.querySelectorAll('input[name^=\"properties[\"]').forEach((el) => {\n          const m = el.name.match(/^properties\\[(.+)\\]$/);\n          if (m) properties[m[1]] = el.value;\n        });\n        const payload = { id: variantId, quantity: qty, properties };\n        \n        const cartAddRes = await fetch('/cart/add.js', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ items: [payload] })\n        });\n        if (cartAddRes.ok) {\n          window.location.href = '/checkout';\n        } else {\n          const cartErr = await cartAddRes.json().catch(() => ({}));\n          throw new Error(cartErr.description || cartErr.message || 'Failed to checkout');\n        }\n      } else {\n        await this._addLineItemAndOpenDrawer(form);\n        if (nativeAtc) {\n          nativeAtc.disabled = false;\n          const textEl = nativeAtc.querySelector('.pdp-atc-btn__text');\n          if (textEl) textEl.textContent = originalAtcText;\n        }\n        this.isSubmitting = false;\n      }\n    } catch (error) {\n      console.error('[Bling] Customization submit error:', error);\n      this.showError(error.message || 'Failed to submit customization. Please try again.');\n      this.isSubmitting = false;\n      if (nativeAtc) {\n        nativeAtc.disabled = false;\n        const textEl = nativeAtc.querySelector('.pdp-atc-btn__text');\n        if (textEl) textEl.textContent = originalAtcText;\n      }\n      if (nativeBuyNow) {\n        nativeBuyNow.disabled = false;\n        nativeBuyNow.textContent = 'Buy Now';\n      }\n    }\n  }\n\n  showError(message) {\n    const errorDiv = this.querySelector('#bling-error');\n    if (errorDiv) {\n      errorDiv.textContent = message;\n      errorDiv.style.display = 'block';\n      setTimeout(() => {\n        errorDiv.style.display = 'none';\n      }, 5000);\n    }\n  }\n}\n\ncustomElements.define('bling-customization-form', BlingCustomizationForm);\n"],
  "mappings": "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",
  "names": ["spanMap", "count", "parentBlock", "opt", "m", "nativeAtc", "nativeBuyNow"]
}
