{
  "version": 3,
  "sources": ["/cdn/shop/t/2/assets/custom-prints-widget-native.js?cp=20260719thisday3"],
  "sourcesContent": ["/* custom-prints-widget (native) \u2014 upload -> AI preview -> pick a design, wired into the NATIVE Shopify buy box.\n *\n * Lean buy-box MODULE, not a page takeover. The theme's native product form owns size selection,\n * price and Add-to-Cart. This widget only:\n *   1. collects photos (two buckets: family here today + in loving memory) and calls the preview API,\n *   2. shows the generated preview INLINE (never touches the product gallery/hero),\n *   3. lets the customer pick a favourite design,\n *   4. writes the chosen art into the native product form as hidden line-item properties, and\n *   5. gates the native Add-to-Cart until a design is chosen.\n *\n * Config (window.CUSTOM_PRINTS_CONFIG): apiBase (required), mount, variations, designLabel.\n * Fonts/colours inherit the theme (store font = Josefin); only structural styles are injected.\n */\n(function () {\n  \"use strict\";\n\n  const cfg = window.CUSTOM_PRINTS_CONFIG || {};\n  const API = (cfg.apiBase || \"\").replace(/\\/$/, \"\");\n  const OPTIONS_COUNT = Math.max(1, Math.min(Number(cfg.variations) || 4, 4));\n  const MAX_UPLOAD_EDGE = 1024;\n  const UPLOAD_JPEG_QUALITY = 0.84;\n  // 90s (was 45s): `auto` runs ~60\u201395s per option. The curve is asymptotic, so this constant is\n  // the time-scale, not a deadline \u2014 bigger = slower tick. 60s\u224846%, 120s\u224869%, 180s\u224881%.\n    // 45s \u2014 matches `low` (~20\u201330s/option). If quality ever goes back to `auto` (~100\u2013260s),\n  // raise this or the bar parks near the cap for minutes.\nconst PROGRESS_TOTAL_MS = 45 * 1000;\n  const DESIGN_LABEL = cfg.designLabel || \"Family Together Again canvas\";\n  const CONCEPT = cfg.concept || \"family-together\";\n  // skipPreview: the \"upload-only\" funnel. Instead of generating N previews in the widget and\n  // making the customer pick one, we just store their photos+names (POST /api/capture) and let\n  // them check out \u2014 an artist proof is emailed for approval before it prints. Everything below\n  // that branches on this (gate, form props, capture(), UI copy) keys off SKIP_PREVIEW so every\n  // existing product keeps the preview flow unchanged.\n  const SKIP_PREVIEW = cfg.skipPreview === true;\n  // Copy shown once photos are saved (skip-preview flow). Overridable per product.\n  const CAPTURE_CONFIRM = cfg.captureConfirm ||\n    \"We'll email you a finished artwork to approve before it prints.\";\n\n  // \u2500\u2500 per-product config (engine is generic; these are the swappable slots) \u2500\u2500\n  // uploads: which photo buckets to collect. memory:true tags people as departed\n  // (adds wings server-side); collectYears:true shows born/passed fields.\n  const DEFAULT_UPLOADS = [\n    { id: \"living\", label: \"Your family\", sublabel: \"\u2014 everyone here with us today\",\n      icon: \"\uFF0B\", cta: \"Add family photos\", hint: \"Tap to upload \u00B7 one clear face per photo\" },\n    { id: \"memory\", label: \"In loving memory\", sublabel: \"\u2014 painted as guardian angels\",\n      icon: \"\uD83D\uDD4A\uFE0F\", cta: \"Add someone who has passed\", hint: \"Optional \u00B7 we'll paint them with soft angel wings\",\n      memory: true, collectYears: true, variant: \"memory\" }\n  ];\n  const UPLOADS = Array.isArray(cfg.uploads) && cfg.uploads.length ? cfg.uploads : DEFAULT_UPLOADS;\n  // fields: extra dropdown/text/toggle inputs that flow into the concept prompt.\n  // [{ id, type:\"dropdown\"|\"text\"|\"toggle\", label, options?, placeholder?, hint? }]\n  const FIELDS = Array.isArray(cfg.fields) ? cfg.fields : [];\n  const MAX_PEOPLE = Math.max(1, Number(cfg.maxPhotos) || 8);\n  // Placeholder for the per-photo name box. Default keeps \"(optional)\" so every existing\n  // product reads exactly as before; products whose whole subject is the names (grandma-garden)\n  // override it, because hedging a feature the customer came for undersells it.\n  const NAME_PLACEHOLDER = typeof cfg.namePlaceholder === \"string\" && cfg.namePlaceholder\n    ? cfg.namePlaceholder\n    : \"Name (optional)\";\n\n  const LOADING_MESSAGES = Array.isArray(cfg.loadingMessages) && cfg.loadingMessages.length ? cfg.loadingMessages : [\n    // Deliberately generic + product-agnostic. Concept-specific lines (\"adding soft wings\u2026\")\n    // mean every new product needs copy written before it can ship. Override via\n    // cfg.loadingMessages only if a product genuinely earns it.\n    \"Getting your photos ready\u2026\",\n    \"Starting your artwork\u2026\",\n    \"Painting the details\u2026\",\n    \"Adding the finishing touches\u2026\",\n    \"Almost done\u2026\"\n  ];\n\n  // \u2500\u2500 state \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  // people: { file, objectUrl, name, birthYear, deathYear, deceased, bucket }\n  // fields: { [fieldId]: value }\n  const state = { people: [], fields: {}, previews: [], selectedIndex: 0, generating: false, error: \"\", captured: null, captureCount: 0 };\n  const selectedPreview = () => state.previews[state.selectedIndex] || null;\n  // What \"ready to add to cart\" means: a saved capture (skip-preview) or a chosen preview.\n  const readyToAdd = () => SKIP_PREVIEW ? !!state.captured : !!selectedPreview();\n  // Editing photos/names after a capture invalidates it \u2014 force a re-save before checkout.\n  function invalidateCapture() {\n    if (!SKIP_PREVIEW || !state.captured) return;\n    state.captured = null; state.captureCount = 0;\n    setFormProp(\"properties[_capture_id]\", \"\");\n    setGate(true);\n  }\n\n  const $ = (sel, root = document) => root.querySelector(sel);\n  const esc = (s) => String(s).replace(/[&<>\"]/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\" }[c]));\n  let root;\n\n  function init() {\n    root = $(cfg.mount || \"#custom-prints-widget\");\n    if (!root) { console.error(\"[custom-prints] mount not found:\", cfg.mount); return; }\n    if (!API) console.warn(\"[custom-prints] no apiBase configured\");\n    injectStyles();\n    render();\n    installFormGate();\n  }\n\n  // \u2500\u2500 native buy-box integration \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  function nativeForm() {\n    const pf = document.querySelector(\"product-form form\") || document.querySelector('form[action*=\"/cart/add\"]');\n    return pf || null;\n  }\n  function nativeButton() {\n    const form = nativeForm();\n    return form ? form.querySelector('[name=\"add\"]') : null;\n  }\n  function setFormProp(name, value) {\n    const form = nativeForm();\n    if (!form) return;\n    let el = form.querySelector('input[data-cp=\"1\"][name=\"' + name.replace(/\"/g, '\\\\\"') + '\"]');\n    if (!el) {\n      el = document.createElement(\"input\");\n      el.type = \"hidden\"; el.name = name; el.setAttribute(\"data-cp\", \"1\");\n      form.appendChild(el);\n    }\n    el.value = value == null ? \"\" : String(value);\n  }\n  function personalizationSummary() {\n    return state.people.map((p) => {\n      const nm = (p.name || \"\").trim();\n      const years = p.deceased && (p.birthYear || p.deathYear) ? \" (\" + (p.birthYear || \"?\") + \"\u2013\" + (p.deathYear || \"?\") + \")\" : \"\";\n      const wings = p.deceased ? \" \u2014 in loving memory\" : \"\";\n      return (nm || \"Photo\") + years + wings;\n    }).join(\", \");\n  }\n  function writeChosenToForm() {\n    if (SKIP_PREVIEW) {\n      if (!state.captured) return;\n      // The capture id is how fulfillment finds this order's uploaded photos + names.\n      setFormProp(\"properties[_capture_id]\", state.captured);\n      setFormProp(\"properties[Design]\", DESIGN_LABEL);\n      const summary = personalizationSummary();\n      if (summary) setFormProp(\"properties[Personalization]\", summary);\n      return;\n    }\n    const chosen = selectedPreview();\n    if (!chosen) return;\n    setFormProp(\"properties[_preview_id]\", chosen.id);\n    setFormProp(\"properties[_preview_url]\", chosen.previewUrl);\n    setFormProp(\"properties[Design]\", DESIGN_LABEL);\n    const summary = personalizationSummary();\n    if (summary) setFormProp(\"properties[Personalization]\", summary);\n  }\n  function setGate(gated) {\n    const btn = nativeButton();\n    if (btn) {\n      btn.disabled = gated;\n      btn.classList.toggle(\"cp-gated\", gated);\n      btn.setAttribute(\"aria-disabled\", gated ? \"true\" : \"false\");\n    }\n  }\n  let gateInstalled = false;\n  function installFormGate() {\n    const form = nativeForm();\n    if (!form || gateInstalled) return;\n    gateInstalled = true;\n    form.addEventListener(\"submit\", function (e) {\n      if (!readyToAdd()) {\n        e.preventDefault(); e.stopImmediatePropagation();\n        state.error = SKIP_PREVIEW\n          ? \"Please add your photos and tap Save before adding to cart.\"\n          : \"Please create your artwork and pick a design before adding to cart.\";\n        render();\n        root.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n      } else {\n        writeChosenToForm();\n      }\n    }, true);\n    const info = form.closest(\"product-info\") || form;\n    new MutationObserver(() => setGate(!readyToAdd())).observe(info, { childList: true, subtree: true });\n    setGate(!readyToAdd());\n  }\n\n  // \u2500\u2500 actions \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  function addPhotos(fileList, bucket) {\n    const files = Array.from(fileList).filter((f) => /^image\\//.test(f.type));\n    for (const file of files) {\n      if (state.people.length >= MAX_PEOPLE) break;\n      state.people.push({\n        file, objectUrl: URL.createObjectURL(file), name: \"\", birthYear: \"\", deathYear: \"\",\n        deceased: !!bucket.memory, bucket: bucket.id, collectYears: !!bucket.collectYears\n      });\n    }\n    state.error = \"\";\n    invalidateCapture();\n    render();\n  }\n  function removePerson(i) {\n    URL.revokeObjectURL(state.people[i].objectUrl);\n    state.people.splice(i, 1);\n    invalidateCapture();\n    render();\n  }\n\n  async function generate() {\n    if (!state.people.length || state.generating) return;\n    state.generating = true; state.error = \"\"; loadPct = 0; loadMsgIdx = 0; loadStartedAt = Date.now(); render();\n    let completed = false;\n    // 90s watchdog: if not one option has arrived by 90s, abort and show a clear error.\n    // With medium fixed (~65s to first option) this only fires on a genuine hang.\n    const ac = new AbortController();\n    let timedOut = false;\n    const watchdog = setTimeout(() => { if (!completed) { timedOut = true; ac.abort(); } }, 90000);\n    try {\n      const form = new FormData();\n      const people = state.people.map((p, i) => ({ name: p.name, photoIndex: i, deceased: p.deceased, birthYear: p.birthYear, deathYear: p.deathYear, bucket: p.bucket }));\n      // Resize on the customer's device before uploading so several large phone\n      // photos don't spend most of the wait travelling over the network.\n      const uploadFiles = await Promise.all(state.people.map((p, i) => prepareUpload(p.file, i)));\n      uploadFiles.forEach((file) => form.append(\"photos\", file));\n      form.append(\"people\", JSON.stringify(people));\n      form.append(\"fields\", JSON.stringify(state.fields || {}));\n      form.append(\"concept\", CONCEPT);\n      form.append(\"variations\", String(OPTIONS_COUNT));\n      // The preview server may be waking from idle (cold start), so a first\n      // request can fail at the network level \u2014 retry once after a short wait.\n      // Ask for NDJSON so each option can be painted as it finishes. The server only streams if\n      // asked, so this stays safe if the two ever get out of sync.\n      const opts = { method: \"POST\", body: form, headers: { Accept: \"application/x-ndjson\" }, signal: ac.signal };\n      // The preview server may be waking from idle (cold start), so a first\n      // request can fail at the network level \u2014 retry once after a short wait.\n      let res;\n      try {\n        res = await fetch(API + \"/api/preview\", opts);\n      } catch (netErr) {\n        await new Promise((r) => setTimeout(r, 4000));\n        res = await fetch(API + \"/api/preview\", opts);\n      }\n      if (!res.ok) throw new Error(\"preview-failed\");\n\n      const streaming = (res.headers.get(\"content-type\") || \"\").indexOf(\"application/x-ndjson\") !== -1\n        && res.body && typeof res.body.getReader === \"function\";\n\n      if (streaming) {\n        state.previews = [];\n        state.selectedIndex = 0;\n        const reader = res.body.getReader();\n        const decoder = new TextDecoder();\n        let buf = \"\", streamErr = \"\";\n        for (;;) {\n          const chunk = await reader.read();\n          if (chunk.done) break;\n          buf += decoder.decode(chunk.value, { stream: true });\n          let nl;\n          // NDJSON: a chunk can hold several lines or half a line, so only parse complete ones.\n          while ((nl = buf.indexOf(\"\\n\")) !== -1) {\n            const line = buf.slice(0, nl).trim();\n            buf = buf.slice(nl + 1);\n            if (!line) continue;\n            let msg;\n            try { msg = JSON.parse(line); } catch (e) { continue; }\n            if (msg.type === \"preview\" && msg.previewUrl) {\n              state.previews.push({ id: msg.id, previewUrl: msg.previewUrl });\n              // Unlock ATC on the FIRST option: the customer can commit without waiting for the rest.\n              if (state.previews.length === 1) { completed = true; writeChosenToForm(); setGate(false); }\n              render();\n            } else if (msg.type === \"done\") {\n              if (Array.isArray(msg.previews) && msg.previews.length) state.previews = msg.previews;\n            } else if (msg.type === \"error\") {\n              streamErr = \"preview-failed\";\n            }\n          }\n        }\n        if (!state.previews.length) throw new Error(streamErr || \"preview-failed\");\n        writeChosenToForm(); setGate(false); completed = true;\n      } else {\n        const data = await res.json().catch(() => ({}));\n        state.previews = Array.isArray(data.previews) && data.previews.length ? data.previews\n          : data.previewUrl ? [{ id: data.id, previewUrl: data.previewUrl }] : [];\n        state.selectedIndex = 0;\n        if (state.previews.length) { completed = true; writeChosenToForm(); setGate(false); }\n        else throw new Error(\"preview-failed\");\n      }\n    } catch (err) {\n      // Never surface raw technical errors (e.g. \"Failed to fetch\") to the customer.\n      state.error = timedOut\n        ? \"Regen not working, try again later. If issue persists please contact support@hearthcove.com\"\n        : \"Preview failed. Please try again.\";\n    } finally {\n      clearTimeout(watchdog);\n      if (completed) await finishLoadingAnimation();\n      state.generating = false; stopLoadingAnimation(); render();\n    }\n  }\n\n  // skip-preview flow: store the customer's photos+names (no generation) and ungate checkout.\n  // Storage MUST succeed here (unlike /api/preview, which can degrade) \u2014 the order is worthless\n  // to fulfillment without the saved photos \u2014 so any non-ok response surfaces a retry.\n  async function capture() {\n    if (!state.people.length || state.generating) return;\n    state.generating = true; state.error = \"\"; render();\n    const ac = new AbortController();\n    let timedOut = false;\n    const watchdog = setTimeout(() => { timedOut = true; ac.abort(); }, 90000);\n    try {\n      const form = new FormData();\n      const people = state.people.map((p, i) => ({ name: p.name, photoIndex: i, deceased: p.deceased, birthYear: p.birthYear, deathYear: p.deathYear, bucket: p.bucket }));\n      const uploadFiles = await Promise.all(state.people.map((p, i) => prepareUpload(p.file, i)));\n      uploadFiles.forEach((file) => form.append(\"photos\", file));\n      form.append(\"people\", JSON.stringify(people));\n      form.append(\"fields\", JSON.stringify(state.fields || {}));\n      form.append(\"concept\", CONCEPT);\n      const opts = { method: \"POST\", body: form, headers: { Accept: \"application/json\" }, signal: ac.signal };\n      let res;\n      try {\n        res = await fetch(API + \"/api/capture\", opts);\n      } catch (netErr) {\n        await new Promise((r) => setTimeout(r, 4000));\n        res = await fetch(API + \"/api/capture\", opts);\n      }\n      if (!res.ok) throw new Error(\"capture-failed\");\n      const data = await res.json().catch(() => ({}));\n      if (!data || !data.captureId) throw new Error(\"capture-failed\");\n      state.captured = data.captureId;\n      state.captureCount = data.sourceCount || state.people.length;\n      writeChosenToForm(); setGate(false);\n    } catch (err) {\n      state.error = timedOut\n        ? \"Couldn't save right now \u2014 please try again. If it keeps happening, email support@hearthcove.com\"\n        : \"Couldn't save your photos. Please try again.\";\n    } finally {\n      clearTimeout(watchdog);\n      state.generating = false; render();\n    }\n  }\n\n  async function prepareUpload(file, index) {\n    if (typeof createImageBitmap !== \"function\") return file;\n\n    let bitmap;\n    try {\n      bitmap = await createImageBitmap(file, { imageOrientation: \"from-image\" });\n      const scale = Math.min(1, MAX_UPLOAD_EDGE / Math.max(bitmap.width, bitmap.height));\n      const width = Math.max(1, Math.round(bitmap.width * scale));\n      const height = Math.max(1, Math.round(bitmap.height * scale));\n      const canvas = document.createElement(\"canvas\");\n      canvas.width = width;\n      canvas.height = height;\n      const context = canvas.getContext(\"2d\");\n      if (!context) return file;\n      context.drawImage(bitmap, 0, 0, width, height);\n\n      const blob = await new Promise((resolve) => canvas.toBlob(resolve, \"image/jpeg\", UPLOAD_JPEG_QUALITY));\n      if (!blob) return file;\n      return new File([blob], `portrait-${index + 1}.jpg`, {\n        type: \"image/jpeg\",\n        lastModified: file.lastModified\n      });\n    } catch (err) {\n      console.warn(\"[custom-prints] using original upload; browser resize failed\", err);\n      return file;\n    } finally {\n      if (bitmap && typeof bitmap.close === \"function\") bitmap.close();\n    }\n  }\n  function pickDesign(i) { state.selectedIndex = i; writeChosenToForm(); setGate(false); render(); }\n\n  // \u2500\u2500 loading animation \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\u2500\u2500\u2500\u2500\n  let loadTimer = null, loadPct = 0, loadMsgIdx = 0, loadStartedAt = 0;\n  function progressForElapsed(elapsedMs) {\n    // Tuned to medium's ~65-70s render (2026-07-17). Climb to 95% over the first 70s,\n    // then crawl 95->99% from 70-90s. At 90s the watchdog in generate() aborts with an\n    // error, so the bar never sits frozen. finishLoadingAnimation() snaps to 100% the\n    // instant the previews arrive.\n    const s = elapsedMs / 1000;\n    if (s <= 70) return 95 * (s / 70);\n    if (s <= 90) return 95 + 4 * ((s - 70) / 20);\n    return 99;\n  }\n  // Paint the fill as a hard-stop background gradient on the bar element itself\n  // (color = fill, background-color = track). This is the robust technique proven on\n  // the custom-song page \u2014 no child element, no width transition to misfire.\n  function paintBar(el, pct) {\n    if (!el) return;\n    const fg = el._fg || (el._fg = getComputedStyle(el).color);\n    el.style.backgroundImage = \"linear-gradient(to right, \" + fg + \" \" + pct + \"%, transparent \" + pct + \"%)\";\n  }\n  function paintLoadingProgress() {\n    const elapsed = Math.max(0, Date.now() - loadStartedAt);\n    loadPct = progressForElapsed(elapsed);\n    loadMsgIdx = Math.min(LOADING_MESSAGES.length - 1, Math.floor(loadPct / 20));\n    const progress = $(\".cp-progress\", root);\n    paintBar(progress, loadPct);\n    if (progress) progress.setAttribute(\"aria-valuenow\", String(Math.round(loadPct)));\n    const label = $(\".cp-loading-msg\", root);\n    const percent = $(\".cp-progress-percent\", root);\n    if (label) label.textContent = LOADING_MESSAGES[loadMsgIdx];\n    if (percent) percent.textContent = Math.round(loadPct) + \"%\";\n  }\n  function startLoadingAnimation() {\n    if (loadTimer) return;\n    paintLoadingProgress();\n    loadTimer = setInterval(paintLoadingProgress, 200);\n  }\n  function finishLoadingAnimation() {\n    stopLoadingAnimation();\n    const startPct = loadPct;\n    const startedAt = Date.now();\n    const duration = 450;\n    return new Promise((resolve) => {\n      const step = () => {\n        const ratio = Math.min(1, (Date.now() - startedAt) / duration);\n        loadPct = startPct + (100 - startPct) * ratio;\n        const progress = $(\".cp-progress\", root);\n        const percent = $(\".cp-progress-percent\", root);\n        paintBar(progress, loadPct);\n        if (progress) progress.setAttribute(\"aria-valuenow\", String(Math.round(loadPct)));\n        if (percent) percent.textContent = Math.round(loadPct) + \"%\";\n        if (ratio < 1) requestAnimationFrame(step);\n        else resolve();\n      };\n      requestAnimationFrame(step);\n    });\n  }\n  function stopLoadingAnimation() { if (loadTimer) clearInterval(loadTimer); loadTimer = null; }\n\n  // \u2500\u2500 render \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  function render() {\n    root.innerHTML = `<div class=\"cp-module\">${viewUploader()}${viewResults()}${viewGateNote()}</div>`;\n    wireEvents();\n    if (state.generating) startLoadingAnimation();\n  }\n\n  function personChips(bucket) {\n    return state.people\n      .map((p, i) => ({ p, i }))\n      .filter((x) => x.p.bucket === bucket.id)\n      .map(({ p, i }) => `\n        <div class=\"cp-person\" data-i=\"${i}\">\n          <div class=\"cp-person-top\">\n            <img class=\"cp-person-thumb\" src=\"${esc(p.objectUrl)}\" alt=\"\" />\n            <button class=\"cp-person-remove\" data-remove=\"${i}\" title=\"Remove\">\u2715</button>\n            <div class=\"cp-person-fields\">\n              ${cfg.collectNames === false ? \"\" : `<input class=\"cp-input\" data-field=\"name\" data-i=\"${i}\" placeholder=\"${esc(NAME_PLACEHOLDER)}\" value=\"${esc(p.name)}\" />`}\n              ${bucket.collectYears ? `<div class=\"cp-years\">\n                <input class=\"cp-input cp-input--year\" data-field=\"birthYear\" data-i=\"${i}\" placeholder=\"Born (e.g. 1940)\" value=\"${esc(p.birthYear)}\" maxlength=\"4\"/>\n                <span class=\"cp-dash\">\u2013</span>\n                <input class=\"cp-input cp-input--year\" data-field=\"deathYear\" data-i=\"${i}\" placeholder=\"Passed (e.g. 2019)\" value=\"${esc(p.deathYear)}\" maxlength=\"4\"/>\n              </div>` : \"\"}\n            </div>\n          </div>\n        </div>`)\n      .join(\"\");\n  }\n\n  function viewBucket(b) {\n    const memory = b.variant === \"memory\" || b.memory;\n    return `\n      <div class=\"cp-bucket${memory ? \" cp-bucket--memory\" : \"\"}\">\n        <div class=\"cp-bucket-label\">${esc(b.label || \"\")} ${b.sublabel ? `<span class=\"cp-bucket-sub\">${esc(b.sublabel)}</span>` : \"\"}</div>\n        <button type=\"button\" class=\"cp-drop${memory ? \" cp-drop--memory\" : \"\"}\" data-bucket=\"${esc(b.id)}\">\n          <input type=\"file\" class=\"cp-file\" data-bucket=\"${esc(b.id)}\" accept=\"image/*\" multiple hidden />\n          <span class=\"cp-drop-icon\" aria-hidden=\"true\">${esc(b.icon || \"\uFF0B\")}</span>\n          <span class=\"cp-drop-main\">${esc(b.cta || \"Add photos\")}</span>\n          ${b.hint ? `<span class=\"cp-drop-sub\">${esc(b.hint)}</span>` : \"\"}\n        </button>\n        <div class=\"cp-people\">${personChips(b)}</div>\n      </div>`;\n  }\n\n  function viewFields() {\n    if (!FIELDS.length) return \"\";\n    const inner = FIELDS.map((f) => {\n      const val = state.fields[f.id] != null ? state.fields[f.id] : (f.default != null ? f.default : \"\");\n      const label = f.label ? `<label class=\"cp-field-label\" for=\"cp-f-${esc(f.id)}\">${esc(f.label)}</label>` : \"\";\n      const hint = f.hint ? `<div class=\"cp-field-hint\">${esc(f.hint)}</div>` : \"\";\n      let control;\n      if (f.type === \"dropdown\") {\n        const ph = f.placeholder ? `<option value=\"\" ${!val ? \"selected\" : \"\"} disabled>${esc(f.placeholder)}</option>` : \"\";\n        const opts = (f.options || []).map((o) => {\n          const ov = typeof o === \"string\" ? o : o.value;\n          const ol = typeof o === \"string\" ? o : (o.label || o.value);\n          return `<option value=\"${esc(ov)}\" ${String(val) === String(ov) ? \"selected\" : \"\"}>${esc(ol)}</option>`;\n        }).join(\"\");\n        control = `<select class=\"cp-input cp-field-input\" id=\"cp-f-${esc(f.id)}\" data-field-id=\"${esc(f.id)}\">${ph}${opts}</select>`;\n      } else if (f.type === \"toggle\") {\n        control = `<label class=\"cp-check\"><input type=\"checkbox\" data-field-id=\"${esc(f.id)}\" ${val ? \"checked\" : \"\"}/><span>${esc(f.toggleLabel || f.label || \"\")}</span></label>`;\n        return `<div class=\"cp-field cp-field--toggle\">${control}${hint}</div>`;\n      } else {\n        control = `<input class=\"cp-input cp-field-input\" id=\"cp-f-${esc(f.id)}\" data-field-id=\"${esc(f.id)}\" placeholder=\"${esc(f.placeholder || \"\")}\" value=\"${esc(val)}\" />`;\n      }\n      return `<div class=\"cp-field\">${label}${control}${hint}</div>`;\n    }).join(\"\");\n    return `<div class=\"cp-fields\">${inner}</div>`;\n  }\n\n  function viewUploader() {\n    const ready = state.people.length > 0;\n    // fieldsFirst: render the global (non-photo) fields ABOVE the upload buckets.\n    // Opt-in per product via CUSTOM_PRINTS_CONFIG.fieldsFirst; DEFAULT OFF so every existing\n    // product renders exactly as before (ThisDay's city/date stay put). Added for products whose\n    // caption is driven by fields (name / years / phrase): making the customer upload a photo\n    // before the fields explaining it appear reads backwards. The per-photo name+year inputs in\n    // personChips are a separate thing and stay put \u2014 for multi-person products those belong to\n    // THEIR photo.\n    const fieldsFirst = !!cfg.fieldsFirst;\n    return `\n      <div class=\"cp-card\">\n        <div class=\"cp-step\">${state.previews.length ? \"Add or edit your photos\" : \"1 \u00B7 Add your photos\"}</div>\n        ${fieldsFirst ? viewFields() : \"\"}\n        ${UPLOADS.map(viewBucket).join(\"\")}\n        ${fieldsFirst ? \"\" : viewFields()}\n        ${state.error ? `<div class=\"cp-error\">${esc(state.error)}</div>` : \"\"}\n        <button class=\"cp-btn cp-btn--primary cp-generate\" ${(ready && !state.generating && !(SKIP_PREVIEW && state.captured)) ? \"\" : \"disabled\"}>\n          ${SKIP_PREVIEW\n            ? (state.generating ? \"Saving\u2026\" : state.captured ? \"\u2713 Photos saved\" : \"2 \u00B7 Save my photos\")\n            : (state.generating ? \"Creating\u2026\" : state.previews.length ? \"\u21BB Try new versions\" : \"2 \u00B7 Create artwork\")}\n        </button>\n        <div class=\"cp-privacy\">\uD83D\uDD12 Your photos are private \u2014 used only to create your artwork, never shown publicly.</div>\n      </div>`;\n  }\n\n  function viewResults() {\n    // skip-preview flow has no preview grid \u2014 once saved, the confirmation lives in the gate note.\n    if (SKIP_PREVIEW) return \"\";\n    if (state.generating) {\n      // Options stream in one at a time, so show the finished ones and keep a loading tile for each\n      // that is still generating \u2014 the grid fills up instead of sitting empty for the whole wait.\n      const doneTiles = state.previews.map((p, i) => `\n        <button class=\"cp-opt ${i === state.selectedIndex ? \"cp-opt--sel\" : \"\"}\" data-pick=\"${i}\">\n          <img src=\"${esc(p.previewUrl)}\" alt=\"Design option ${i + 1}\" loading=\"lazy\" />\n          ${i === state.selectedIndex ? `<span class=\"cp-opt-check\">\u2713</span>` : \"\"}\n        </button>`).join(\"\");\n      const pending = Math.max(0, OPTIONS_COUNT - state.previews.length);\n      const tiles = doneTiles + Array.from({ length: pending }, () => `<div class=\"cp-opt cp-opt--loading\"></div>`).join(\"\");\n      return `<div class=\"cp-card cp-results\">\n        <div class=\"cp-results-head\"><span class=\"cp-spinner cp-spinner--sm\"></span><span class=\"cp-loading-msg\">${LOADING_MESSAGES[0]}</span></div>\n        <div class=\"cp-progress\" data-cbar role=\"progressbar\" aria-label=\"Artwork generation progress\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"${Math.round(loadPct)}\">&#8203;</div>\n        <div class=\"cp-progress-meta\"><span class=\"cp-progress-percent\">${Math.round(loadPct)}%</span></div>\n        <div class=\"cp-results-sub\">${state.previews.length ? `${state.previews.length} of ${OPTIONS_COUNT} ready \u2014 the rest are still painting.` : `Creating ${OPTIONS_COUNT} designs. They appear as they finish.`}</div>\n        <div class=\"cp-options\">${tiles}</div></div>`;\n    }\n    if (state.previews.length < 2) return \"\";\n    const tiles = state.previews.map((p, i) => `\n      <button class=\"cp-opt ${i === state.selectedIndex ? \"cp-opt--sel\" : \"\"}\" data-pick=\"${i}\">\n        <img src=\"${esc(p.previewUrl)}\" alt=\"Design option ${i + 1}\" loading=\"lazy\" />\n        ${i === state.selectedIndex ? `<span class=\"cp-opt-check\">\u2713</span>` : \"\"}\n      </button>`).join(\"\");\n    return `<div class=\"cp-card cp-results\"><div class=\"cp-results-title\">Pick your favorite design</div><div class=\"cp-options\">${tiles}</div></div>`;\n  }\n  function viewGateNote() {\n    if (SKIP_PREVIEW) {\n      return state.captured\n        ? `<div class=\"cp-gatemsg cp-gatemsg--ok\">\u2713 Photos saved${state.captureCount ? ` (${state.captureCount})` : \"\"} \u2014 ${esc(CAPTURE_CONFIRM)} Choose your size below and add to cart.</div>`\n        : `<div class=\"cp-gatemsg\">\uD83D\uDC46 Add your photos and tap Save, then choose a size below and add to cart. ${esc(CAPTURE_CONFIRM)}</div>`;\n    }\n    return selectedPreview()\n      ? `<div class=\"cp-gatemsg cp-gatemsg--ok\">\u2713 Design selected \u2014 choose your size below and add to cart.</div>`\n      : `<div class=\"cp-gatemsg\">\uD83D\uDC46 Create your artwork first, then choose a size below and add to cart.</div>`;\n  }\n\n  // \u2500\u2500 events \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n  function wireEvents() {\n    root.querySelectorAll(\".cp-drop\").forEach((drop) => {\n      const bucketId = drop.dataset.bucket;\n      const bucket = UPLOADS.find((b) => b.id === bucketId) || { id: bucketId };\n      const file = drop.querySelector(\".cp-file\");\n      drop.addEventListener(\"click\", () => file.click());\n      drop.addEventListener(\"dragover\", (e) => { e.preventDefault(); drop.classList.add(\"cp-drop--over\"); });\n      drop.addEventListener(\"dragleave\", () => drop.classList.remove(\"cp-drop--over\"));\n      drop.addEventListener(\"drop\", (e) => {\n        e.preventDefault(); drop.classList.remove(\"cp-drop--over\");\n        if (e.dataTransfer.files) addPhotos(e.dataTransfer.files, bucket);\n      });\n      file.addEventListener(\"change\", (e) => addPhotos(e.target.files, bucket));\n    });\n    root.querySelectorAll(\"[data-remove]\").forEach((b) => b.addEventListener(\"click\", () => removePerson(Number(b.dataset.remove))));\n    root.querySelectorAll(\"[data-field]\").forEach((el) => {\n      const i = Number(el.dataset.i), field = el.dataset.field;\n      el.addEventListener(\"input\", () => {\n        state.people[i][field] = el.value;\n        if (SKIP_PREVIEW) { if (state.captured) { invalidateCapture(); render(); } }\n        else if (selectedPreview()) writeChosenToForm();\n      });\n    });\n    // extra concept inputs (dropdown/text/toggle)\n    root.querySelectorAll(\"[data-field-id]\").forEach((el) => {\n      const id = el.dataset.fieldId;\n      const evt = el.type === \"checkbox\" || el.tagName === \"SELECT\" ? \"change\" : \"input\";\n      el.addEventListener(evt, () => {\n        state.fields[id] = el.type === \"checkbox\" ? el.checked : el.value;\n        if (SKIP_PREVIEW) { if (state.captured) { invalidateCapture(); render(); } }\n        else if (selectedPreview()) writeChosenToForm();\n      });\n    });\n    const gen = $(\".cp-generate\", root);\n    if (gen) gen.addEventListener(\"click\", SKIP_PREVIEW ? capture : generate);\n    root.querySelectorAll(\"[data-pick]\").forEach((b) => b.addEventListener(\"click\", () => pickDesign(Number(b.dataset.pick))));\n  }\n\n  // \u2500\u2500 styles (structural only; font + colour inherit the store theme) \u2500\u2500\n  function injectStyles() {\n    if (document.getElementById(\"cp-styles\")) return;\n    const css = `\n    #custom-prints-widget, #custom-prints-widget * { box-sizing: border-box; }\n    #custom-prints-widget { --cp-ink: currentColor; --cp-muted:#8a8580; --cp-line:#e7e2d9; --cp-bg:#fff; --cp-soft:#faf8f4; --cp-accent:#8a7a5c;\n      font-family: inherit; margin: 0 0 18px; }\n    .cp-module { display:flex; flex-direction:column; gap:14px; }\n    .cp-card { background:var(--cp-bg); border:1px solid var(--cp-line); border-radius:14px; padding:16px; }\n    .cp-step { font-weight:600; font-size:15px; margin-bottom:12px; }\n    .cp-bucket { margin-bottom:14px; }\n    .cp-bucket--memory { margin-bottom:4px; }\n    .cp-bucket-label { font-weight:600; font-size:14px; margin-bottom:8px; }\n    .cp-bucket-sub { font-weight:400; color:var(--cp-muted); }\n    .cp-drop { display:flex; flex-direction:column; align-items:center; gap:3px; width:100%; border:2px dashed #cbbfa8; border-radius:12px; padding:18px 16px; text-align:center; cursor:pointer; transition:.15s; background:var(--cp-soft); font-family:inherit; color:inherit; }\n    .cp-drop:hover, .cp-drop--over, .cp-drop:focus-visible { border-color:var(--cp-accent); background:#f1ece2; outline:none; box-shadow:0 0 0 3px #eee7d8; }\n    .cp-drop-icon { display:flex; align-items:center; justify-content:center; width:38px; height:38px; margin-bottom:3px; border-radius:50%; background:#fff; border:1px solid var(--cp-line); font-size:20px; line-height:1; color:var(--cp-accent); }\n    .cp-drop-main { font-weight:700; font-size:15px; }\n    .cp-drop-sub { font-size:12.5px; color:var(--cp-muted); }\n    .cp-drop--memory { border-color:#e0cfa8; background:#faf5e9; }\n    .cp-drop--memory .cp-drop-icon { color:#a98b57; }\n    .cp-people { margin-top:10px; display:flex; flex-direction:column; gap:10px; }\n    .cp-people:empty { margin-top:0; }\n    .cp-person { border:1px solid var(--cp-line); border-radius:10px; padding:10px; }\n    .cp-person-top { display:flex; gap:10px; align-items:flex-start; position:relative; }\n    .cp-person-thumb { width:88px; height:88px; border-radius:10px; object-fit:cover; flex:none; }\n    .cp-person-remove { position:absolute; top:-4px; right:-4px; border:none; background:#00000088; color:#fff; width:20px; height:20px; border-radius:50%; cursor:pointer; font-size:11px; }\n    .cp-person-fields { flex:1; display:flex; flex-direction:column; gap:6px; }\n    .cp-input { width:100%; border:1px solid var(--cp-line); border-radius:8px; padding:8px 10px; font-size:14px; font-family:inherit; }\n    .cp-input:focus { outline:none; border-color:var(--cp-accent); }\n    .cp-years { display:flex; align-items:center; gap:8px; }\n    .cp-input--year { flex:1; }\n    .cp-dash { color:var(--cp-muted); }\n    .cp-fields { display:flex; flex-direction:column; gap:12px; margin:14px 0 4px; }\n    .cp-field { display:flex; flex-direction:column; gap:5px; }\n    .cp-field-label { font-weight:600; font-size:14px; }\n    .cp-field-hint { font-size:12px; color:var(--cp-muted); }\n    .cp-field-input { font-family:inherit; }\n    select.cp-field-input { appearance:auto; background:#fff; }\n    .cp-check { display:flex; align-items:center; gap:8px; font-size:14px; cursor:pointer; }\n    .cp-btn { width:100%; border:none; border-radius:10px; padding:14px; font-size:15px; font-weight:600; cursor:pointer; transition:.15s; font-family:inherit; }\n    .cp-btn:disabled { opacity:.45; cursor:not-allowed; }\n    .cp-btn--primary { background:var(--cp-accent); color:#fff; margin-top:6px; }\n    .cp-btn--primary:not(:disabled):hover { filter:brightness(1.06); }\n    .cp-privacy { font-size:12px; color:var(--cp-muted); text-align:center; margin-top:10px; line-height:1.5; }\n    .cp-error { background:#fff0f0; color:#c0392b; border:1px solid #f3c6c6; border-radius:8px; padding:10px; font-size:13px; margin-top:10px; }\n    .cp-results { background:var(--cp-soft); border-color:var(--cp-line); }\n    .cp-results-title { font-weight:600; margin-bottom:12px; text-align:center; }\n    .cp-results-head { display:flex; align-items:center; gap:10px; justify-content:center; font-weight:600; margin-bottom:12px; }\n    .cp-progress-meta { display:flex; justify-content:center; font-size:13px; font-variant-numeric:tabular-nums; margin-top:7px; }\n    .cp-progress-percent { font-weight:700; color:var(--cp-ink); }\n    .cp-results-sub { font-size:12px; color:var(--cp-muted); text-align:center; margin:8px 0 12px; }\n    .cp-options { display:grid; grid-template-columns:1fr 1fr; gap:10px; }\n    .cp-opt { position:relative; padding:0; border:2px solid transparent; border-radius:10px; overflow:hidden; cursor:pointer; background:#eee; aspect-ratio:1/1; }\n    .cp-opt img { width:100%; height:100%; object-fit:cover; display:block; }\n    .cp-opt--sel { border-color:var(--cp-accent); box-shadow:0 0 0 2px #eee7d8; }\n    .cp-opt-check { position:absolute; top:6px; right:6px; width:22px; height:22px; border-radius:50%; background:var(--cp-accent); color:#fff; font-size:13px; display:flex; align-items:center; justify-content:center; }\n    .cp-opt--loading { background:linear-gradient(90deg,#efeae0,#f7f3ea,#efeae0); background-size:200% 100%; animation:cp-shimmer 1.3s linear infinite; cursor:default; }\n    @keyframes cp-shimmer { to { background-position:-200% 0; } }\n    .cp-gatemsg { font-size:13px; color:var(--cp-muted); text-align:center; padding:2px; }\n    .cp-gatemsg--ok { color:#16a34a; font-weight:600; }\n    .cp-spinner { width:42px; height:42px; border:4px solid #eee; border-top-color:var(--cp-accent); border-radius:50%; animation:cp-spin 1s linear infinite; }\n    .cp-spinner--sm { width:20px; height:20px; border-width:3px; }\n    @keyframes cp-spin { to { transform:rotate(360deg); } }\n    .cp-loading-msg { font-size:15px; }\n    /* fill painted as a background gradient on this element (color=fill, bg=track) */\n    .cp-progress { height:10px; border-radius:20px; background-color:#ded6c8; background-repeat:no-repeat; color:#6f5d40; font-size:0; line-height:0; }\n    .product-form__submit.cp-gated { opacity:.5; cursor:not-allowed; }\n    `;\n    const style = document.createElement(\"style\");\n    style.id = \"cp-styles\"; style.textContent = css;\n    document.head.appendChild(style);\n  }\n\n  if (document.readyState === \"loading\") document.addEventListener(\"DOMContentLoaded\", init);\n  else init();\n})();\n"],
  "mappings": "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",
  "names": ["root", "summary", "tiles"]
}
