{
  "version": 3,
  "sources": ["/cdn/shop/t/45/assets/wnf-chat-fullpage-20260625.js?wnf_chat=fullpage_20260625"],
  "sourcesContent": ["/* WNF live-chat widget \u2014 vanilla, dependency-free, lazy-initialized.\n * Compact dark proactive card (Chat now / Browse FAQs) + gold bubble launcher\n * + a Chat/FAQ panel (questions use current server-side facts). Explicit automated\n * framing; online/away by real Portland store hours. CWV-safe (loads on first\n * engagement via wnf-chat-loader.liquid).\n *\n * Loader injects window.WNF_CHAT_CFG:\n *   { api, soloHost, hours, assets:{store,blzMark}, page:{key,productTitle,...},\n *     staff:{ joey:{name,role,img}, ... } }\n * Brand: cream #FFFAED \u00B7 gold #f2c070 \u00B7 charcoal #1c1d1d \u00B7 teal #404f52.\n *\n * 2026-10-03: phone experiment \"msheet1\" (MX block below, OFF by default). The\n * sheet arm replaces the dark card with a compact question sheet shown after real\n * engagement; chips send the tapped question; photo action; contact ask after the\n * answer. WNFChatOpen({ intent: \"photo\" }) is supported on every arm.\n */\n(function () {\n  if (window.__wnfChatLoaded) return;\n  window.__wnfChatLoaded = true;\n\n  var CFG = window.WNF_CHAT_CFG || {};\n  var API = CFG.api || \"\";\n  var PAGE = CFG.page || { key: \"default\" };\n  var STAFF = CFG.staff || {};\n  var ASSETS = CFG.assets || {};\n\n  function ls(k, v) { try { if (v === undefined) return localStorage.getItem(k); localStorage.setItem(k, v); } catch (e) { return null; } }\n  function ss(k, v) { try { if (v === undefined) return sessionStorage.getItem(k); sessionStorage.setItem(k, v); } catch (e) { return null; } }\n  var sessionId = ls(\"wnf_chat_session\") ||\n    (function () { var id = \"w_\" + Math.random().toString(36).slice(2) + Date.now().toString(36); ls(\"wnf_chat_session\", id); return id; })();\n\n  // ---- full-page mobile mode -------------------------------------------------\n  // On phones the launcher/mini/card navigate to a dedicated SAME-ORIGIN page\n  // (CFG.chatPage, e.g. /pages/chat) that hosts this exact chat UI as a NORMAL\n  // document \u2014 no position:fixed overlay, no background scroll-lock. That lets iOS\n  // Safari move the composer above the soft keyboard natively (the whole bug class\n  // that plagued the in-storefront sheet \u2014 see memory/wnf/chat-mobile-keyboard-fix).\n  // Desktop is unchanged (corner panel). Page mode is active only when the chat-page\n  // template set window.WNF_CHAT_PAGE AND rendered the #wnf-chat-page host.\n  var PAGE_HOST = (typeof document !== \"undefined\") ? document.getElementById(\"wnf-chat-page\") : null;\n  var PAGE_MODE = !!(window.WNF_CHAT_PAGE && PAGE_HOST);\n  // Temporary on-device keyboard instrumentation: ?wnfkbd=1 shows a live readout of\n  // the visualViewport metrics so we can diagnose the iOS keyboard on a real iPhone\n  // (no headless engine can reproduce the soft keyboard). Invisible without the flag.\n  var DEBUG_KBD = false; try { DEBUG_KBD = /[?&]wnfkbd=1/.test(location.search || \"\"); } catch (e) {}\n  var LAUNCH_VIEW = \"chat\", LAUNCH_RETURN = \"\", LAUNCH_TITLE = \"\", LAUNCH_ASK = \"\", LAUNCH_INTENT = \"\", LAUNCH_SRC = \"\", LAUNCH_STASHED = false;\n  if (PAGE_MODE) {\n    // Adopt the originating storefront page's context (key, product/collection,\n    // cart, journey) that the launcher stashed before navigating, so Joey's greeting,\n    // FAQs, and the staff/AI page-context all match where the shopper came from.\n    try {\n      var _lc = JSON.parse(ss(\"wnf_chat_launch\") || \"null\");\n      if (_lc) {\n        LAUNCH_STASHED = true;\n        if (_lc.page) CFG.page = _lc.page;\n        LAUNCH_VIEW = _lc.view === \"faq\" ? \"faq\" : \"chat\";\n        LAUNCH_RETURN = _lc.returnUrl || \"\";\n        LAUNCH_TITLE = typeof _lc.returnTitle === \"string\" ? _lc.returnTitle : \"\";\n        LAUNCH_INTENT = _lc.intent === \"photo\" ? \"photo\" : \"\";\n        LAUNCH_SRC = typeof _lc.src === \"string\" ? _lc.src.slice(0, 20) : \"\";\n        // A question tapped on the storefront is sent ONCE: drop it from the stash\n        // before sending so a reload, back/forward, or bfcache restore never re-sends.\n        if (typeof _lc.ask === \"string\" && _lc.ask) {\n          LAUNCH_ASK = _lc.ask.slice(0, 300);\n          delete _lc.ask;\n          ss(\"wnf_chat_launch\", JSON.stringify(_lc));\n        }\n      }\n    } catch (e) {}\n    try { if (/[?&]intent=photo(?:&|#|$)/.test(location.search || \"\")) LAUNCH_INTENT = \"photo\"; } catch (e) {}\n    PAGE = CFG.page || PAGE;\n  }\n\n  var ab = ls(\"wnf_ab_host\");\n  if (ab !== \"A\" && ab !== \"B\") { ab = Math.random() < 0.5 ? \"A\" : \"B\"; ls(\"wnf_ab_host\", ab); }\n\n  // ---- mobile invitation experiment (2026-10-03; see DESIGN.md / RELEASE-PLAN.md) ----\n  // Phones only. \"control\" = today's dark card on its timer; \"sheet\" = the compact\n  // question sheet after real engagement, photo action, and the contact ask after an\n  // answer. MX.on=false (default) assigns nobody: every visitor gets control and no\n  // experiment params are sent. Preview/QA override, kept for the browser session:\n  // ?wnf_mx=sheet | ?wnf_mx=control | ?wnf_mx=off (QA traffic carries wnf_mx_qa=1).\n  // MX.emailCopy stays false until the backend \"email me a copy\" change is deployed.\n  var MX = { on: false, id: \"msheet1\", emailCopy: false };\n  var mxArmCache, mxQA = false, mxNewAssign = false;\n  function mxArm() {\n    if (mxArmCache !== undefined) return mxArmCache;\n    var arm = null;\n    try {\n      var m = /[?&]wnf_mx=(sheet|control|off)(?:&|#|$)/.exec(location.search || \"\");\n      if (m) ss(\"wnf_mx_force\", m[1] === \"off\" ? \"\" : m[1]);\n      var forced = ss(\"wnf_mx_force\");\n      if (forced === \"sheet\" || forced === \"control\") { arm = forced; mxQA = true; }\n      else if (MX.on && isMobileView()) {\n        var key = \"wnf_mx_\" + MX.id;\n        arm = ls(key);\n        if (arm !== \"sheet\" && arm !== \"control\") {\n          ls(key, Math.random() < 0.5 ? \"sheet\" : \"control\");\n          arm = ls(key); // only users whose assignment persists take part\n          if (arm === \"sheet\" || arm === \"control\") mxNewAssign = true; else arm = null;\n        }\n      }\n    } catch (e) { arm = null; }\n    if (arm && !isMobileView()) arm = null; // desktop is never in the experiment\n    mxArmCache = arm;\n    return arm;\n  }\n  function track(event, params) {\n    try {\n      var p = Object.assign({ wnf_ab_host: ab, wnf_page: PAGE.key, wnf_variant: copyKey() }, params || {});\n      var arm = mxArm();\n      if (arm) { p.wnf_mx = MX.id; p.wnf_mx_arm = arm; if (mxQA) p.wnf_mx_qa = 1; }\n      (window.dataLayer = window.dataLayer || []).push(Object.assign({ event: event }, p));\n      sendGtag(event, p, 0);\n    } catch (e) {}\n  }\n  // wnf-chat-open-canonical-2026-10-10: the full-page chat (/pages/chat) boots before the Google tag defines\n  // gtag, so page-mode events were dropped (mobile wnf_chat_open ~1 a week). Retry for up to 10s instead.\n  function sendGtag(event, p, n) {\n    if (typeof window.gtag === \"function\") { try { window.gtag(\"event\", event, p); } catch (e) {} return; }\n    if (n < 40) setTimeout(function () { sendGtag(event, p, n + 1); }, 250);\n  }\n\n  // Joey is the real owner and chat contact; automated replies have a separate author label.\n  var joey = (CFG.staff && CFG.staff.joey) || {};\n  var host = { name: \"Joey\", role: \"Local Owner\", img: joey.img || \"\" };\n  var ASSISTANT_NAME = \"Automated reply\";\n  function firstName() { return \"Joey\"; }\n\n  // ---- online/away by real Portland store hours ------------------------------\n  var HOURS = CFG.hours || { 0: [11, 17], 1: [10, 18], 2: [10, 18], 3: [10, 18], 4: [10, 18], 5: [10, 18], 6: [10, 18] };\n  // Closed all day on Thanksgiving (4th Thursday of November) and Christmas Day\n  // (Joey, 2026-09-26; ws_facts). Dates are Portland calendar dates.\n  function isHoliday(y, m, d) {\n    if (m === 12 && d === 25) return true;\n    if (m === 11) { var first = new Date(Date.UTC(y, 10, 1)).getUTCDay(); return d === 1 + ((4 - first + 7) % 7) + 21; }\n    return false;\n  }\n  // Portland wall clock: { y, m, d, wd, hour }.\n  function pdxNow() {\n    var parts = new Intl.DateTimeFormat(\"en-US\", { timeZone: \"America/Los_Angeles\", year: \"numeric\", month: \"numeric\", day: \"numeric\", weekday: \"short\", hour: \"numeric\", hour12: false }).formatToParts(new Date());\n    function get(t) { return parts.find(function (p) { return p.type === t; }).value; }\n    var hour = +get(\"hour\"); if (hour === 24) hour = 0;\n    return { y: +get(\"year\"), m: +get(\"month\"), d: +get(\"day\"), wd: { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 }[get(\"weekday\")], hour: hour };\n  }\n  // Hours for the Portland date `offset` days from today, or null when closed.\n  function hoursOn(now, offset) {\n    var t = new Date(Date.UTC(now.y, now.m - 1, now.d + offset));\n    if (isHoliday(t.getUTCFullYear(), t.getUTCMonth() + 1, t.getUTCDate())) return null;\n    return HOURS[t.getUTCDay()] || null;\n  }\n  function isOpenNow() {\n    try {\n      var now = pdxNow(), h = hoursOn(now, 0);\n      return !!h && now.hour >= h[0] && now.hour < h[1];\n    } catch (e) { return true; }\n  }\n  var OPEN = isOpenNow();\n\n  // ---- per-page copy ----------------------------------------------------------\n  // Every page type gets its own card headline, full welcome, input placeholder,\n  // FAQ set, and proactive-card timing \u2014 all keyed off PAGE.key (from the loader)\n  // plus a collection-category refinement (colCat) for collection pages. To add or\n  // tune a page, edit COPY / TIMING below. Card & welcome may be strings OR\n  // functions (used when they need the live product/collection/cart values).\n\n  // Quick questions use the normal server-side answer and verification path.\n  function Q(q) { return { q: q }; }\n  // Default pages (home, contact, policies) are where customers with an order land, so\n  // order status sits beside the shopping questions (2026-09-23 chat review).\n  var DEFAULT_FAQS = [Q(\"Where's my order?\"), Q(\"Hours & phone\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\")];\n\n  // Collection page \u2192 category, so each collection type pulls its own lever.\n  function colCat() {\n    var h = ((PAGE.collectionHandle || \"\") + \" \" + (PAGE.collectionTitle || \"\")).toLowerCase();\n    if (/locally|local-made|locally-made|oregon|made-in|hand.?crafted|pacific.?north/.test(h)) return \"local\";\n    if (/mattress/.test(h)) return \"mattress\";\n    if (/sleeper/.test(h)) return \"sleeper\";\n    if (/custom-sofa|custom sofa/.test(h)) return \"custom\";\n    if (/sectional/.test(h)) return \"sectional\";\n    if (/sofa|couch|loveseat/.test(h)) return \"sofas\";\n    if (/dining/.test(h)) return \"dining\"; // before chair/recliner: \"dining chairs\" must resolve to dining, not chairs\n    if (/recliner/.test(h)) return \"recliners\";\n    if (/chair/.test(h)) return \"chairs\";\n    if (/bed|dresser|nightstand|bedroom/.test(h)) return \"bedroom\";\n    if (/storage|cabinet|console|media|bookcase|sideboard|wardrobe/.test(h)) return \"storage\";\n    return \"\";\n  }\n\n  var COPY = {\n    home: {\n      card: \"Let\u2019s find your next favorite piece.\",\n      welcome: \"What are you looking for? I can help compare pieces, check listed details, or plan a showroom visit.\",\n      ph: \"What are you furnishing?\",\n      faqs: [Q(\"Do you deliver?\"), Q(\"Can I see it in person?\"), Q(\"What's your return policy?\"), Q(\"Do you offer financing?\")]\n    },\n    pdp: {\n      card: function () { return PAGE.productTitle ? \"Questions about \" + PAGE.productTitle + \"?\" : \"Let\u2019s take a closer look at this piece.\"; },\n      welcome: \"Want to check the dimensions, compare options, or understand delivery for this piece?\",\n      ph: \"Is it in stock? Delivery time?\",\n      faqs: [Q(\"Is it in stock?\"), Q(\"How soon can I get it?\"), Q(\"Can I see it in person?\"), Q(\"What if it's not right?\")]\n    },\n    murphy: {\n      card: \"Make room for overnight guests.\",\n      welcome: \"What space are you working with? I can help compare the listed dimensions and bed options.\",\n      ph: \"Will it fit my room?\",\n      faqs: [Q(\"Will it fit my room?\"), Q(\"Can I see one open?\"), Q(\"Delivery & install?\"), Q(\"Do you offer financing?\")]\n    },\n    fjords: {\n      card: \"Compare Fjords sizes and options.\",\n      welcome: \"I can help compare Fjords sizes, upholstery options, and listed features. What matters most to you?\",\n      ph: \"Ask about leather options\u2026\",\n      faqs: [Q(\"What leather options are there?\"), Q(\"Can I sit in it first?\"), Q(\"How long is the lead time?\"), Q(\"Delivery & financing?\")]\n    },\n    consigned: {\n      card: \"Questions about this piece?\",\n      welcome: \"Have a question about this piece? I can help with the listing and explain how availability is confirmed.\",\n      ph: \"Is this one still available?\",\n      faqs: [Q(\"Is this still available?\"), Q(\"Can you hold it for me?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\")]\n    },\n    // ---- brand / line PDPs (detected by vendor in the loader) ----\n    stanton: {\n      card: \"Compare Stanton sizes and fabrics.\",\n      welcome: \"I can help compare Stanton sizes and fabric options. What are you looking for?\",\n      ph: \"Pick my fabric? Lead time?\",\n      faqs: [Q(\"Where is it made?\"), Q(\"Can I pick the fabric?\"), Q(\"Can I sit on it first?\"), Q(\"How long does it take?\")]\n    },\n    stylus: {\n      card: \"Compare Stylus sizes and fabrics.\",\n      welcome: \"I can help compare Stylus sizes and fabric options. What are you looking for?\",\n      ph: \"Pick my fabric? When can I get it?\",\n      faqs: [Q(\"Where is it made?\"), Q(\"Can I pick the fabric?\"), Q(\"How long does it take?\"), Q(\"Can I see it in person?\")]\n    },\n    nectar: {\n      // \u26A0\uFE0F 365-night trial / Forever Warranty held pending Hayden's confirm (he didn't\n      // check \"sleep trial\"). Conservative copy below; promise bar on the live PDP claims them.\n      card: \"Find a mattress for your space.\",\n      welcome: \"I can help compare listed mattress sizes and features. What would you like to know?\",\n      ph: \"Which firmness is right for me?\",\n      faqs: [Q(\"Can I try it in person?\"), Q(\"Which firmness should I pick?\"), Q(\"What's your return policy?\"), Q(\"Delivery & setup?\")]\n    },\n    \"private-label\": {\n      card: \"Want a closer look at this piece?\",\n      welcome: \"Want to compare the listed dimensions, options, or delivery for this piece?\",\n      ph: \"Tell me about this piece\u2026\",\n      faqs: [Q(\"What makes it exclusive?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\"), Q(\"Do you offer financing?\")]\n    },\n    // ---- collection pages (generic + per-category) ----\n    col: {\n      card: \"Let\u2019s find the right piece for your room.\",\n      welcome: \"What kind of piece are you looking for, and what matters most to you?\",\n      ph: \"Help me find the right piece\u2026\",\n      faqs: [Q(\"Do you deliver?\"), Q(\"Can I see it in person?\"), Q(\"What's your return policy?\"), Q(\"Do you offer financing?\")]\n    },\n    \"col-sofas\": {\n      card: \"Let\u2019s find a sofa for your room.\",\n      welcome: \"What size sofa are you looking for? Share your space or budget and I can help narrow the options.\",\n      ph: \"Help me pick the right sofa\u2026\",\n      faqs: [Q(\"Can I customize the fabric?\"), Q(\"Can I sit on it first?\"), Q(\"How soon can I get it?\"), Q(\"Do you offer financing?\")]\n    },\n    \"col-sectional\": {\n      card: \"A sectional that fits your room.\",\n      welcome: \"What are the dimensions of your space? I can help compare sectional layouts and listed sizes.\",\n      ph: \"Will it fit my space?\",\n      faqs: [Q(\"Will it fit my space?\"), Q(\"Can I customize the layout?\"), Q(\"Can I see it in person?\"), Q(\"Delivery & financing?\")]\n    },\n    \"col-chairs\": {\n      card: \"Find your new favorite seat.\",\n      welcome: \"What kind of chair would work in your space? I can help compare options.\",\n      ph: \"Help me find a chair\u2026\",\n      faqs: [Q(\"Can I sit on it first?\"), Q(\"Do you deliver?\"), Q(\"What if it's not right?\"), Q(\"Do you offer financing?\")]\n    },\n    \"col-recliners\": {\n      card: \"Let\u2019s find your kind of comfort.\",\n      welcome: \"What matters most in your recliner: size, upholstery, or how it reclines?\",\n      ph: \"Which recliner fits me best?\",\n      faqs: [Q(\"Which recliner is most comfortable?\"), Q(\"What leather/fabric options?\"), Q(\"Can I try it in person?\"), Q(\"Delivery & financing?\")]\n    },\n    \"col-dining\": {\n      card: \"Make room for everyone at the table.\",\n      welcome: \"How many people would you like to seat? I can help compare tables and chairs for your space.\",\n      ph: \"How many does it seat?\",\n      faqs: [Q(\"How many does it seat?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\"), Q(\"Do you offer financing?\")]\n    },\n    \"col-bedroom\": {\n      card: \"Make your bedroom feel like home.\",\n      welcome: \"Are you looking for a bed, storage, or pieces that work together?\",\n      ph: \"Help me furnish my bedroom\u2026\",\n      faqs: [Q(\"Can I see it in person?\"), Q(\"Do you deliver?\"), Q(\"What's your return policy?\"), Q(\"Do you offer financing?\")]\n    },\n    \"col-mattress\": {\n      card: \"Let\u2019s compare your mattress options.\",\n      welcome: \"I can help compare listed mattress sizes and features. What would you like to know?\",\n      ph: \"Which mattress is right for me?\",\n      faqs: [Q(\"Can I try it in person?\"), Q(\"Which firmness should I pick?\"), Q(\"What's your return policy?\"), Q(\"Delivery & setup?\")]\n    },\n    \"col-sleeper\": {\n      card: \"A sofa for every day. A bed for guests.\",\n      welcome: \"What size guest bed do you need, and how much room do you have for the sofa?\",\n      ph: \"What size bed does it make?\",\n      faqs: [Q(\"What size bed does it make?\"), Q(\"Can I customize the fabric?\"), Q(\"Can I see one open?\"), Q(\"Delivery & financing?\")]\n    },\n    \"col-storage\": {\n      card: \"Find a place for the things you love.\",\n      welcome: \"What needs a home, and how much space do you have? I can help compare storage options.\",\n      ph: \"What size do you need?\",\n      faqs: [Q(\"What size will fit?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\"), Q(\"What's your return policy?\")]\n    },\n    \"col-local\": {\n      card: \"Explore Oregon-made furniture.\",\n      welcome: \"I can help check where a specific piece is made and compare the listed options.\",\n      ph: \"Help me find a locally-made piece\u2026\",\n      faqs: [Q(\"Where are these made?\"), Q(\"Can I pick the fabric?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\")]\n    },\n    \"col-custom\": {\n      card: \"Your fabric. Your fit. Let\u2019s make it yours.\",\n      welcome: \"I can help compare fabric and configuration options. What are you hoping to customize?\",\n      ph: \"Help me design my sofa\u2026\",\n      faqs: [Q(\"Is design help free?\"), Q(\"What fabrics can I choose?\"), Q(\"How does a custom order work?\"), Q(\"How long does it take?\")]\n    },\n    cart: {\n      card: \"Check the details before checkout.\",\n      welcome: \"Is there a detail you want to check before checkout? I can help with your pieces or the current store policies.\",\n      ph: \"Any questions before checkout?\",\n      faqs: [Q(\"How soon will it arrive?\"), Q(\"When is delivery free?\"), Q(\"What if it's not right?\"), Q(\"Do you offer financing?\")]\n    },\n    // ---- content pages ----\n    design: {\n      // Explain design help without impersonating a designer or booking a visit.\n      card: \"Need help planning your room?\",\n      welcome: \"Tell me about your room and what you want to keep. I can help compare pieces and explain how to get design help.\",\n      ph: \"Tell me about your room\u2026\",\n      faqs: [Q(\"Is design help free?\"), Q(\"How does a consult work?\"), Q(\"Can you match my style?\"), Q(\"Can I customize a sofa?\")]\n    },\n    showroom: {\n      card: \"Plan your showroom visit.\",\n      welcome: \"Planning a visit to Grand Avenue or Cedar Mill? I can help check hours, directions, and how to confirm a display.\",\n      ph: \"When are you open? Parking?\",\n      faqs: [Q(\"Hours & address\"), Q(\"Where do I park?\"), Q(\"Do I need an appointment?\"), Q(\"Can I take it home the same day?\")]\n    },\n    \"consign-lp\": {\n      card: \"Thinking about consignment?\",\n      welcome: \"Thinking about consignment? I can explain the current intake process and terms.\",\n      ph: \"What would you like to consign?\",\n      faqs: [Q(\"How does consignment work?\"), Q(\"What do you accept?\"), Q(\"How much will I get?\"), Q(\"Do you pick up?\")]\n    },\n    about: {\n      card: \"Meet the people behind What\u2019s New.\",\n      welcome: \"What would you like to know about the store or how we work?\",\n      ph: \"Ask us anything\u2026\",\n      faqs: [Q(\"Where are you located?\"), Q(\"Can I see it in person?\"), Q(\"Do you deliver?\"), Q(\"Do you offer financing?\")]\n    },\n    \"default\": {\n      card: \"A little local help for your home.\",\n      welcome: \"What are you looking for? I can help compare pieces, check listed details, or plan a showroom visit.\",\n      ph: \"What are you furnishing?\",\n      faqs: [Q(\"Do you deliver?\"), Q(\"Can I see it in person?\"), Q(\"What's your return policy?\"), Q(\"Do you offer financing?\")]\n    }\n  };\n\n  // Proactive-card timing per page: higher-intent pages fire sooner / shallower\n  // scroll; cart adds desktop exit-intent to catch checkout abandoners.\n  var TIMING = {\n    pdp: { d: 6000, s: 0.35 }, murphy: { d: 6000, s: 0.35 }, fjords: { d: 6000, s: 0.35 }, consigned: { d: 6000, s: 0.30 },\n    stanton: { d: 6000, s: 0.35 }, stylus: { d: 6000, s: 0.35 }, nectar: { d: 6000, s: 0.35 }, \"private-label\": { d: 6000, s: 0.35 }, \"col-local\": { d: 7000, s: 0.45 },\n    \"col-mattress\": { d: 7000, s: 0.40 }, \"col-custom\": { d: 6000, s: 0.40 },\n    cart: { d: 5000, s: 0.40, exit: true },\n    design: { d: 6000, s: 0.40 }, \"consign-lp\": { d: 6000, s: 0.40 }, showroom: { d: 8000, s: 0.50 },\n    col: { d: 8000, s: 0.50 }, about: { d: 9000, s: 0.55 }, home: { d: 10000, s: 0.60 }, \"default\": { d: 9000, s: 0.55 }\n  };\n\n  // Resolve the most-specific copy key (collection category > col > page key > default).\n  function copyKey() {\n    if (PAGE.key === \"col\") { var c = colCat(); if (c && COPY[\"col-\" + c]) return \"col-\" + c; return \"col\"; }\n    return COPY[PAGE.key] ? PAGE.key : \"default\";\n  }\n  function copyFor() { return COPY[copyKey()] || COPY[\"default\"]; }\n  function val(x) { return typeof x === \"function\" ? x() : x; }\n  function timingFor() { return TIMING[copyKey()] || TIMING[PAGE.key] || TIMING[\"default\"]; }\n\n  // What page/product the visitor is on, for the staff console + alerts + the AI\n  // draft. Lets a message like \"Can I see this at the store?\" be answered \u2014 staff\n  // and the AI see what \"this\" is, whether it's in stock, what's in the cart, and\n  // the path that got them here. Title prefers the product/collection name (from\n  // the loader), then the document title; URL is the full clickable href.\n  function selectedVariantId() {\n    try {\n      var url = new URL(PAGE_MODE ? LAUNCH_RETURN : location.href, location.origin);\n      var variant = url.searchParams.get(\"variant\");\n      // An invalid explicit selection must not silently select a sibling/default.\n      return variant === null ? null : (/^\\d+$/.test(variant) ? variant : \"unresolved\");\n    } catch (e) { return null; }\n  }\n  // Per-session browsing journey (page titles seen this session, most-recent last)\n  // is recorded by the loader on every page load \u2014 the widget only reads it here.\n  function journey() {\n    try { return JSON.parse(ss(\"wnf_journey\") || \"[]\"); } catch (e) { return []; }\n  }\n  function pageContext() {\n    var title = (PAGE.productTitle || PAGE.collectionTitle || (PAGE_MODE ? LAUNCH_TITLE : document.title) || \"\").toString().slice(0, 200);\n    var url = \"\";\n    try { url = (window.location && window.location.href || \"\").toString().slice(0, 500); } catch (e) {}\n    // In full-page mobile chat the document IS /pages/chat, not where the shopper\n    // actually is. Report the originating storefront page they launched from so the\n    // persisted page_url (and the console's \"Viewing\" link + team alerts) point at\n    // the product they were viewing, not the chat page.\n    if (PAGE_MODE) {\n      try {\n        var ret = LAUNCH_RETURN ? new URL(LAUNCH_RETURN, location.origin) : null;\n        url = ret && ret.origin === location.origin && !/^\\/pages\\/chat\\/?$/.test(ret.pathname) ? ret.href.slice(0, 500) : \"\";\n        if (!url) title = \"\";\n      } catch (e) { url = \"\"; title = \"\"; }\n    }\n    var meta = {\n      key: PAGE.key || null,\n      productHandle: PAGE.productHandle || null,\n      productAvailable: typeof PAGE.productAvailable === \"boolean\" ? PAGE.productAvailable : null,\n      productVendor: PAGE.productVendor || null,\n      productType: PAGE.productType || null,\n      productPrice: typeof PAGE.productPrice === \"number\" ? PAGE.productPrice : null,\n      variantId: selectedVariantId(),\n      collectionTitle: PAGE.collectionTitle || null,\n      cartCount: typeof PAGE.cartCount === \"number\" ? PAGE.cartCount : null,\n      cartTotal: typeof PAGE.cartTotal === \"number\" ? PAGE.cartTotal : null,\n      cartRemaining: typeof PAGE.cartRemaining === \"number\" ? PAGE.cartRemaining : null,\n      cart: Array.isArray(PAGE.cart) ? PAGE.cart.slice(0, 20) : [],\n      journey: journey().slice(-12)\n    };\n    return { url: url, title: title, meta: meta };\n  }\n\n  // Short per-page line for the always-visible mini bubble next to the launcher.\n  // Resolved by the same copyKey() (collection-category > col > page key > default).\n  // Keep these SHORT (one glanceable line) \u2014 the fuller pitch lives in the dark card.\n  // Conversion-optimized (Hormozi value-equation: lead with a high-value, low-effort,\n  // fast OFFER \u2014 never a doubt-question like \"will it fit?\" that raises anxiety and\n  // makes the shopper do the work). First-person from a named local owner (authority +\n  // liking), leaning on WNF's REAL levers: free design help, 350+ fabrics, sit on it at\n  // 439 SE Grand, hold the one-of-one. Keep each \u2264 ~2 lines.\n  var BUBBLE = {\n    home: \"Furnishing a room? I'll help \uD83D\uDC4B\",\n    pdp: \"I'll check stock & delivery\",\n    murphy: \"Which Murphy bed fits? Ask me\",\n    fjords: \"I'll help pick your leather\",\n    consigned: \"Questions about this piece?\",\n    stanton: \"Compare fabrics and sizes\",\n    stylus: \"Made to order \u2014 I'll help\",\n    nectar: \"I'll help pick your firmness\",\n    \"private-label\": \"Want the details?\",\n    col: \"I'll help you find it \uD83D\uDC4B\",\n    \"col-sofas\": \"I'll help you find a sofa\",\n    \"col-sectional\": \"I'll find a sectional that fits\",\n    \"col-chairs\": \"I'll help you find a chair\",\n    \"col-recliners\": \"Find your recliner \u2014 ask me\",\n    \"col-dining\": \"I'll help with your dining room\",\n    \"col-bedroom\": \"I'll help with your bedroom\",\n    \"col-mattress\": \"I'll help pick your mattress\",\n    \"col-sleeper\": \"I'll find a sleeper that fits\",\n    \"col-storage\": \"I'll find storage that fits\",\n    \"col-local\": \"See what's Oregon-made \u2014 ask\",\n    \"col-custom\": \"Compare custom sofa options\",\n    cart: \"Questions before checkout? \uD83D\uDC4B\",\n    design: \"Need help planning your room?\",\n    showroom: \"Planning a visit? I'll help\",\n    \"consign-lp\": \"Want to consign? Ask me\",\n    about: \"Questions about us? \uD83D\uDC4B\",\n    \"default\": \"Here to help \u2014 ask me \uD83D\uDC4B\"\n  };\n  function bubbleLine() { return val(BUBBLE[copyKey()] || BUBBLE[PAGE.key] || BUBBLE[\"default\"]); }\n\n  function cardQuestion() { return val(copyFor().card); }\n  function cardSub() { return \"Message me here for a hand with your furniture.\"; }\n  // Fuller welcome shown when the conversation opens.\n  function welcomeMsg() {\n    return \"Hi! I'm WNF\u2019s automated shopping assistant. Joey and the team can join the conversation here. \" + val(copyFor().welcome);\n  }\n\n  // ---- server-answered quick questions (per-page set, known facts only) ------------------\n  var FAQS = copyFor().faqs || DEFAULT_FAQS;\n\n  // ---- helpers ----------------------------------------------------------------\n  function el(tag, attrs, html) { var e = document.createElement(tag); if (attrs) for (var k in attrs) e.setAttribute(k, attrs[k]); if (html != null) e.innerHTML = html; return e; }\n  function esc(s) { return String(s == null ? \"\" : s).replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\"); }\n  // Render a message body safely. esc() first (XSS guard), THEN light formatting so a\n  // stray markdown token from the AI renders properly instead of showing raw chars:\n  // **bold**, [label](url) + bare URLs -> links, \"- \" bullets -> \u2022, newlines -> <br>.\n  function fmt(s) {\n    var t = esc(s);\n    t = t.replace(/\\[([^\\]]+)\\]\\((https?:\\/\\/[^\\s)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener\">$1</a>');\n    t = t.replace(/(^|\\s)(https?:\\/\\/[^\\s<]+)/g, '$1<a href=\"$2\" target=\"_blank\" rel=\"noopener\">$2</a>');\n    t = t.replace(/\\*\\*([^*]+)\\*\\*/g, \"<strong>$1</strong>\").replace(/__([^_]+)__/g, \"<strong>$1</strong>\");\n    return t.replace(/(^|\\n)\\s*[-*]\\s+/g, \"$1\u2022 \"); // newlines handled by .wnf-m white-space:pre-wrap\n  }\n  var CHAT_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke-width=\"2\"><path d=\"M21 11.5a8.5 8.5 0 0 1-12.5 7.5L3 21l2-5.5A8.5 8.5 0 1 1 21 11.5z\"/></svg>';\n  var SEND_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M22 2 11 13\"/><path d=\"M22 2 15 22l-4-9-9-4 20-7z\"/></svg>';\n  var PHONE_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1.9.4 1.8.7 2.7a2 2 0 0 1-.5 2.1L8.1 9.8a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.7.7a2 2 0 0 1 1.8 2z\"/></svg>';\n  var CLOSE_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6 6 18\"/></svg>';\n  var THUMB_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3z\"/><path d=\"M7 10l4-8a3 3 0 0 1 3 3v4h5.5a2 2 0 0 1 2 2.3l-1.4 8A2 2 0 0 1 18.1 21H7\"/></svg>';\n  // Camera/photo glyph for the attach button.\n  var CLIP_SVG = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"6\" width=\"18\" height=\"14\" rx=\"2.5\"/><circle cx=\"12\" cy=\"13\" r=\"3.2\"/><path d=\"M8 6l1.4-2.2h5.2L16 6\"/></svg>';\n  function avatar(big) { return '<span class=\"wnf-av' + (big ? \" big\" : \"\") + '\">' + (host.img ? '<img src=\"' + esc(host.img) + '\" alt=\"Joey, WNF local owner\" width=\"46\" height=\"46\" style=\"width:100%;height:100%;object-fit:cover;border-radius:50%\">' : '<span aria-hidden=\"true\" style=\"display:grid;place-items:center;width:100%;height:100%;font-size:18px;font-weight:700;background:#f2c070\">J</span>') + '</span>'; }\n\n  // ---- styles -----------------------------------------------------------------\n  var CSS =\n    \".wnf{position:fixed;right:calc(18px + env(safe-area-inset-right));bottom:calc(18px + env(safe-area-inset-bottom) + var(--wnf-lift, 0px));z-index:2147483000;transition:bottom .18s ease;font:14px/1.5 Futura,'Futura PT','Jost','Trebuchet MS',Arial,sans-serif;-webkit-text-size-adjust:100%;text-size-adjust:100%;-webkit-tap-highlight-color:transparent}\" +\n    \".wnf *{box-sizing:border-box}\" +\n    \".wnf button,.wnf input,.wnf a{touch-action:manipulation}\" +  // kill 300ms tap delay + double-tap zoom\n    \".wnf button{-webkit-user-select:none;user-select:none}\" +\n    \".wnf input,.wnf textarea{font-size:16px}\" +                  // belt-and-suspenders vs iOS focus zoom (>=16px)\n    \".wnf-av{position:relative;display:block;width:46px;height:46px;border-radius:50%;border:2px solid #f2c070;background:#FFFAED;flex:0 0 auto}\" +\n    \".wnf-av.big{width:52px;height:52px}\" +\n    \".wnf-av img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}\" +\n    \".wnf-dot{position:absolute;right:-1px;bottom:-1px;width:12px;height:12px;border-radius:50%;background:#3fbf6a;border:2px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.06);z-index:3}\" +\n    \".wnf--closed .wnf-dot{background:#e0a23f}\" +\n    // gold bubble launcher\n    \".wnf-launch{width:58px;height:58px;border-radius:50%;background:#f2c070;border:none;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 22px rgba(0,0,0,.28);cursor:pointer;position:relative;margin-left:auto}\" +\n    \".wnf-launch:hover{transform:translateY(-1px)}\" +\n    \".wnf-launch:active{transform:scale(.94)}\" +\n    \".wnf-launch svg{width:26px;height:26px;stroke:#1c1d1d}\" +\n    \".wnf-launch .wnf-dot{width:13px;height:13px}\" +\n    // always-visible subtle nudge bubble, sits just LEFT of the launcher (all screen sizes)\n    \".wnf-mini{position:absolute;right:72px;bottom:6px;display:flex;align-items:center;gap:11px;width:max-content;max-width:280px;background:#fff;color:#1c1d1d;border:1px solid #ece5d8;border-radius:16px 16px 4px 16px;box-shadow:0 12px 30px rgba(20,16,8,.18);padding:10px 32px 10px 10px;cursor:pointer;animation:wnfRise .35s ease}\" +\n    \".wnf-mini:hover{transform:translateY(-1px)}\" +\n    \".wnf-mini .wnf-av{width:40px;height:40px}\" +\n    \".wnf-mini__tx{min-width:0}\" +\n    \".wnf-mini__nm{font-size:10.5px;font-weight:700;color:#8a8073;text-transform:uppercase;letter-spacing:.3px;line-height:1.1;margin-bottom:2px;white-space:nowrap}\" +\n    \".wnf-mini__ln{font-size:14px;font-weight:600;line-height:1.3;color:#1c1d1d}\" +\n    // 44x44 tap circle CENTERED on the x glyph, extending 12px past the bubble corner\n    // (.wnf-mini doesn't clip). The prior 40px box was anchored inside the corner with the\n    // glyph at its edge, so a thumb tap centered on the glyph landed half OUTSIDE the bubble\n    // = dead zone, nothing happened (Hayden repro on iPhone 2026-07-04). Now the forgiveness\n    // surrounds the glyph on all sides; mini is appended after the launcher so the overlap\n    // corner still resolves to this button.\n    \".wnf-mini__x{position:absolute;top:-12px;right:-12px;width:44px;height:44px;display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;color:#c1b8aa;font-size:18px;line-height:1;cursor:pointer;border-radius:50%;touch-action:manipulation;-webkit-tap-highlight-color:transparent;z-index:2}\" +\n    \".wnf-mini__x:active{background:rgba(125,117,106,.16)}\" +\n    \".wnf-mini::after{content:'';position:absolute;right:-6px;bottom:15px;width:12px;height:12px;background:#fff;border-top:1px solid #ece5d8;border-right:1px solid #ece5d8;transform:rotate(45deg)}\" +\n    \".wnf-mini[hidden]{display:none}\" +\n    // dark proactive card\n    \".wnf-pop{position:absolute;right:0;bottom:70px;width:320px;max-width:86vw;background:#1c1d1d;color:#fff;border-radius:18px;box-shadow:0 18px 50px rgba(20,16,8,.4);padding:18px 16px;animation:wnfRise .35s ease}\" +\n    \"@keyframes wnfRise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}\" +\n    \".wnf-pop__hd{display:flex;align-items:center;gap:11px;margin-bottom:13px}\" +\n    \".wnf-pop__hd .nm{font-size:17px;font-weight:700;line-height:1.1}\" +\n    \".wnf-pop__hd .ro{font-size:12.5px;color:#f2c070;font-weight:600}\" +\n    \".wnf-pop__q{font-size:17px;font-weight:600;line-height:1.3;margin:0 0 5px;color:#fff}\" +\n    \".wnf-pop__sub{font-size:12.5px;color:#b8b0a0;margin:0 0 15px}\" +\n    \".wnf-x{position:absolute;top:7px;right:7px;width:38px;height:38px;display:flex;align-items:center;justify-content:center;background:none;border:none;color:#7d756a;font-size:23px;line-height:1;cursor:pointer;border-radius:50%}\" +\n    \".wnf-x:active{background:rgba(125,117,106,.18)}\" +\n    \".wnf-cta{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;border:none;border-radius:11px;padding:12px;font:inherit;font-size:15px;font-weight:700;cursor:pointer;margin-top:9px}\" +\n    \".wnf-cta svg{width:17px;height:17px;stroke:#1c1d1d}\" +\n    \".wnf-cta--gold{background:#f2c070;color:#1c1d1d}\" +\n    \".wnf-cta--gold:active{filter:brightness(.93)}\" +\n    \".wnf-cta--ghost{background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,.35);font-weight:600}\" +\n    \".wnf-cta--ghost:active{background:rgba(255,255,255,.12)}\" +\n    // panel\n    \".wnf-panel{display:none;flex-direction:column;position:absolute;right:0;bottom:70px;width:376px;max-width:92vw;height:600px;max-height:78vh;background:#fff;border-radius:18px;box-shadow:0 18px 50px rgba(20,16,8,.3);overflow:hidden}\" +\n    \".wnf-panel.open{display:flex}\" +\n    // One-row header: who you're talking to, whether the store is open, call, close.\n    // Address and full hours live in the answers (and the Hours & phone quick question).\n    \".wnf-hd{display:flex;align-items:center;gap:10px;background:#1c1d1d;color:#fff;padding:11px 8px 11px 14px;position:relative;flex:0 0 auto}\" +\n    \".wnf-hd .wnf-av{width:40px;height:40px}\" +\n    \".wnf-hdtxt{flex:1;min-width:0}\" +\n    \".wnf-hd .n{font-weight:700;font-size:15px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\" +\n    \".wnf-hd .s{display:flex;align-items:center;gap:5px;font-size:12px;line-height:1.35;color:#cdb98f;white-space:nowrap;overflow:hidden}\" +\n    \".wnf-hd .s .st{display:inline-flex;align-items:center;gap:5px;color:#a9a397}\" +\n    \".wnf-hd .s .st i{width:7px;height:7px;border-radius:50%;background:#3fbf6a;flex:0 0 auto}\" +\n    \".wnf--closed .wnf-hd .s .st i{background:#e0a23f}\" +\n    \".wnf-hdbtn{flex:0 0 auto;width:38px;height:38px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:50%;background:transparent;color:#cdb98f;cursor:pointer;text-decoration:none}\" +\n    \".wnf-hdbtn:hover,.wnf-hdbtn:active{background:rgba(255,255,255,.1);color:#fff}\" +\n    \".wnf-hdbtn svg{width:19px;height:19px;display:block}\" +\n    \".wnf-hd .wnf-x{position:static;font-size:0}\" +\n    \".wnf-tabs{display:flex;background:#26282a;padding:0 8px 8px}\" +\n    \".wnf-tab{flex:1;text-align:center;padding:8px;font:inherit;font-size:13px;font-weight:600;border:none;background:transparent;color:#cdb98f;cursor:pointer;border-radius:8px}\" +\n    \".wnf-tab.on{background:#f2c070;color:#1c1d1d}\" +\n    \".wnf-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;background:#FFFAED}\" +\n    \".wnf-log{display:flex;flex-direction:column;gap:8px;padding:14px}\" +\n    \".wnf-faq{display:none;padding:8px 14px 14px}\" +\n    \".wnf-faq__intro{font-size:12px;color:#8c8473;padding:8px 2px 4px}\" +\n    \".wnf-faq__more{font-size:12.5px;color:#8c8473;text-align:center;margin:14px 0 2px}\" +\n    \".wnf-fq{display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%;text-align:left;padding:13px 2px;border:none;border-bottom:1px solid #ece1c7;background:none;font:inherit;font-size:14.5px;font-weight:500;color:#1c1d1d;cursor:pointer}\" +\n    \".wnf-fq:hover,.wnf-fq:active{color:#404f52}.wnf-fq span{color:#f2c070;font-weight:700}\" +\n    \".wnf-rate{display:flex;align-items:center;gap:4px;margin:-3px 0 6px 4px;font-size:12px;color:#8a8073}\" +\n    \".wnf-rate span{margin-right:2px}\" +\n    \".wnf-rate button{display:flex;align-items:center;justify-content:center;width:34px;height:30px;padding:0;border:0;border-radius:15px;background:transparent;color:#8a8073;cursor:pointer}\" +\n    \".wnf-rate button:hover,.wnf-rate button:active{background:#f1e9d6;color:#1c1d1d}\" +\n    \".wnf-rate button svg{width:16px;height:16px}\" +\n    \".wnf-rate button:disabled{opacity:.5;cursor:default}\" +\n    // Quick questions under the welcome: the page's FAQs as one-tap chips. They go\n    // through the normal answer path (submit), and disappear once the chat starts.\n    \".wnf-qr{display:flex;flex-wrap:wrap;gap:6px;align-self:flex-start;max-width:94%;margin:2px 0 4px}\" +\n    \".wnf-qr button{border:1px solid #e3d3ad;background:#fff;color:#1c1d1d;border-radius:100px;padding:7px 13px;min-height:36px;font:inherit;font-size:13.5px;font-weight:500;line-height:1.2;cursor:pointer;text-align:left}\" +\n    \".wnf-qr button:hover,.wnf-qr button:active{background:#fdf1d8;border-color:#f2c070}\" +\n    // Store intro at the top of the thread: scrolls away as the conversation grows.\n    \".wnf-intro{display:flex;flex-direction:column;align-items:center;gap:5px;padding:4px 0 8px;opacity:.9}\" +\n    \".wnf-m{max-width:85%;padding:9px 12px;border-radius:13px;font-size:14px;line-height:1.45;white-space:pre-wrap}\" +\n    \".wnf-m.store{background:#fff;border:1px solid #ece4d2;align-self:flex-start;border-bottom-left-radius:4px}\" +\n    \".wnf-m.you{background:#f2c070;align-self:flex-end;border-bottom-right-radius:4px}\" +\n    \".wnf-m .by{display:block;font-size:10px;color:#404f52;font-weight:600;margin-bottom:2px}\" +\n    \".wnf-m a{color:#404f52;font-weight:600;text-decoration:underline;text-underline-offset:2px}\" +\n    \".wnf-m.you a{color:#1c1d1d}\" +\n    // product cards \u2014 a 2-up grid rendered under a store reply that recommends pieces\n    \".wnf-pc{align-self:flex-start;width:100%;max-width:94%;display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:-1px}\" +\n    \".wnf-pc__c{display:flex;flex-direction:column;background:#fff;border:1px solid #ece4d2;border-radius:12px;overflow:hidden;text-decoration:none;color:#1c1d1d;transition:box-shadow .15s ease,transform .15s ease}\" +\n    \".wnf-pc__c:hover,.wnf-pc__c:active{box-shadow:0 4px 14px rgba(28,29,29,.12);transform:translateY(-1px)}\" +\n    \".wnf-pc__img{width:100%;aspect-ratio:1/1;background:#FFFAED;overflow:hidden}\" +\n    \".wnf-pc__img img{width:100%;height:100%;object-fit:cover;display:block}\" +\n    \".wnf-pc__b{padding:8px 10px 10px;display:flex;flex-direction:column;gap:3px}\" +\n    \".wnf-pc__t{font-size:12.5px;font-weight:600;line-height:1.3;color:#1c1d1d;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\" +\n    \".wnf-pc__p{font-size:12.5px;font-weight:700;color:#404f52}\" +\n    \".wnf-pc__cta{margin-top:5px;align-self:flex-start;background:#f2c070;color:#1c1d1d;font-size:11px;font-weight:700;border-radius:100px;padding:4px 12px;text-decoration:none}\" +\n    // typing indicator (three pulsing dots) shown while a store reply is \"being typed\"\n    \".wnf-typing .wnf-m__t{display:inline-flex;align-items:center;gap:4px;padding:2px 0}\" +\n    \".wnf-dots{display:inline-flex;gap:4px}\" +\n    \".wnf-dots i{width:6px;height:6px;border-radius:50%;background:#b6ad9c;display:inline-block;animation:wnfBlink 1.25s infinite ease-in-out both}\" +\n    \".wnf-dots i:nth-child(2){animation-delay:.18s}\" +\n    \".wnf-dots i:nth-child(3){animation-delay:.36s}\" +\n    \"@keyframes wnfBlink{0%,80%,100%{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}\" +\n    \".wnf-cc{align-self:flex-start;max-width:94%;background:#fff;border:1px solid #ece4d2;border-radius:14px;padding:13px 14px;margin-top:2px;display:flex;flex-direction:column;gap:8px}\" +\n    \".wnf-cc__t{font-size:13.5px;line-height:1.45;color:#1c1d1d;font-weight:600}\" +\n    \".wnf-cc__in{width:100%;box-sizing:border-box;border:1px solid #ece4d2;border-radius:9px;padding:10px 12px;font-family:inherit;font-size:16px;color:#1c1d1d;background:#FFFAED;outline:none}\" +\n    \".wnf-cc__in:focus{border-color:#f2c070}\" +\n    \".wnf-cc__err{font-size:12px;color:#9a2c1a;margin:-2px 0 0}\" +\n    \".wnf-cc__row{display:flex;align-items:center;gap:12px;margin-top:2px}\" +\n    \".wnf-cc__send{background:#f2c070;color:#1c1d1d;border:0;border-radius:9px;padding:11px 20px;min-height:44px;font-family:inherit;font-size:14px;font-weight:700;cursor:pointer}\" +\n    \".wnf-cc__send:active{filter:brightness(.93)}\" +\n    \".wnf-cc__skip{background:transparent;border:0;color:#8c8473;font-family:inherit;font-size:13px;min-height:44px;padding:0 4px;cursor:pointer;text-decoration:underline}\" +\n    // Composer: one field holding photo, text, and send. Send lights up only when\n    // there is something to send.\n    \".wnf-ft{display:flex;align-items:center;padding:10px 12px;border-top:1px solid #ece4d2;background:#fff}\" +\n    \".wnf-field{flex:1;min-width:0;display:flex;align-items:center;gap:2px;padding:3px;background:#FFFAED;border:1px solid #e6dcc6;border-radius:24px;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}\" +\n    \".wnf-field:focus-within{border-color:#e2b865;background:#fff;box-shadow:0 0 0 3px rgba(242,192,112,.22)}\" +\n    // The storefront theme puts its own focus ring on every input; the field owns focus here.\n    \".wnf .wnf-in,.wnf .wnf-in:focus,.wnf .wnf-in:focus-visible,.wnf-page-host .wnf-in,.wnf-page-host .wnf-in:focus,.wnf-page-host .wnf-in:focus-visible{border:0!important;outline:none!important;box-shadow:none!important}\" +\n    \".wnf-in{flex:1;min-width:0;border:0;border-radius:0;padding:9px 4px;font:inherit;font-size:16px;line-height:20px;outline:none;background:transparent;color:#1c1d1d;caret-color:#1c1d1d;-webkit-appearance:none;appearance:none}\" +\n    \".wnf-in::placeholder{color:#958b78}\" +\n    \".wnf-send{flex:0 0 auto;width:38px;height:38px;border:0;border-radius:50%;background:#efe7d6;color:#a89f8c;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;transition:background .15s ease,color .15s ease}\" +\n    \".wnf-ft.has-text .wnf-send{background:#f2c070;color:#1c1d1d}\" +\n    \".wnf-ft.has-text .wnf-send:hover,.wnf-ft.has-text .wnf-send:active{background:#e6ad4f}\" +\n    \".wnf-send svg{width:17px;height:17px;stroke:currentColor;fill:none;margin-left:-1px}\" +\n    // image bubbles \u2014 a photo the customer sent, or a staff-sent image\n    \".wnf-imgs{display:flex;flex-wrap:wrap;gap:6px;margin:1px 0}\" +\n    \".wnf-img{display:block;max-width:210px;border-radius:11px;overflow:hidden;border:1px solid rgba(28,29,29,.08)}\" +\n    \".wnf-img img{display:block;width:100%;height:auto;max-height:260px;object-fit:cover;background:#FFFAED}\" +\n    \".wnf-m--img{padding:4px;background:transparent;border:none;max-width:70%}\" +\n    \".wnf-m.you.wnf-m--img{background:transparent}\" +\n    // attach (camera) button in the composer + the pending-photo preview strip\n    \".wnf-clip{flex:0 0 auto;width:38px;height:38px;border:0;border-radius:50%;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;color:#8c8473}\" +\n    \".wnf-clip:hover,.wnf-clip:active{background:#f1e9d6;color:#404f52}\" +\n    \".wnf-clip svg{width:20px;height:20px}\" +\n    \".wnf-atts[hidden]{display:none}\" +\n    \".wnf-atts{display:flex;flex-wrap:wrap;gap:8px;padding:10px 12px 0;background:#fff}\" +\n    \".wnf-att{position:relative;width:56px;height:56px;border-radius:10px;overflow:hidden;border:1px solid #ece1c7;background:#FFFAED}\" +\n    \".wnf-att img{width:100%;height:100%;object-fit:cover;display:block}\" +\n    \".wnf-att__x{position:absolute;top:2px;right:2px;width:18px;height:18px;border:0;border-radius:50%;background:rgba(28,29,29,.72);color:#fff;font-size:12px;line-height:18px;text-align:center;cursor:pointer;padding:0}\" +\n    \".wnf-blz-lock{display:inline-flex;align-items:center;gap:8px}\" +\n    \".wnf-blz-mark{height:24px;width:auto;display:block}\" +\n    \".wnf-blz-txt{font-size:9.5px;font-weight:700;color:#1c1d1d;text-align:left;line-height:1.15;letter-spacing:.03em;text-transform:uppercase}\" +\n    \".wnf-blz-txt small{display:block;font-weight:500;color:#404f52;font-size:9px;letter-spacing:.01em;text-transform:none}\" +\n    \".wnf-since{font-size:11px;color:#8c8473}\" +\n    // Mobile: align the sheet to Safari's visible viewport rectangle. The composer is\n    // pinned to the sheet bottom, so it follows the keyboard without a separate estimate.\n    \"@media (max-width:600px),(pointer:coarse) and (max-height:500px) and (max-width:950px){\" +\n      \".wnf{left:calc(18px + env(safe-area-inset-left));right:calc(18px + env(safe-area-inset-right));bottom:calc(18px + env(safe-area-inset-bottom) + var(--wnf-lift, 0px));pointer-events:none}\" +\n      // .wnf-mini MUST be here too: the root is pointer-events:none on mobile, so any\n      // interactive child left off this list renders fine but is tap-through \u2014 the mini\n      // bubble (and its dismiss \u00D7) was dead on phones until added 2026-07-04.\n      \".wnf-launch,.wnf-pop,.wnf-panel,.wnf-mini,.wnf-sheet{pointer-events:auto}\" +\n      \".wnf-panel{--wnf-vv-left:0px;--wnf-vv-top:0px;position:fixed;top:0;left:0;right:auto;bottom:auto;width:100%;max-width:none;height:100vh;height:100dvh;max-height:none;border-radius:0;transform:translate3d(var(--wnf-vv-left),var(--wnf-vv-top),0)}\" +\n      \".wnf-panel.open{animation:wnfSheet .28s ease}\" +\n      \".wnf-panel.closing{display:flex;animation:wnfSheetOut .22s ease forwards}\" +\n      \".wnf-hd{padding-top:calc(11px + env(safe-area-inset-top))}\" +\n      \".wnf-hdbtn{width:44px;height:44px}\" +\n      \".wnf-qr button{min-height:40px}\" +\n      \".wnf-rate button{width:44px;height:36px}\" +\n      \".wnf-body{padding-bottom:calc(78px + env(safe-area-inset-bottom));scroll-padding-bottom:calc(78px + env(safe-area-inset-bottom))}\" +\n      \".wnf-ft{position:absolute;left:0;right:0;bottom:0;padding-bottom:calc(11px + env(safe-area-inset-bottom))}\" +\n      \".wnf-pop{right:0;width:min(320px,100%);max-width:none}\" +\n      \".wnf-cc{width:100%;max-width:100%}\" +\n      \".wnf-cc__in{min-height:44px}\" +\n    \"}\" +\n    \"@keyframes wnfSheet{from{opacity:.5;transform:translateY(100%)}to{opacity:1;transform:none}}\" +\n    \"@keyframes wnfSheetOut{from{opacity:1;transform:none}to{opacity:.4;transform:translateY(100%)}}\" +\n    \"@media (prefers-reduced-motion:reduce){.wnf-pop{animation:none}.wnf-panel.open,.wnf-panel.closing{animation:none}.wnf-launch:active{transform:none}}\" +\n    // ---- experiment arm \"sheet\" (phones): compact question sheet, Sunflower style ----\n    // Jost \u00B7 plum #432d3a \u00B7 muted #675e61 \u00B7 oat #f7f5f0 \u00B7 sun #f4c44f. Sits above any\n    // sticky buy bar (--wnf-sheet-lift) and never over Add to Cart (see sheetGuard).\n    \".wnf--sheet-up .wnf-launch,.wnf--sheet-up .wnf-mini{visibility:hidden}\" +\n    \".wnf-sheet{position:fixed;left:calc(10px + env(safe-area-inset-left));right:calc(10px + env(safe-area-inset-right));bottom:calc(10px + env(safe-area-inset-bottom) + var(--wnf-sheet-lift,0px));max-width:460px;margin:0 auto;background:#f7f5f0;color:#432d3a;border:1px solid rgba(67,45,58,.10);border-radius:18px;box-shadow:0 16px 40px rgba(40,24,34,.18),0 2px 8px rgba(40,24,34,.06);padding:14px 0 12px;font-family:Jost,Futura,'Futura PT','Trebuchet MS',Arial,sans-serif;letter-spacing:.2px;line-height:1.3;transition:bottom .24s ease,opacity .2s ease,transform .2s ease;animation:wnfSheetIn .36s cubic-bezier(.2,.8,.2,1)}\" +\n    \".wnf-sheet.out{opacity:0;transform:translateY(14px);pointer-events:none}\" +\n    \"@keyframes wnfSheetIn{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}\" +\n    \".wnf-sheet__hd{display:flex;align-items:center;gap:11px;padding:0 48px 0 14px}\" +\n    \".wnf-sheet .wnf-av{width:40px;height:40px;border-color:#f4c44f}\" +\n    \".wnf-sheet__t{font-size:16.5px;font-weight:600;color:#432d3a;letter-spacing:-.1px;margin:0}\" +\n    \".wnf-sheet__by{display:flex;align-items:center;gap:5px;font-size:12.5px;color:#675e61;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\" +\n    \".wnf-sheet__by i{width:7px;height:7px;border-radius:50%;background:#3fbf6a;flex:0 0 auto}\" +\n    \".wnf--closed .wnf-sheet__by i{background:#e0a23f}\" +\n    \".wnf-sheet__x{position:absolute;top:4px;right:4px;width:44px;height:44px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:50%;background:transparent;color:#675e61;cursor:pointer}\" +\n    \".wnf-sheet__x svg{width:18px;height:18px}\" +\n    \".wnf-sheet__x:active{background:rgba(67,45,58,.08)}\" +\n    \".wnf-sheet__rail{display:flex;gap:8px;overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding:12px 14px 2px;scroll-padding:0 14px;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent)}\" +\n    \".wnf-sheet__rail::-webkit-scrollbar{display:none}\" +\n    \".wnf-chip{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;min-height:42px;padding:0 15px;border:1px solid rgba(67,45,58,.20);border-radius:999px;background:#fff;color:#432d3a;font:inherit;font-size:14.5px;font-weight:500;letter-spacing:.1px;white-space:nowrap;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s ease,border-color .15s ease,transform .1s ease}\" +\n    \".wnf-chip:active{background:#fdf3d4;border-color:#f4c44f;transform:scale(.98)}\" +\n    \".wnf-chip--own{background:transparent;border-style:dashed;color:#675e61}\" +\n    \".wnf-chip svg{width:15px;height:15px;flex:0 0 auto}\" +\n    \".wnf-sheet__ft{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 16px 0;font-size:12.5px;color:#675e61}\" +\n    \".wnf-sheet__photo{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;min-height:36px;padding:0;border:0;background:none;color:#432d3a;font:inherit;font-size:14px;font-weight:600;white-space:nowrap;cursor:pointer;text-decoration:underline;text-decoration-color:rgba(67,45,58,.3);text-underline-offset:3px}\" +\n    \".wnf-sheet__photo svg{width:18px;height:18px}\" +\n    \".wnf-sheet__note{flex:1 1 auto;min-width:0;font-size:12px;line-height:1.25;text-align:right}\" +\n    \".wnf-sheet__note:only-child{text-align:left}\" +\n    \"@media (prefers-reduced-motion:reduce){.wnf-sheet{animation:none;transition:none}}\" +\n    // one-field contact ask (sheet arm) and the photo prompt card\n    \".wnf-cc2{align-self:stretch;background:#fff;border:1px solid rgba(67,45,58,.12);border-radius:14px;padding:13px 14px 8px;margin:2px 0;color:#432d3a;font-family:inherit}\" +\n    \".wnf-cc2__t{font-size:15px;font-weight:600;line-height:1.35;margin:0}\" +\n    \".wnf-cc2__s{font-size:13px;color:#675e61;line-height:1.4;margin:2px 0 10px}\" +\n    \".wnf-cc2__row{display:flex;gap:8px}\" +\n    \".wnf .wnf-cc2__in,.wnf-page-host .wnf-cc2__in{flex:1;min-width:0;height:44px;border:1px solid rgba(67,45,58,.22)!important;border-radius:10px;padding:0 12px;font:inherit;font-size:16px;color:#432d3a;background:#f7f5f0;outline:none!important;box-shadow:none!important;-webkit-appearance:none;appearance:none}\" +\n    \".wnf .wnf-cc2__in:focus,.wnf-page-host .wnf-cc2__in:focus{border-color:#432d3a!important;background:#fff}\" +\n    \".wnf-cc2__go{flex:0 0 auto;height:44px;padding:0 18px;border:0;border-radius:10px;background:#432d3a;color:#fff;font:inherit;font-size:15px;font-weight:600;cursor:pointer}\" +\n    \".wnf-cc2__go:disabled{opacity:.6}\" +\n    \".wnf-cc2__err{font-size:12.5px;color:#9a2c1a;margin:6px 0 0}\" +\n    \".wnf-cc2__no{display:block;min-height:36px;margin:4px auto 0;padding:0 8px;border:0;background:none;color:#675e61;font:inherit;font-size:13px;cursor:pointer}\" +\n    \".wnf-pcta{align-self:stretch;display:flex;flex-direction:column;gap:4px;background:#fff;border:1px solid rgba(67,45,58,.12);border-radius:14px;padding:14px;margin:2px 0;color:#432d3a;font-family:inherit}\" +\n    \".wnf-pcta__t{font-size:15px;font-weight:600;margin:0}\" +\n    \".wnf-pcta__s{font-size:13px;color:#675e61;margin:0 0 8px}\" +\n    \".wnf-pcta__go{display:flex;align-items:center;justify-content:center;gap:8px;height:46px;border:0;border-radius:10px;background:#432d3a;color:#fff;font:inherit;font-size:15px;font-weight:600;cursor:pointer}\" +\n    \".wnf-pcta__go svg{width:19px;height:19px}\";\n\n  var root, panel, bodyEl, log, faqEl, input, ft, popEl, miniEl = null, miniDismissed = false, booted = false, lastAt = null, pollTimer = null, pollActive = false, pollDelay = 5000, emptyPolls = 0, opened = false, started = false;\n  // Bug-fix state: seenIds dedupes rendered replies so the poll can never show the\n  // same staff message twice; lastPrompt/promptSent carry the assistant line the\n  // customer saw (card/welcome) to the backend ONCE so staff have context.\n  var seenIds = {}, lastPrompt = \"\", promptSent = false;\n  var askedContact = false, contactSent = false, contactAfterAnswer = false, photoTurn = false;\n  // Contact ask bookkeeping (2026-10-03 fix for the 9/4 regression that stopped asking\n  // on automated answers). One widget ask per thread (persisted per chat session);\n  // no card right after the automated reply itself asked for an email or phone, or\n  // once the shopper has typed one.\n  var ASKED_KEY = \"wnf_contact_asked:\" + sessionId, answerBuf = \"\", turnNo = 0, aiAskTurn = 0;\n  var AI_ASKS_RE = /\\b(your|best)\\s+(e-?mail|phone|number|contact)|\\breach you\\b|\\bget back to you\\b|\\bfollow up with you\\b|\\bcontact (info|details|information)\\b|\\b(leave|share|send) (us )?(an|your) (e-?mail|phone|number)/i;\n  var TYPED_CONTACT_RE = /[^@\\s]+@[^@\\s]+\\.[a-z]{2,}|(?:\\+?1[\\s.-]?)?\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}\\b/i;\n  function noteStoreBubble(sender, body) { if (contactAfterAnswer && sender === ASSISTANT_NAME) answerBuf += \"\\n\" + (body || \"\"); }\n  function afterAnswerDone() {\n    if (!contactAfterAnswer || !answerBuf) return;\n    contactAfterAnswer = false;\n    var text = answerBuf; answerBuf = \"\";\n    if (AI_ASKS_RE.test(text)) { aiAskTurn = turnNo; track(\"wnf_chat_contact_deferred\", { reason: \"ai_asked\" }); return; }\n    if (aiAskTurn && turnNo - aiAskTurn < 2) { track(\"wnf_chat_contact_deferred\", { reason: \"ai_asked_last_turn\" }); return; }\n    setTimeout(function () { maybeContact(\"answer\"); }, 900);\n  }\n  // Pending image attachments (downscaled, not yet sent) + the preview strip element.\n  var attsEl = null, pendingImgs = [], MAX_ATTS = 3;\n\n  // ---- panel ------------------------------------------------------------------\n  function buildPanel() {\n    panel = el(\"div\", { class: \"wnf-panel\", role: \"dialog\", \"aria-modal\": \"true\", \"aria-label\": \"Chat with What's New Furniture\", tabindex: \"-1\" });\n    panel.innerHTML =\n      '<div class=\"wnf-hd\">' + avatar() +\n        '<div class=\"wnf-hdtxt\"><div class=\"n\">' + esc(host.name) + '</div>' +\n        '<div class=\"s\">' + statusLine() + '</div></div>' +\n        '<a class=\"wnf-hdbtn wnf-call\" href=\"tel:+15032353454\" aria-label=\"Call the store at (503) 235-3454\" title=\"Call (503) 235-3454\">' + PHONE_SVG + '</a>' +\n        '<button class=\"wnf-hdbtn wnf-x\" aria-label=\"Close\">' + CLOSE_SVG + '</button></div>' +\n      '<div class=\"wnf-body\"><div class=\"wnf-log\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\"></div><div class=\"wnf-faq\"></div></div>' +\n      '<div class=\"wnf-atts\" hidden></div>' +\n      '<div class=\"wnf-ft\"><div class=\"wnf-field\">' +\n        '<button class=\"wnf-clip\" aria-label=\"Attach a photo\" title=\"Attach a photo\">' + CLIP_SVG + '</button>' +\n        '<input class=\"wnf-file\" type=\"file\" accept=\"image/*\" multiple hidden aria-hidden=\"true\">' +\n        '<input class=\"wnf-in\" type=\"text\" placeholder=\"' + esc(placeholderText()) + '\" aria-label=\"Message\" enterkeyhint=\"send\" autocomplete=\"off\" autocorrect=\"on\" autocapitalize=\"sentences\">' +\n        '<button class=\"wnf-send\" aria-label=\"Send\">' + SEND_SVG + '</button>' +\n      '</div></div>';\n    root.appendChild(panel);\n    bodyEl = panel.querySelector(\".wnf-body\");\n    log = panel.querySelector(\".wnf-log\");\n    faqEl = panel.querySelector(\".wnf-faq\");\n    input = panel.querySelector(\".wnf-in\");\n    ft = panel.querySelector(\".wnf-ft\");\n    attsEl = panel.querySelector(\".wnf-atts\");\n    panel.querySelector(\".wnf-x\").onclick = function () { PAGE_MODE ? leaveChatPage() : closePanel(); };\n    panel.querySelector(\".wnf-call\").addEventListener(\"click\", function () { track(\"wnf_chat_call\"); });\n    input.addEventListener(\"input\", syncSend);\n    var sendBtn = panel.querySelector(\".wnf-send\");\n    sendBtn.onclick = function () { submit(input.value); };\n    // A tap on Send while the soft keyboard is up must NOT blur the input: the blur\n    // collapses the visual viewport mid-tap, the composer jumps down before the click\n    // dispatches, and the tap dies (the mobile \"send does nothing\" bug). Preventing\n    // mousedown's default keeps focus \u2014 and the keyboard \u2014 in place; click still fires.\n    sendBtn.addEventListener(\"mousedown\", function (e) { e.preventDefault(); });\n    input.addEventListener(\"keydown\", function (e) { if (e.key === \"Enter\") submit(input.value); });\n    bindKeyboardInput(input);\n    // Attach-a-photo: file picker, paste-into-input, and drag-drop onto the panel.\n    var fileInput = panel.querySelector(\".wnf-file\");\n    var clipBtn = panel.querySelector(\".wnf-clip\");\n    clipBtn.onclick = function () { fileInput.click(); };\n    clipBtn.addEventListener(\"mousedown\", function (e) { e.preventDefault(); }); // same blur race as Send\n    fileInput.addEventListener(\"change\", function () { handleFiles(fileInput.files); fileInput.value = \"\"; });\n    input.addEventListener(\"paste\", function (e) {\n      var items = e.clipboardData && e.clipboardData.items; if (!items) return;\n      var files = []; for (var i = 0; i < items.length; i++) { if (items[i].kind === \"file\") { var f = items[i].getAsFile(); if (f) files.push(f); } }\n      if (files.length) { e.preventDefault(); handleFiles(files); }\n    });\n    panel.addEventListener(\"dragover\", function (e) { if (e.dataTransfer && Array.prototype.indexOf.call(e.dataTransfer.types || [], \"Files\") >= 0) { e.preventDefault(); } });\n    panel.addEventListener(\"drop\", function (e) { if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) { e.preventDefault(); handleFiles(e.dataTransfer.files); } });\n    renderFaq();\n  }\n  // \"Local Owner \u00B7 \u25CF Open till 6pm\" (or \"Opens 10am\" after hours), from store hours.\n  function statusLine() {\n    return esc(host.role) + '<span aria-hidden=\"true\">\u00B7</span><span class=\"st\"><i></i>' + esc(storeHoursNote()) + \"</span>\";\n  }\n  function hourLabel(h) { return (h % 12 || 12) + (h < 12 || h === 24 ? \"am\" : \"pm\"); }\n  var DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n  function storeHoursNote() {\n    try {\n      var now = pdxNow(), today = hoursOn(now, 0), holiday = isHoliday(now.y, now.m, now.d);\n      if (today && now.hour >= today[0] && now.hour < today[1]) return \"Open till \" + hourLabel(today[1]);\n      if (today && now.hour < today[0]) return \"Opens \" + hourLabel(today[0]);\n      // Next opening skips closed days and holidays. The day is named unless it is\n      // simply tomorrow after a normal day (today's wording, unchanged).\n      for (var i = 1; i <= 10; i++) {\n        var next = hoursOn(now, i);\n        if (next) return \"Opens \" + (i === 1 && !holiday ? \"\" : DAY_NAMES[(now.wd + i) % 7] + \" \") + hourLabel(next[0]);\n      }\n    } catch (e) {}\n    return \"Portland, OR\";\n  }\n  function syncSend() { if (ft && input) ft.classList.toggle(\"has-text\", !!input.value.trim() || pendingImgs.length > 0); }\n  function placeholderText() { return copyFor().ph || \"What are you furnishing?\"; }\n  function switchTab(name) {\n    var chat = name === \"chat\";\n    log.style.display = chat ? \"flex\" : \"none\";\n    faqEl.style.display = chat ? \"none\" : \"block\";\n    if (ft) ft.style.display = chat ? \"flex\" : \"none\";\n    if (chat) { startChat(); startPolling(); }\n  }\n  function renderFaq() {\n    faqEl.innerHTML = '<div class=\"wnf-faq__intro\">Tap a question to check current details.</div>' +\n      FAQS.map(function (f, i) { return '<button class=\"wnf-fq\" data-i=\"' + i + '\">' + esc(f.q) + ' <span>\u2192</span></button>'; }).join(\"\") +\n      '<div class=\"wnf-faq__more\">Don\\'t see your question?</div>' +\n      '<button class=\"wnf-cta wnf-cta--gold wnf-faq__chat\">' + CHAT_SVG + ' Ask ' + esc(firstName()) + ' a question</button>';\n    faqEl.querySelectorAll(\".wnf-fq\").forEach(function (b) {\n      b.onclick = function () {\n        var f = FAQS[+b.getAttribute(\"data-i\")];\n        track(\"wnf_chat_faq\", { q: f.q });\n        switchTab(\"chat\");\n        submit(f.q);\n      };\n    });\n    faqEl.querySelector(\".wnf-faq__chat\").onclick = function () { track(\"wnf_chat_faq_escalate\"); switchTab(\"chat\"); if (input) input.focus(); };\n  }\n\n  // ---- product cards ---------------------------------------------------------\n  // A store reply that recommends pieces carries a `products` array (from the AI's\n  // catalog search). Render them as a small 2-up grid of cards under the bubble.\n  function wnfMoney(n) { return \"$\" + Number(n).toLocaleString(\"en-US\", { minimumFractionDigits: Number.isInteger(Number(n)) ? 0 : 2, maximumFractionDigits: 2 }); }\n  function wnfPriceLabel(min, max) {\n    if (min == null) return \"\";\n    if (max == null || min === max) return wnfMoney(min);\n    return wnfMoney(min) + \"\u2013\" + wnfMoney(max);\n  }\n  function productCards(products) {\n    if (!products || !products.length) return null;\n    var grid = el(\"div\", { class: \"wnf-pc\" });\n    var n = 0;\n    products.forEach(function (p) {\n      if (!p || !p.title || n >= 6) return;\n      // textContent everywhere \u2014 never innerHTML untrusted catalog strings.\n      var card = el(\"a\", { class: \"wnf-pc__c\" });\n      if (p.url) { card.setAttribute(\"href\", p.url); card.setAttribute(\"rel\", \"noopener\"); }\n      var imgWrap = el(\"div\", { class: \"wnf-pc__img\" });\n      if (p.imageUrl) { var img = el(\"img\", { alt: \"\", loading: \"lazy\" }); img.setAttribute(\"src\", p.imageUrl); imgWrap.appendChild(img); }\n      card.appendChild(imgWrap);\n      var b = el(\"div\", { class: \"wnf-pc__b\" });\n      var t = el(\"div\", { class: \"wnf-pc__t\" }); t.textContent = p.title; b.appendChild(t);\n      var label = wnfPriceLabel(p.priceMin, p.priceMax);\n      if (label) { var pr = el(\"div\", { class: \"wnf-pc__p\" }); pr.textContent = label; b.appendChild(pr); }\n      var cta = el(\"span\", { class: \"wnf-pc__cta\" }); cta.textContent = \"View\"; b.appendChild(cta);\n      card.appendChild(b);\n      card.addEventListener(\"click\", function () { track(\"wnf_chat_product_click\", { handle: p.handle || \"\" }); });\n      grid.appendChild(card); n++;\n    });\n    return n ? grid : null;\n  }\n\n  // ---- image attachments -----------------------------------------------------\n  // Render a small row of image bubbles (a customer's photo, or a staff-sent image).\n  // Each `im` is { url, w, h } \u2014 url is a signed URL (from the poll) or a local\n  // object/data URL (the customer's own just-sent photo). Tapping opens it full-size.\n  function imageGrid(images) {\n    var wrap = el(\"div\", { class: \"wnf-imgs\" });\n    var n = 0;\n    (images || []).forEach(function (im) {\n      if (!im || !im.url || n >= 4) return;\n      var a = el(\"a\", { class: \"wnf-img\", rel: \"noopener\", target: \"_blank\" });\n      a.setAttribute(\"href\", im.url);\n      var img = el(\"img\", { alt: \"attached image\", loading: \"lazy\" });\n      img.setAttribute(\"src\", im.url);\n      if (im.w && im.h) { img.setAttribute(\"width\", im.w); img.setAttribute(\"height\", im.h); }\n      a.appendChild(img); wrap.appendChild(a); n++;\n    });\n    return n ? wrap : null;\n  }\n\n  // Downscale a picked file to a longest-edge ~1568px JPEG (Claude's sweet spot; also\n  // keeps uploads small). Everything routes through a canvas so HEIC/PNG/WebP all\n  // normalize to JPEG. Calls back with { blob, mime, w, h, previewUrl } or null.\n  function downscaleImage(file, cb) {\n    try {\n      var url = URL.createObjectURL(file);\n      var img = new Image();\n      img.onload = function () {\n        try {\n          var maxEdge = 1568;\n          var w = img.naturalWidth || img.width, h = img.naturalHeight || img.height;\n          var scale = Math.min(1, maxEdge / Math.max(w, h || 1));\n          var tw = Math.max(1, Math.round(w * scale)), th = Math.max(1, Math.round(h * scale));\n          var canvas = document.createElement(\"canvas\");\n          canvas.width = tw; canvas.height = th;\n          canvas.getContext(\"2d\").drawImage(img, 0, 0, tw, th);\n          URL.revokeObjectURL(url);\n          var previewUrl = canvas.toDataURL(\"image/jpeg\", 0.7);\n          canvas.toBlob(function (blob) {\n            if (!blob) { cb(null); return; }\n            cb({ blob: blob, mime: \"image/jpeg\", w: tw, h: th, previewUrl: previewUrl });\n          }, \"image/jpeg\", 0.85);\n        } catch (e) { try { URL.revokeObjectURL(url); } catch (e2) {} cb(null); }\n      };\n      img.onerror = function () { try { URL.revokeObjectURL(url); } catch (e) {} cb(null); };\n      img.src = url;\n    } catch (e) { cb(null); }\n  }\n\n  function handleFiles(fileList) {\n    var files = Array.prototype.slice.call(fileList || []);\n    files.forEach(function (f) {\n      if (!f || String(f.type).indexOf(\"image/\") !== 0) return;\n      if (pendingImgs.length >= MAX_ATTS) return;\n      downscaleImage(f, function (res) {\n        if (!res) { add(\"store\", \"That image wouldn't load \u2014 mind trying a different photo?\", \"WNF\"); return; }\n        if (pendingImgs.length >= MAX_ATTS) return;\n        pendingImgs.push(res);\n        renderAtts();\n      });\n    });\n  }\n\n  // Rebuild the pending-photo preview strip above the composer (thumbnails + remove).\n  function renderAtts() {\n    syncSend();\n    if (!attsEl) return;\n    attsEl.innerHTML = \"\";\n    if (!pendingImgs.length) { attsEl.hidden = true; return; }\n    attsEl.hidden = false;\n    pendingImgs.forEach(function (a, i) {\n      var chip = el(\"div\", { class: \"wnf-att\" });\n      var img = el(\"img\", { alt: \"\" }); img.setAttribute(\"src\", a.previewUrl); chip.appendChild(img);\n      var x = el(\"button\", { class: \"wnf-att__x\", type: \"button\", \"aria-label\": \"Remove photo\" }, \"\u00D7\");\n      x.onclick = function () { pendingImgs.splice(i, 1); renderAtts(); };\n      chip.appendChild(x);\n      attsEl.appendChild(chip);\n    });\n    scrollChatBottom();\n  }\n\n  // \"Helpful? \uD83D\uDC4D \uD83D\uDC4E\" under the last bubble of a task-free automatic answer (server\n  // marks it rateable). A \uD83D\uDC4D is our verified-resolution signal; a \uD83D\uDC4E opens a staff task.\n  function addRating(messageId) {\n    if (!messageId || !log) return;\n    var row = el(\"div\", { class: \"wnf-rate\", role: \"group\", \"aria-label\": \"Rate this answer\" },\n      '<span>Helpful?</span><button type=\"button\" data-r=\"up\" aria-label=\"Yes, helpful\">' + THUMB_SVG + '</button><button type=\"button\" data-r=\"down\" aria-label=\"No, not helpful\"><span style=\"display:flex;transform:rotate(180deg)\">' + THUMB_SVG + '</span></button>');\n    function done(text) { row.innerHTML = \"<span>\" + esc(text) + \"</span>\"; }\n    Array.prototype.forEach.call(row.querySelectorAll(\"button\"), function (b) {\n      b.onclick = function () {\n        var r = b.getAttribute(\"data-r\");\n        Array.prototype.forEach.call(row.querySelectorAll(\"button\"), function (x) { x.disabled = true; });\n        track(\"wnf_chat_rating\", { rating: r });\n        fetch(API + \"/api/chat/rate\", { method: \"POST\", headers: { \"content-type\": \"text/plain\" }, body: JSON.stringify({ sessionId: sessionId, messageId: messageId, rating: r }) })\n          .then(function (res) { if (!res.ok) throw new Error(res.status); done(r === \"up\" ? \"Thanks!\" : \"Sorry about that. I've flagged it for the team.\"); })\n          .catch(function () { done(\"Couldn't save that. If something's off, tell me here.\"); });\n      };\n    });\n    log.appendChild(row); scrollChatBottom();\n  }\n  function add(from, body, by, products, images) {\n    removeQuickReplies();\n    var hasBody = body != null && String(body).trim().length > 0;\n    var imgEl = imageGrid(images);\n    var m = el(\"div\", { class: \"wnf-m \" + (from === \"you\" ? \"you\" : \"store\") + (imgEl && !hasBody ? \" wnf-m--img\" : \"\") });\n    if (from !== \"you\" && by) m.innerHTML = '<span class=\"by\">' + esc(by) + \"</span>\";\n    if (imgEl) m.appendChild(imgEl);\n    if (hasBody) m.appendChild(el(\"span\", { class: \"wnf-m__t\" }, fmt(body)));\n    log.appendChild(m);\n    if (from !== \"you\") { var pc = productCards(products); if (pc) log.appendChild(pc); }\n    scrollChatBottom();\n  }\n\n  // ---- realistic reply pacing (types like a very fast human) ------------------\n  // Fresh store replies aren't dumped in instantly. We show a typing indicator,\n  // then reveal each bubble after a short, length-based delay, so a multi-bubble\n  // answer lands as a few quick texts the way a person fires them off.\n  // Tuned from research (Gnewuch dynamic-delay; Nielsen 0.1/1/10s limits): the\n  // delay scales with length (feels human) but the WHOLE turn is budgeted to stay\n  // snappy (a reply the AI already has shouldn't take ~10s to land). Tunables:\n  //   ~22ms/char, first bubble floored at 0.8s (never robotically instant), later\n  //   bubbles 0.55s, per-bubble cap 2.8s, gaps scale with the prior bubble length,\n  //   \u00B118% jitter so it isn't mechanical, ~5s total budget per turn.\n  var PACE_PER_CHAR = 22, PACE_BASE = 250, PACE_MIN = 550, PACE_FIRST_MIN = 800, PACE_MAX = 2800, PACE_TURN_BUDGET = 5000;\n  var revealQ = [], revealing = false, typingEl = null, turnSpent = 0, turnFirst = true;\n  function paceJitter(ms) { return Math.round(ms * (0.82 + Math.random() * 0.36)); } // \u00B118%\n  function paceGap(prevLen) { return Math.max(400, Math.min(1200, Math.round(prevLen * 6))); }\n  function showTyping() {\n    if (typingEl || !log) return;\n    typingEl = el(\"div\", { class: \"wnf-m store wnf-typing\", \"aria-label\": \"Checking current store details\" },\n      '<span class=\"by\">WNF</span>' +\n      '<span class=\"wnf-m__t\"><span class=\"wnf-dots\"><i></i><i></i><i></i></span></span>');\n    log.appendChild(typingEl); scrollChatBottom();\n  }\n  function hideTyping() {\n    if (typingEl && typingEl.parentNode) typingEl.parentNode.removeChild(typingEl);\n    typingEl = null;\n  }\n  function queueStoreReply(body, products, images, sender, rateId) { revealQ.push({ body: body, products: products || null, images: images || null, sender: sender, rateId: rateId || null }); drainReveal(); }\n  function drainReveal() {\n    if (revealing) return;\n    if (!revealQ.length) { hideTyping(); turnSpent = 0; turnFirst = true; return; }\n    revealing = true;\n    var item = revealQ.shift() || {};\n    var body = String(item.body || \"\");\n    var floor = turnFirst ? PACE_FIRST_MIN : PACE_MIN;\n    var delay = Math.max(floor, Math.min(PACE_MAX, PACE_BASE + body.length * PACE_PER_CHAR));\n    // Once the turn's time budget is spent, drop later bubbles to the floor so a\n    // long multi-bubble answer never drags past ~5s total.\n    if (turnSpent >= PACE_TURN_BUDGET) delay = floor;\n    delay = paceJitter(delay);\n    turnSpent += delay;\n    turnFirst = false;\n    showTyping();\n    setTimeout(function () {\n      hideTyping();\n      add(\"store\", body, item.sender || \"WNF\", item.products, item.images);\n      if (item.rateId) addRating(item.rateId);\n      revealing = false;\n      noteStoreBubble(item.sender, body);\n      if (!revealQ.length) afterAnswerDone();\n      if (revealQ.length) {\n        var gap = paceJitter(paceGap(body.length));\n        turnSpent += gap;\n        setTimeout(drainReveal, gap);\n      } else {\n        turnSpent = 0; turnFirst = true; drainReveal();\n      }\n    }, delay);\n  }\n\n  function scrollChatBottom() {\n    var scroller = bodyEl || log;\n    if (!scroller) return;\n    scroller.scrollTop = scroller.scrollHeight;\n    if (window.requestAnimationFrame) window.requestAnimationFrame(function () { scroller.scrollTop = scroller.scrollHeight; });\n  }\n  function chatNearBottom() {\n    var scroller = bodyEl || log;\n    if (!scroller) return true;\n    return scroller.scrollHeight - scroller.clientHeight - scroller.scrollTop < 48;\n  }\n  function startChat() {\n    if (started) return; started = true;\n    var w = welcomeMsg();\n    // If a proactive card already framed the conversation, keep ITS question as the\n    // context the customer replied to; otherwise the welcome is the opening line.\n    if (!lastPrompt) lastPrompt = w;\n    log.appendChild(storeIntro());\n    add(\"store\", w, ASSISTANT_NAME);\n    showQuickReplies();\n  }\n  // Trust line at the top of the thread (was a fixed footer that cost ~60px of every view).\n  function storeIntro() {\n    return el(\"div\", { class: \"wnf-intro\" },\n      '<span class=\"wnf-blz-lock\">' + (ASSETS.blzMark ? '<img class=\"wnf-blz-mark\" src=\"' + ASSETS.blzMark + '\" alt=\"Trail Blazers\">' : \"\") +\n      '<span class=\"wnf-blz-txt\">Official Trail Blazers<small>Small-Business Partner</small></span></span>' +\n      '<div class=\"wnf-since\">Family-owned in Portland since 2010</div>');\n  }\n  var qrEl = null;\n  function showQuickReplies() {\n    if (!log || !FAQS.length) return;\n    qrEl = el(\"div\", { class: \"wnf-qr\", role: \"group\", \"aria-label\": \"Quick questions\" });\n    FAQS.forEach(function (f) {\n      var b = el(\"button\", { type: \"button\" }); b.textContent = f.q;\n      b.onclick = function () { track(\"wnf_chat_faq\", { q: f.q, src: \"chip\" }); submit(f.q); };\n      qrEl.appendChild(b);\n    });\n    log.appendChild(qrEl);\n  }\n  function removeQuickReplies() { if (qrEl && qrEl.parentNode) qrEl.parentNode.removeChild(qrEl); qrEl = null; }\n\n  // ---- mobile keyboard-safe sheet --------------------------------------------\n  // The panel follows Safari's visual viewport rectangle. That avoids the iOS keyboard\n  // double-counting trap: the sheet moves to the viewport offset and shrinks to viewport\n  // height; the composer remains bottom:0 inside that rectangle.\n  function isMobileView() {\n    var coarse = false;\n    try { coarse = window.matchMedia && window.matchMedia(\"(pointer:coarse)\").matches; } catch (e) {}\n    return window.innerWidth <= 600 || (coarse && window.innerHeight <= 500 && window.innerWidth <= 950);\n  }\n  function isIOSLike() { return /iP(ad|hone|od)/.test(navigator.platform) || (navigator.platform === \"MacIntel\" && navigator.maxTouchPoints > 1); }\n  var vvRaf = null, vvLeftPad = \"\", vvTopPad = \"\", vvWidth = \"\", vvHeight = \"\", kbPrimed = false, kbPrimeTimer = null;\n  function hasKeyboardFocus() {\n    return !!(panel && panel.contains(document.activeElement) && /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement.tagName));\n  }\n  function clearViewportFit() {\n    if (!panel) return;\n    panel.style.removeProperty(\"--wnf-vv-left\");\n    panel.style.removeProperty(\"--wnf-vv-top\");\n    panel.style.removeProperty(\"width\");\n    panel.style.removeProperty(\"height\");\n    vvLeftPad = \"\";\n    vvTopPad = \"\";\n    vvWidth = \"\";\n    vvHeight = \"\";\n  }\n  function applyViewportFit(vv) {\n    if (!panel) return;\n    // Height-only, and ONLY while the soft keyboard is up. visualViewport.height shrinks for\n    // the keyboard (CSS 100dvh can't see that), so we pin the sheet to it then. With no\n    // keyboard we clear the inline height and let CSS 100dvh own it. We NEVER read offsetTop\n    // or set top/left/width: under the background scroll-lock iOS contaminates offsetTop, which\n    // is what flung the sheet off-screen / collapsed it before (see chat-mobile-keyboard-fix).\n    if (hasKeyboardFocus() || kbPrimed) {\n      var height = Math.round(Math.max((window.innerHeight || 600) * 0.4, vv.height || window.innerHeight || 0)) + \"px\";\n      if (height !== vvHeight) { panel.style.height = height; vvHeight = height; }\n    } else if (vvHeight) {\n      panel.style.removeProperty(\"height\"); vvHeight = \"\";\n    }\n  }\n  function holdPageStill() {\n    // No-op under the overflow:hidden lock: the background can't scroll, so there's nothing to\n    // re-pin. Kept as a stable call target for the keyboard-priming timers below.\n  }\n  function holdPageStillForKeyboard() {\n    holdPageStill();\n    setTimeout(holdPageStill, 60);\n    setTimeout(holdPageStill, 180);\n    setTimeout(holdPageStill, 360);\n    setTimeout(holdPageStill, 650);\n  }\n  function primeKeyboard() {\n    if (!panel || !panel.classList.contains(\"open\") || !isMobileView()) return;\n    kbPrimed = true;\n    if (kbPrimeTimer) clearTimeout(kbPrimeTimer);\n    syncVV();\n    holdPageStillForKeyboard();\n    kbPrimeTimer = setTimeout(function () {\n      kbPrimed = false;\n      syncVV();\n    }, 900);\n  }\n  function markKeyboardIntent() {\n    holdPageStillForKeyboard();\n  }\n  function maybeReleaseKeyboard() {\n    setTimeout(function () {\n      if (!panel || !panel.classList.contains(\"open\")) return;\n      if (panel.contains(document.activeElement) && /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement.tagName)) return;\n      kbPrimed = false;\n      if (kbPrimeTimer) { clearTimeout(kbPrimeTimer); kbPrimeTimer = null; }\n      syncVV();\n    }, 80);\n  }\n  function bindKeyboardInput(node) {\n    if (!node) return;\n    node.addEventListener(\"pointerdown\", markKeyboardIntent);\n    node.addEventListener(\"touchstart\", markKeyboardIntent, { passive: true });\n    node.addEventListener(\"focus\", function () {\n      primeKeyboard();\n      var f = PAGE_MODE ? syncPageVV : syncVV;\n      setTimeout(f, 80);\n      setTimeout(f, 320);\n      setTimeout(f, 700);\n    });\n    node.addEventListener(\"blur\", function () {\n      maybeReleaseKeyboard();\n      var f = PAGE_MODE ? syncPageVV : syncVV;\n      setTimeout(f, 160);\n      setTimeout(f, 360);\n    });\n  }\n  function syncVV() {\n    if (PAGE_MODE) return;          // page mode owns sizing via syncPageVV()\n    if (vvRaf) return;\n    vvRaf = (window.requestAnimationFrame || function (fn) { return setTimeout(fn, 16); })(function () {\n      vvRaf = null;\n      if (!panel) return;\n      if (!panel.classList.contains(\"open\") || !isMobileView()) {\n        clearViewportFit();\n        return;\n      }\n      var vv = window.visualViewport;\n      if (!vv) { clearViewportFit(); return; }\n      var atBottom = chatNearBottom();\n      applyViewportFit(vv);\n      holdPageStill();\n      if (atBottom || kbPrimed || hasKeyboardFocus()) scrollChatBottom();\n    });\n  }\n  var scrollLocked = false, lockY = 0, htmlOverflow = \"\", bodyOverflow = \"\";\n  function restorePageScroll() {\n    var y = lockY || 0;\n    window.scrollTo(0, y);\n    setTimeout(function () { window.scrollTo(0, y); }, 80);\n  }\n  // Block background scroll / rubber-band WITHOUT position:fixing the body \u2014 the old fixed-body\n  // lock is exactly what contaminated visualViewport.offsetTop and mis-sized the sheet. Touches\n  // inside the scrollable chat log (and on text inputs) pass through; everything else is\n  // prevented while the sheet is open.\n  function preventBgTouch(e) {\n    var t = e.target;\n    if (panel && panel.classList.contains(\"open\") && panel.contains(t)) {\n      var sc = bodyEl || panel.querySelector(\".wnf-body\");\n      if ((sc && sc.contains(t)) || /^(INPUT|TEXTAREA)$/.test(t.tagName)) return;\n    }\n    if (e.cancelable) e.preventDefault();\n  }\n  function lockScroll(on) {\n    if (on) {\n      if (!isMobileView() || scrollLocked) return;\n      scrollLocked = true;\n      lockY = window.scrollY || window.pageYOffset || 0;\n      htmlOverflow = document.documentElement.style.overflow;\n      bodyOverflow = document.body.style.overflow;\n      document.documentElement.style.overflow = \"hidden\";\n      document.body.style.overflow = \"hidden\";\n      document.addEventListener(\"touchmove\", preventBgTouch, { passive: false });\n    } else {\n      if (!scrollLocked) return;\n      scrollLocked = false;\n      document.documentElement.style.overflow = htmlOverflow;\n      document.body.style.overflow = bodyOverflow;\n      document.removeEventListener(\"touchmove\", preventBgTouch, { passive: false });\n      restorePageScroll();\n    }\n  }\n  // iOS auto-zooms toward an input focused inside a position:fixed surface even at 16px.\n  // While the mobile sheet is open we preserve the page viewport and append the stricter\n  // iOS zoom lock tokens, then restore only if no other script changed the meta meanwhile.\n  var vpMeta = null, vpOrig = null, vpApplied = null;\n  function setNoZoom(on) {\n    if (on && (!isMobileView() || !isIOSLike())) return;\n    vpMeta = vpMeta || document.querySelector('meta[name=\"viewport\"]');\n    if (!vpMeta) return;\n    if (on) {\n      if (vpOrig === null) vpOrig = vpMeta.getAttribute(\"content\") || \"\";\n      var base = vpOrig || \"width=device-width, initial-scale=1\";\n      base = base.replace(/\\s*,?\\s*(maximum-scale|user-scalable)\\s*=\\s*[^,]+/gi, \"\");\n      vpApplied = base.replace(/\\s*,\\s*,/g, \",\").replace(/^\\s*,|,\\s*$/g, \"\") + \", maximum-scale=1, user-scalable=no\";\n      vpMeta.setAttribute(\"content\", vpApplied);\n    } else if (vpOrig !== null) {\n      if ((vpMeta.getAttribute(\"content\") || \"\") === vpApplied) vpMeta.setAttribute(\"content\", vpOrig);\n      vpOrig = null;\n      vpApplied = null;\n    }\n  }\n  var pushedState = false, closingTimer = null;\n  function setLauncherModalHidden(hidden) {\n    var launchBtn = root && root.querySelector(\".wnf-launch\");\n    if (!launchBtn) return;\n    if (hidden) {\n      launchBtn.setAttribute(\"aria-hidden\", \"true\");\n      launchBtn.setAttribute(\"tabindex\", \"-1\");\n    } else {\n      launchBtn.removeAttribute(\"aria-hidden\");\n      launchBtn.removeAttribute(\"tabindex\");\n    }\n  }\n  function focusablePanelEls() {\n    if (!panel) return [];\n    var nodes = panel.querySelectorAll('button,[href],input,select,textarea,[tabindex]:not([tabindex=\"-1\"])');\n    var out = [];\n    Array.prototype.forEach.call(nodes, function (n) {\n      if (!n.disabled && n.offsetParent !== null && n.getAttribute(\"aria-hidden\") !== \"true\") out.push(n);\n    });\n    return out;\n  }\n  function closePanel(fromHistory) {\n    if (!panel) return;\n    var wasOpen = panel.classList.contains(\"open\");\n    if (!wasOpen && !panel.classList.contains(\"closing\")) return;\n    panel.classList.remove(\"open\");\n    if (closingTimer) { clearTimeout(closingTimer); closingTimer = null; }\n    if (wasOpen && isMobileView()) {\n      panel.classList.add(\"closing\");\n      closingTimer = setTimeout(function () { if (panel) panel.classList.remove(\"closing\"); closingTimer = null; }, 240);\n    } else {\n      panel.classList.remove(\"closing\");\n    }\n    if (kbPrimeTimer) { clearTimeout(kbPrimeTimer); kbPrimeTimer = null; }\n    kbPrimed = false;\n    clearViewportFit();\n    setLauncherModalHidden(false);\n    setNoZoom(false);\n    lockScroll(false);\n    if (!PAGE_MODE) stopPolling();\n    if (input) input.blur();\n    var launchBtn = root && root.querySelector(\".wnf-launch\");\n    if (launchBtn) try { launchBtn.focus({ preventScroll: true }); } catch (e) { }\n    if (!fromHistory && pushedState) {\n      pushedState = false;\n      try { history.back(); } catch (e) { }\n      restorePageScroll();\n    }\n    showMini(); // restore the subtle nudge after the panel closes\n  }\n  if (window.visualViewport) {\n    window.visualViewport.addEventListener(\"resize\", syncVV, { passive: true });\n    window.visualViewport.addEventListener(\"scroll\", syncVV, { passive: true });\n  }\n  window.addEventListener(\"orientationchange\", function () { setTimeout(syncVV, 60); setTimeout(syncVV, 300); }, { passive: true });\n  // Escape closes; Android hardware-back closes (we push one history entry on open).\n  document.addEventListener(\"keydown\", function (e) {\n    if (!panel || !panel.classList.contains(\"open\")) return;\n    if (e.key === \"Escape\") { closePanel(); return; }\n    if (e.key !== \"Tab\") return;\n    // Only trap Tab when the panel is a full-screen modal (mobile). On desktop the\n    // panel is a small corner box, so the storefront behind it must stay tabbable.\n    if (!isMobileView()) return;\n    var f = focusablePanelEls();\n    if (!f.length) { e.preventDefault(); panel.focus(); return; }\n    var first = f[0], last = f[f.length - 1];\n    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n  });\n  document.addEventListener(\"focusin\", function (e) {\n    // Focus-trap ONLY while the panel is a full-screen modal (mobile). On desktop the\n    // panel is a corner widget \u2014 yanking focus back froze the page (no clicking, no\n    // keyboard scroll on the storefront behind it).\n    if (!isMobileView()) return;\n    if (panel && panel.classList.contains(\"open\") && !panel.contains(e.target)) {\n      var f = focusablePanelEls();\n      (f[0] || panel).focus();\n    }\n  });\n  window.addEventListener(\"popstate\", function () {\n    if (panel && panel.classList.contains(\"open\")) { pushedState = false; closePanel(true); }\n  });\n  document.addEventListener(\"visibilitychange\", function () {\n    if (document.hidden) stopPolling();\n    else if (started && (PAGE_MODE || (panel && panel.classList.contains(\"open\")))) startPolling();\n  });\n\n  function openPanel(view, src, intent) {\n    dismissPop();\n    hideMini();\n    if (!panel) buildPanel();\n    if (closingTimer) { clearTimeout(closingTimer); closingTimer = null; }\n    panel.classList.remove(\"closing\");\n    panel.classList.add(\"open\");\n    setNoZoom(true);\n    lockScroll(true);\n    setLauncherModalHidden(true);\n    if (isMobileView() && !pushedState) { try { history.pushState({ wnfChat: 1 }, \"\"); pushedState = true; } catch (e) { } }\n\t    if (!opened) { opened = true; var op = { host: host.name, mode: \"panel\", src: src || \"other\" }; if (intent) op.intent = intent; track(\"wnf_chat_open\", op); }\n\t    switchTab(view === \"faq\" ? \"faq\" : \"chat\");\n    if (view !== \"faq\") startPolling();\n\t    syncVV();\n    // On phones, don't auto-pop the keyboard \u2014 opening a clean full-screen sheet feels\n    // native and avoids the focus-scroll jump; the user taps the input to type.\n    if (view !== \"faq\" && input && !isMobileView()) input.focus();\n    else if (isMobileView()) try { panel.focus({ preventScroll: true }); } catch (e) { panel.focus(); }\n  }\n\n  // ---- mobile \u2192 dedicated full page ------------------------------------------\n  // On phones, route every \"open chat\" (launcher, mini bubble, dark card, public\n  // hook) to the standalone /pages/chat document instead of the overlay. Falls back\n  // to the corner panel when chatPage isn't configured or on desktop.\n  function shouldUseChatPage() {\n    return !PAGE_MODE && !!CFG.chatPage && isMobileView();\n  }\n  function openChat(view, src) {\n    if (shouldUseChatPage()) return goToChatPage(view, undefined, src);\n    openPanel(view, src);\n  }\n  // extra (optional): { ask: \"question to send once on arrival\", intent: \"photo\", src: \"sheet\" }.\n  // Without extra the stash and URL are exactly what they were before.\n  // openSrc (optional): where the open came from (launcher, mini, card, cta, sheet) for the canonical wnf_chat_open.\n  function goToChatPage(view, extra, openSrc) {\n    var v = view === \"faq\" ? \"faq\" : \"chat\";\n    // Stash the originating page's full context so the chat page restores it\n    // (greeting, FAQs, staff/AI page-context) and knows where the X returns to.\n    try {\n      var stash = {\n        page: CFG.page || PAGE,\n        view: v,\n        returnUrl: location.pathname + location.search + location.hash,\n        returnTitle: (document.title || \"\").slice(0, 120)\n      };\n      if (extra && extra.ask) stash.ask = String(extra.ask).slice(0, 300);\n      if (extra && extra.intent === \"photo\") stash.intent = \"photo\";\n      if (extra && extra.src) stash.src = String(extra.src).slice(0, 20);\n      ss(\"wnf_chat_launch\", JSON.stringify(stash));\n    } catch (e) {}\n    track(\"wnf_chat_page_nav\", extra && extra.src ? { view: v, src: extra.src } : { view: v });\n    var op = { host: host.name, mode: \"page\", src: openSrc || (extra && extra.src) || \"other\", view: v };\n    if (extra && extra.intent === \"photo\") op.intent = \"photo\";\n    track(\"wnf_chat_open\", op);\n    var url = CFG.chatPage;\n    if (v === \"faq\") url += (url.indexOf(\"?\") >= 0 ? \"&\" : \"?\") + \"v=faq\";\n    if (extra && extra.intent === \"photo\") url += (url.indexOf(\"?\") >= 0 ? \"&\" : \"?\") + \"intent=photo\";\n    location.href = url;\n  }\n  function leaveChatPage() {\n    track(\"wnf_chat_page_close\", { page: copyKey() });\n    // A real navigation got us here, so the previous storefront page is one step\n    // back \u2014 history.back restores it (and its scroll position via bfcache). Deep\n    // link / no history \u2192 fall back to the stashed return URL, then home.\n    if (window.history && history.length > 1) { try { history.back(); return; } catch (e) {} }\n    location.href = LAUNCH_RETURN || \"/\";\n  }\n\n  // ---- page-mode boot (the dedicated /pages/chat host) -----------------------\n  // Renders the SAME panel into #wnf-chat-page as a normal in-flow full-screen\n  // surface (no fixed overlay, no scroll-lock). The only viewport JS is a height\n  // sync from visualViewport \u2014 safe here because nothing locks the body, so\n  // visualViewport never gets the offsetTop contamination that broke the sheet.\n  var PAGE_CSS =\n    // The shell is sized to window.visualViewport (NOT 100dvh) and follows offsetTop.\n    // On iOS the keyboard shrinks ONLY the visual viewport \u2014 100dvh and position:fixed\n    // both ignore it, which is why the old fixed/100dvh host got dragged away and let the\n    // page behind show through. height:var(--wnf-vvh) + translateY(var(--wnf-vvoff)) keeps\n    // the shell exactly over the visible area so the composer always rides above the keyboard.\n    \".wnf-page-host{position:fixed;top:0;left:0;width:100%;height:100vh;height:100dvh;height:var(--wnf-vvh,100dvh);transform:translateY(var(--wnf-vvoff,0px));display:flex;flex-direction:column;background:#FFFAED;z-index:2147483000;font:14px/1.5 Futura,'Futura PT','Jost','Trebuchet MS',Arial,sans-serif;-webkit-text-size-adjust:100%;text-size-adjust:100%;-webkit-tap-highlight-color:transparent;will-change:height}\" +\n    \".wnf-page-host *{box-sizing:border-box}\" +\n    \".wnf-page-host button,.wnf-page-host input,.wnf-page-host a{touch-action:manipulation}\" +\n    \".wnf-page-host input,.wnf-page-host textarea{font-size:16px}\" +\n    // override every overlay/@media .wnf-panel rule: in page mode it's a static, full-host flex column\n    \".wnf-page-host .wnf-panel{position:static;display:flex;flex:1 1 auto;width:100%;max-width:none;height:auto;max-height:none;min-height:0;border-radius:0;box-shadow:none;transform:none;animation:none}\" +\n    \".wnf-page-host .wnf-body{padding-bottom:0;scroll-padding-bottom:12px}\" +\n    \".wnf-page-host .wnf-ft{position:static;padding-bottom:calc(11px + env(safe-area-inset-bottom))}\" +\n    \".wnf-page-host .wnf-hd{padding-top:calc(11px + env(safe-area-inset-top))}\" +\n    \".wnf-page-host .wnf-hdbtn{width:44px;height:44px}\";\n  var pageVVRaf = null;\n  function syncPageVV() {\n    if (!PAGE_MODE || !root) return;\n    if (pageVVRaf) return;\n    pageVVRaf = (window.requestAnimationFrame || function (fn) { return setTimeout(fn, 16); })(function () {\n      pageVVRaf = null;\n      if (!root) return;\n      var vv = window.visualViewport;\n      var h = vv && vv.height ? vv.height : (window.innerHeight || 0);\n      var off = vv ? vv.offsetTop : 0;\n      // Drive the shell from the VISUAL viewport: height tracks the keyboard (visual\n      // viewport shrinks on iOS), translateY tracks Safari's keyboard-pan (offsetTop).\n      // This is the only signal iOS exposes for the keyboard; both resize AND scroll\n      // events feed it (scroll fires as offsetTop drifts). The composer is a normal-flow\n      // flex child at the bottom, so it always lands just above the keyboard.\n      if (h) root.style.setProperty(\"--wnf-vvh\", Math.round(h) + \"px\");\n      root.style.setProperty(\"--wnf-vvoff\", Math.round(off) + \"px\");\n      if (hasKeyboardFocus()) scrollChatBottom();\n      if (DEBUG_KBD) updateDbg();\n    });\n  }\n  var dbgEl = null;\n  function initDbg() {\n    if (dbgEl) return;\n    dbgEl = el(\"div\", { style: \"position:fixed;top:0;left:0;right:0;z-index:2147483646;background:rgba(180,0,0,.92);color:#fff;font:11px/1.35 monospace;padding:6px 8px;white-space:pre-wrap;pointer-events:none\" });\n    document.body.appendChild(dbgEl);\n    updateDbg();\n    setInterval(updateDbg, 250);\n  }\n  function updateDbg() {\n    if (!dbgEl) return;\n    var vv = window.visualViewport;\n    var ft = panel && panel.querySelector(\".wnf-ft\");\n    var cmpB = ft ? Math.round(ft.getBoundingClientRect().bottom) : \"?\";\n    var ae = document.activeElement;\n    dbgEl.textContent =\n      \"iH=\" + window.innerHeight + \" vvH=\" + (vv ? Math.round(vv.height) : \"?\") + \" vvTop=\" + (vv ? Math.round(vv.offsetTop) : \"?\") +\n      \"\\n--vvh=\" + (root ? root.style.getPropertyValue(\"--wnf-vvh\") : \"?\") + \" hostH=\" + (root ? root.clientHeight : \"?\") +\n      \" composerBottom=\" + cmpB +\n      \"\\nfocus=\" + (ae ? (ae.tagName + \".\" + (ae.className || \"\").toString().slice(0, 18)) : \"none\");\n  }\n  function bootPage() {\n    if (booted) return; booted = true;\n    var style = el(\"style\"); style.textContent = CSS + PAGE_CSS; document.head.appendChild(style);\n    root = PAGE_HOST;\n    // Re-parent the host to <body> so it escapes the theme's section wrapper \u2014 Motion's\n    // animate_sections sets that wrapper to opacity:0 (and a translate) until its reveal\n    // fires, which would otherwise dim/mis-anchor our fixed chat. (Same reason the live\n    // corner widget appends straight to document.body.)\n    if (root.parentNode !== document.body) document.body.appendChild(root);\n    root.className = (root.className ? root.className + \" \" : \"\") + \"wnf-page-host\" + (OPEN ? \"\" : \" wnf--closed\");\n    // Lock the document to the viewport so nothing scrolls/rubber-bands behind the shell\n    // (on the standalone page there's nothing behind it anyway, but this prevents any\n    // Safari pan from exposing blank space below).\n    try {\n      document.documentElement.style.height = \"100%\";\n      document.documentElement.style.overflow = \"hidden\";\n      document.body.style.height = \"100%\";\n      document.body.style.margin = \"0\";\n      document.body.style.overflow = \"hidden\";\n      document.body.style.overscrollBehavior = \"none\";\n    } catch (e) {}\n    buildPanel();                       // appends the panel into root (= the page host)\n    panel.classList.add(\"open\");\n    switchTab(LAUNCH_ASK ? \"chat\" : (LAUNCH_VIEW === \"faq\" ? \"faq\" : \"chat\"));\n    arriveWithIntent();\n    if (window.visualViewport) {\n      window.visualViewport.addEventListener(\"resize\", syncPageVV, { passive: true });\n      window.visualViewport.addEventListener(\"scroll\", syncPageVV, { passive: true });\n    }\n    window.addEventListener(\"orientationchange\", function () { setTimeout(syncPageVV, 60); setTimeout(syncPageVV, 300); }, { passive: true });\n    // iOS 18/26 regression: visualViewport.offsetTop can stay >0 after the keyboard\n    // dismisses, leaving the shell shifted. A 1px scroll nudge re-seats it.\n    document.addEventListener(\"focusout\", function () {\n      setTimeout(function () {\n        var vv = window.visualViewport;\n        if (vv && vv.offsetTop > 0) { try { window.scrollBy(0, -1); window.scrollBy(0, 1); } catch (e) {} }\n        syncPageVV();\n      }, 100);\n    });\n    syncPageVV();\n    if (DEBUG_KBD) initDbg();\n    if (!opened) { opened = true; if (!LAUNCH_STASHED) track(\"wnf_chat_open\", { host: host.name, mode: \"page\", src: \"direct\" }); }\n    track(\"wnf_chat_exposure\", { host: host.name, mode: \"page\" });\n  }\n\n  // ---- arrival intents: a tapped question, a photo picked on the storefront ----\n  // The storefront stashes these before navigating to the full-page chat (phones).\n  var PHOTO_KEY = \"wnf_chat_photos\";\n  function photoCaption() { return \"Here's a photo of my room. Will it fit?\"; }\n  function dataUrlToBlob(d) {\n    var parts = String(d).split(\",\"), bin = atob(parts[1] || \"\"), n = bin.length, u8 = new Uint8Array(n);\n    for (var i = 0; i < n; i++) u8[i] = bin.charCodeAt(i);\n    return new Blob([u8], { type: \"image/jpeg\" });\n  }\n  // Photos picked on the storefront arrive staged in the composer (not sent): the\n  // shopper sees exactly what will go and taps Send, as with any other photo.\n  function restoreStashedPhotos() {\n    var list = null;\n    try { list = JSON.parse(ss(PHOTO_KEY) || \"null\"); } catch (e) {}\n    try { sessionStorage.removeItem(PHOTO_KEY); } catch (e) {}\n    if (!Array.isArray(list) || !list.length) return false;\n    list.slice(0, MAX_ATTS).forEach(function (p) {\n      if (!p || typeof p.d !== \"string\" || p.d.indexOf(\"data:image/jpeg;base64,\") !== 0) return;\n      try { pendingImgs.push({ blob: dataUrlToBlob(p.d), mime: \"image/jpeg\", w: +p.w || 0, h: +p.h || 0, previewUrl: p.d }); } catch (e) {}\n    });\n    if (!pendingImgs.length) return false;\n    renderAtts();\n    if (input && !input.value) input.value = photoCaption();\n    syncSend();\n    return true;\n  }\n  // \"Send a photo of your room\" card in the conversation. Its button opens the picker\n  // directly (a real tap), so no extra step is hidden behind the camera icon.\n  function showPhotoPrompt() {\n    if (!log || log.querySelector(\".wnf-pcta\")) return;\n    var card = el(\"div\", { class: \"wnf-pcta\" },\n      '<p class=\"wnf-pcta__t\">Send a photo of your room</p>' +\n      '<p class=\"wnf-pcta__s\">A person from our Portland team looks at every photo.</p>' +\n      '<button class=\"wnf-pcta__go\" type=\"button\">' + CLIP_SVG + ' Choose a photo</button>');\n    card.querySelector(\".wnf-pcta__go\").onclick = function () {\n      track(\"wnf_chat_photo_pick\", { src: \"prompt\" });\n      var f = panel && panel.querySelector(\".wnf-file\"); if (f) f.click();\n    };\n    log.appendChild(card); scrollChatBottom();\n  }\n  function arriveWithIntent() {\n    if (LAUNCH_ASK) {\n      var q = LAUNCH_ASK; LAUNCH_ASK = \"\";\n      nextMsgSrc = LAUNCH_SRC || \"ask\";\n      setTimeout(function () { submit(q); }, 450); // let the welcome land first\n      return;\n    }\n    var staged = restoreStashedPhotos();\n    if (!staged && LAUNCH_INTENT === \"photo\") showPhotoPrompt();\n    if (staged) nextMsgSrc = \"photo\";\n  }\n  var nextMsgSrc = \"\";\n\n  function submit(text) {\n    text = (text || \"\").trim();\n    var imgs = pendingImgs.slice();\n    if (!text && !imgs.length) return;\n    if (!panel || !panel.classList.contains(\"open\")) { openPanel(\"chat\"); }\n    switchTab(\"chat\");\n    pendingImgs = []; renderAtts();\n    // Optimistically show the customer's own bubble (text + local thumbnails) now.\n    add(\"you\", text, null, null, imgs.map(function (a) { return { url: a.previewUrl, w: a.w, h: a.h }; }));\n    input.value = \"\"; syncSend();\n    showTyping();\n    if (text) {\n      turnNo++;\n      if (TYPED_CONTACT_RE.test(text)) ls(ASKED_KEY, \"typed\"); // they gave it already: never ask\n    }\n    var mp = { host: host.name, has_image: !!imgs.length };\n    if (nextMsgSrc) { mp.src = nextMsgSrc; nextMsgSrc = \"\"; }\n    track(\"wnf_chat_message\", mp);\n    if (imgs.length) photoTurn = true;\n    if (imgs.length) uploadThenSend(text, imgs, 0);\n    else sendToApi(text, 0, null);\n  }\n  // Upload each pending photo to the private bucket, then send the message carrying\n  // the returned attachment paths. A failed upload is skipped; if nothing survives\n  // and there's no text either, we surface a retry nudge instead of an empty send.\n  function uploadThenSend(text, imgs, tries) {\n    var results = [], pending = imgs.length;\n    imgs.forEach(function (a) {\n      var fd = new FormData();\n      fd.append(\"sessionId\", sessionId);\n      fd.append(\"file\", a.blob, \"photo.jpg\");\n      fd.append(\"width\", String(a.w)); fd.append(\"height\", String(a.h));\n      fetch(API + \"/api/chat/upload\", { method: \"POST\", body: fd })\n        .then(function (r) { if (!r.ok) throw new Error(r.status); return r.json(); })\n        .then(function (d) { if (d && d.path) results.push({ path: d.path, mime: d.mime, width: d.width, height: d.height }); })\n        .catch(function () {})\n        .then(function () {\n          if (--pending > 0) return;\n          if (results.length !== imgs.length) {\n            hideTyping();\n            pendingImgs = imgs; renderAtts(); input.value = text; syncSend();\n            add(\"store\", \"A photo didn't upload, so I haven't sent this message. Your text and photos are ready to try again.\", \"WNF\");\n            return;\n          }\n          sendToApi(text, 0, results);\n        });\n    });\n  }\n  function sendToApi(text, tries, attachments) {\n    var pc = pageContext();\n    var body = { sessionId: sessionId, message: text, page: copyKey(), pageUrl: pc.url, pageTitle: pc.title, pageMeta: pc.meta, device: isMobileView() ? \"mobile\" : \"desktop\" };\n    if (attachments && attachments.length) body.attachments = attachments;\n    // Send the assistant line the customer saw with their FIRST message only, so the\n    // backend records it as the thread's opening turn (staff context). Once-only.\n    if (!promptSent && lastPrompt) body.precedingPrompt = String(lastPrompt).slice(0, 2000);\n    // If we already know who this visitor is (logged-in Shopify customer, or contact\n    // saved from a prior chat), send it WITH the message so the backend has it before\n    // the AI drafts \u2014 otherwise the contact card only posts AFTER this round-trip and\n    // the bot re-asks for an email/phone we already have. Fill-empty-only server-side.\n    var kc = knownContact();\n    if (kc && (kc.email || kc.phone || kc.name)) body.contact = { name: kc.name || \"\", email: kc.email || \"\", phone: kc.phone || \"\" };\n    fetch(API + \"/api/chat\", { method: \"POST\", headers: { \"content-type\": \"text/plain\" }, body: JSON.stringify(body) })\n      .then(function (r) {\n        // 429 = rate limited. Read the body for the server's customer-safe copy and\n        // hand it to the .then below as a terminal outcome \u2014 throwing here would hit\n        // the generic catch, which RETRIES after 900ms and makes the throttle worse.\n        if (r.status === 429) return r.json().catch(function () { return {}; }).then(function (d) {\n          return { status: \"rate_limited\", message: d && d.message };\n        });\n        if (!r.ok) throw new Error(r.status);\n        return r.json();\n      })\n      .then(function (d) {\n        if (d && d.status === \"rate_limited\") {\n          hideTyping();\n          add(\"store\", d.message || \"You're sending messages faster than we can read them. Give it a moment and try again, or call us at (503) 235-3454 if it's urgent.\", \"WNF\");\n          return;\n        }\n        promptSent = true;\n        if (d && d.messageId) seenIds[d.messageId] = 1; // our own message \u2014 never re-render from poll\n        // Auto-answered replies are persisted server-side as message rows and are\n        // delivered (paced, one bubble at a time) by the poll below. Rendering\n        // d.reply here too would show the answer twice \u2014 once as a single combined\n        // bubble, then again as the paced split bubbles (the \"double messages\" bug).\n        // So for an answered turn we only show the typing indicator now (snappy\n        // feel) and let the poll reveal it. The pending-human holding line has no\n        // server row, so it's rendered here as before.\n        if (d.status === \"answered\") { showTyping(); setTimeout(function () { if (!revealing && !revealQ.length) hideTyping(); }, 12000); }\n        else { hideTyping(); add(\"store\", \"Your question is in the team's queue. You can keep browsing. Leave an email or phone if you'd like a reply after you leave.\", \"WNF\"); }\n        if (d.status !== \"answered\" || d.followUpRequired) maybeContact(\"handoff\");\n        // Automated answer: ask once it has landed (the moment of value). The 9/4\n        // release had stopped asking on these turns entirely (all devices).\n        else { contactAfterAnswer = true; answerBuf = \"\"; }\n        pokePoll(); // the paced reply (or a teammate) lands via the poll \u2014 check back soon\n      })\n      .catch(function () {\n        hideTyping();\n        // A lost response can follow a successful write. Never silently POST twice.\n        add(\"store\", \"I couldn't confirm that your message went through. Check for a reply before sending it again, or call the store at (503) 235-3454.\", \"WNF\");\n        pokePoll();\n      });\n  }\n\n  // ---- contact capture (after first message; email OR phone so we can reply) --\n  function validEmail(s) { return /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(s); }\n  function validPhone(s) { return String(s).replace(/\\D/g, \"\").length >= 7; }\n  function postContact(obj) {\n    var payload = { sessionId: sessionId, name: obj.name || \"\", email: obj.email || \"\", phone: obj.phone || \"\" };\n    if (obj.sendCopy === true) payload.sendCopy = true; // backend \"email me a copy\" (MX.emailCopy)\n    return fetch(API + \"/api/chat/contact\", {\n      method: \"POST\", headers: { \"content-type\": \"text/plain\" },\n      body: JSON.stringify(payload)\n    }).then(function (r) { if (!r.ok) throw new Error(\"contact_save_failed\"); return r.json().catch(function () { return {}; }); });\n  }\n  // Known-contact for this visitor, in priority order: a logged-in Shopify customer\n  // (CFG.customer, injected by the loader) \u2192 a contact they typed earlier (localStorage).\n  function knownContact() {\n    var c = CFG.customer;\n    if (c && (c.email || c.phone)) return { name: c.name || \"\", email: c.email || \"\", phone: c.phone || \"\" };\n    var saved = ls(\"wnf_contact\");\n    if (saved) { try { return JSON.parse(saved); } catch (e) {} }\n    return null;\n  }\n  // If we already know who they are (Shopify login or a prior chat) \u2014 don't ask;\n  // just attach it silently so staff can reply. Otherwise show the ask card once.\n  function maybeContact(kind) {\n    if (contactSent) return;\n    // A skip lasts for this browser tab, not every future visit on this device.\n    try { if (sessionStorage.getItem(\"wnf_contact_skip:\" + sessionId) === \"1\") return; } catch (e) {}\n    var known = knownContact();\n    if (known) { postContact(known).then(function () { contactSent = true; }).catch(function () {}); return; }\n    if (askedContact || ls(ASKED_KEY)) return;\n    askedContact = true; ls(ASKED_KEY, \"1\");\n    if (mxArm() === \"sheet\") addContactAsk(kind === \"answer\" ? \"answer\" : \"handoff\");\n    else addContactCard(kind === \"answer\" ? \"answer\" : \"handoff\");\n  }\n  // Sheet arm: one field, asked at the moment it is worth something, promising only\n  // what actually happens. \"handoff\" = a person will answer this thread (staff reply\n  // is emailed to the saved address: threads.emailCustomerReply). \"answer\" = after\n  // an automated answer; with MX.emailCopy the backend emails a copy of the answer.\n  function addContactAsk(kind) {\n    var copy = kind === \"answer\"\n      ? (MX.emailCopy\n        ? { t: \"Want a copy of this?\", s: \"I'll email it to you, handy for measuring at home or your showroom visit.\", ph: \"Your email\", go: \"Email it\", emailOnly: true }\n        : { t: \"Want the team's follow-up by email?\", s: \"If Joey or the team adds anything, it goes straight to your inbox.\", ph: \"Your email\", go: \"Save\", emailOnly: true })\n      : { t: \"Where should we send the team's reply?\", s: (photoTurn ? \"A person from our Portland team will look at your photo and answer here.\" : \"A person from our Portland team will answer here.\") + \" Add your email and their reply comes to your inbox too.\", ph: \"Email or phone\", go: \"Send\", emailOnly: false };\n    var card = el(\"div\", { class: \"wnf-cc2\", role: \"group\", \"aria-label\": copy.t });\n    card.innerHTML =\n      '<p class=\"wnf-cc2__t\">' + esc(copy.t) + '</p><p class=\"wnf-cc2__s\">' + esc(copy.s) + '</p>' +\n      '<div class=\"wnf-cc2__row\"><input class=\"wnf-cc2__in\" type=\"text\" inputmode=\"email\" autocomplete=\"email\" autocapitalize=\"none\" autocorrect=\"off\" spellcheck=\"false\" enterkeyhint=\"send\" aria-label=\"' + esc(copy.ph) + '\" placeholder=\"' + esc(copy.ph) + '\">' +\n      '<button class=\"wnf-cc2__go\" type=\"button\">' + esc(copy.go) + '</button></div>' +\n      '<p class=\"wnf-cc2__err\" role=\"alert\" hidden></p>' +\n      '<button class=\"wnf-cc2__no\" type=\"button\">No thanks</button>';\n    log.appendChild(card); scrollChatBottom();\n    track(\"wnf_chat_contact_shown\", { kind: kind, format: \"v2\" });\n    var inp = card.querySelector(\".wnf-cc2__in\"), go = card.querySelector(\".wnf-cc2__go\"), err = card.querySelector(\".wnf-cc2__err\");\n    bindKeyboardInput(inp);\n    go.addEventListener(\"mousedown\", function (e) { e.preventDefault(); }); // keep the keyboard up (same as Send)\n    inp.oninput = function () { err.hidden = true; inp.removeAttribute(\"aria-invalid\"); };\n    inp.addEventListener(\"keydown\", function (e) { if (e.key === \"Enter\") { e.preventDefault(); save(); } });\n    card.querySelector(\".wnf-cc2__no\").onclick = function () {\n      try { sessionStorage.setItem(\"wnf_contact_skip:\" + sessionId, \"1\"); } catch (e) {}\n      track(\"wnf_chat_contact_skip\", { kind: kind, format: \"v2\" });\n      if (card.parentNode) card.parentNode.removeChild(card);\n    };\n    go.onclick = save;\n    function save() {\n      var v = inp.value.trim(), isEmail = validEmail(v), isPhone = !isEmail && !copy.emailOnly && validPhone(v) && !/[a-z@]/i.test(v);\n      if (!isEmail && !isPhone) {\n        err.textContent = copy.emailOnly ? \"Add an email address so we can send it.\" : \"Add an email or phone so the team can reach you.\";\n        err.hidden = false; inp.setAttribute(\"aria-invalid\", \"true\"); scrollChatBottom(); return;\n      }\n      var obj = { name: \"\", email: isEmail ? v : \"\", phone: isPhone ? v : \"\" };\n      if (kind === \"answer\" && MX.emailCopy) obj.sendCopy = true;\n      go.disabled = true;\n      postContact(obj).then(function (res) {\n        ls(\"wnf_contact\", JSON.stringify({ name: \"\", email: obj.email, phone: obj.phone })); contactSent = true;\n        track(\"wnf_chat_contact_saved\", { has_email: !!obj.email, has_phone: !!obj.phone, kind: kind, format: \"v2\", copy: (res && res.copy) || \"\" });\n        if (card.parentNode) card.parentNode.removeChild(card);\n        var msg = kind === \"answer\"\n          ? (obj.sendCopy && res && res.copy === \"sent\" ? \"Sent. Check your inbox.\" : \"Saved. If Joey or the team adds anything, it'll come to your inbox.\")\n          : (obj.email ? \"Saved. The team's reply will come to your inbox too.\" : \"Saved. The team can reach you at that number.\");\n        add(\"store\", msg, \"WNF\");\n      }).catch(function () {\n        go.disabled = false; err.textContent = \"That didn't save. Please try again.\"; err.hidden = false;\n      });\n    }\n  }\n  function addContactCard(kind) {\n    var card = el(\"div\", { class: \"wnf-cc\" });\n    card.innerHTML =\n      '<div class=\"wnf-cc__t\">Where should the team reach you if you step away?</div>' +\n      '<input class=\"wnf-cc__in\" data-f=\"name\" type=\"text\" placeholder=\"Name (optional)\" aria-label=\"Name optional\" autocomplete=\"name\">' +\n      '<input class=\"wnf-cc__in\" data-f=\"email\" type=\"email\" placeholder=\"Email\" aria-label=\"Email\" autocomplete=\"email\" inputmode=\"email\" autocapitalize=\"none\" autocorrect=\"off\" spellcheck=\"false\" aria-describedby=\"wnf-cc-err\">' +\n      '<input class=\"wnf-cc__in\" data-f=\"phone\" type=\"tel\" placeholder=\"Phone (optional)\" aria-label=\"Phone optional\" autocomplete=\"tel\" inputmode=\"tel\" aria-describedby=\"wnf-cc-err\">' +\n      '<div class=\"wnf-cc__err\" id=\"wnf-cc-err\" role=\"alert\" hidden>Add an email or phone so we can reply.</div>' +\n      '<div class=\"wnf-cc__row\"><button class=\"wnf-cc__send\" type=\"button\">Send</button><button class=\"wnf-cc__skip\" type=\"button\">Skip</button></div>';\n    log.appendChild(card); scrollChatBottom();\n    track(\"wnf_chat_contact_shown\", { kind: kind, format: \"v1\" });\n    function val(f) { return card.querySelector('[data-f=\"' + f + '\"]').value.trim(); }\n    var err = card.querySelector(\".wnf-cc__err\");\n    function clearErr() {\n      err.hidden = true;\n      card.querySelector('[data-f=\"email\"]').removeAttribute(\"aria-invalid\");\n      card.querySelector('[data-f=\"phone\"]').removeAttribute(\"aria-invalid\");\n    }\n    card.querySelector('[data-f=\"email\"]').oninput = clearErr;\n    card.querySelector('[data-f=\"phone\"]').oninput = clearErr;\n    bindKeyboardInput(card.querySelector('[data-f=\"name\"]'));\n    bindKeyboardInput(card.querySelector('[data-f=\"email\"]'));\n    bindKeyboardInput(card.querySelector('[data-f=\"phone\"]'));\n    card.querySelector(\".wnf-cc__skip\").onclick = function () {\n      try { sessionStorage.setItem(\"wnf_contact_skip:\" + sessionId, \"1\"); } catch (e) {}\n      track(\"wnf_chat_contact_skip\", { kind: kind, format: \"v1\" });\n      if (card.parentNode) card.parentNode.removeChild(card);\n    };\n    card.querySelector(\".wnf-cc__send\").onclick = function () {\n      var email = val(\"email\"), phone = val(\"phone\"), name = val(\"name\");\n      if (!((email && validEmail(email)) || (phone && validPhone(phone)))) {\n        err.hidden = false;\n        card.querySelector('[data-f=\"email\"]').setAttribute(\"aria-invalid\", \"true\");\n        card.querySelector('[data-f=\"phone\"]').setAttribute(\"aria-invalid\", \"true\");\n        scrollChatBottom();\n        return;\n      }\n      var obj = { name: name, email: email, phone: phone };\n      var saveButton = card.querySelector(\".wnf-cc__send\");\n      saveButton.disabled = true;\n      postContact(obj).then(function () {\n        ls(\"wnf_contact\", JSON.stringify(obj)); contactSent = true;\n        track(\"wnf_chat_contact_saved\", { has_email: !!email, has_phone: !!phone, kind: kind, format: \"v1\" });\n        if (card.parentNode) card.parentNode.removeChild(card);\n        add(\"store\", \"Your contact details are saved with this chat.\", \"WNF\");\n      }).catch(function () {\n        saveButton.disabled = false;\n        err.textContent = \"Those details didn't save. Please try again.\";\n        err.hidden = false;\n      });\n    };\n    // Focus only on a hand-off (they are waiting); after an answer they may be typing.\n    var emailEl = card.querySelector('[data-f=\"email\"]'); if (emailEl && !isMobileView() && kind !== \"answer\") emailEl.focus();\n  }\n  function poll() {\n    if (!pollActive) return;\n    if (document.hidden) { stopPolling(); return; }\n    var url = API + \"/api/chat/messages?sessionId=\" + encodeURIComponent(sessionId) + (lastAt ? \"&since=\" + encodeURIComponent(lastAt) : \"\");\n    fetch(url).then(function (r) { return r.json(); }).then(function (d) {\n      var got = 0;\n      (d.messages || []).forEach(function (m) {\n        // Dedupe by stable id so a reply renders at most once \u2014 across overlapping\n        // polls AND the full-thread refetch on each page load (the 4\u00D7-copies bug).\n        if (m.id) { if (seenIds[m.id]) { lastAt = m.at; return; } seenIds[m.id] = 1; }\n        if (m.from === \"store\") {\n          // Pace only FRESH replies (a real teammate just answered). Older messages\n          // \u2014 e.g. the full-thread refetch on a page reload \u2014 render instantly so we\n          // don't replay history through the typing animation.\n          var fresh = false;\n          try { fresh = (Date.now() - new Date(m.at).getTime()) < 45000; } catch (e) {}\n          var sender = m.sender === \"team\" ? \"WNF team\" : m.sender === \"assistant\" ? ASSISTANT_NAME : \"WNF\";\n          var rateId = m.rateable ? m.id : null;\n          if (fresh) queueStoreReply(m.body, m.products, m.images, sender, rateId);\n          else { add(\"store\", m.body, sender, m.products, m.images); if (rateId) addRating(rateId); noteStoreBubble(sender, m.body); }\n        }\n        lastAt = m.at;\n        got++;\n      });\n      if (!revealing && !revealQ.length) afterAnswerDone();\n      emptyPolls = got ? 0 : emptyPolls + 1;\n      pollDelay = got ? 5000 : Math.min(30000, 5000 * Math.pow(2, Math.min(emptyPolls, 3)));\n    }).catch(function () {\n      pollDelay = Math.min(30000, pollDelay * 2);\n    }).then(schedulePoll);\n  }\n  function schedulePoll() {\n    if (!pollActive || pollTimer) return;\n    pollTimer = setTimeout(function () { pollTimer = null; poll(); }, pollDelay);\n  }\n  // After the customer sends, check back quickly for a beat so a fast teammate\n  // reply lands promptly instead of waiting out the current (backed-off) interval.\n  // The normal backoff resumes on the next empty poll.\n  function pokePoll() {\n    if (!pollActive) return;\n    emptyPolls = 0; pollDelay = 1800;\n    if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }\n    schedulePoll();\n  }\n  function startPolling() {\n    if (pollActive) return;\n    pollActive = true;\n    pollDelay = 5000;\n    emptyPolls = 0;\n    poll();\n  }\n  function stopPolling() {\n    pollActive = false;\n    if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }\n  }\n\n  // ---- proactive dark card ----------------------------------------------------\n  function showPop() {\n    if (document.querySelector(\"style[data-wnf-commercial-chat]\")) return;\n    if (popEl || (panel && panel.classList.contains(\"open\"))) return;\n    if (ss(\"wnf_pop_done\") || ls(\"wnf_pop_dismissed\")) return;\n    ss(\"wnf_pop_done\", \"1\");\n    lastPrompt = cardQuestion(); // what the customer is replying to, for staff context\n    hideMini(); // the card takes the corner while it's up\n    popEl = el(\"div\", { class: \"wnf-pop\" });\n    popEl.innerHTML =\n      '<button class=\"wnf-x\" aria-label=\"Dismiss\">\u00D7</button>' +\n      '<div class=\"wnf-pop__hd\">' + avatar(true) + '<div><div class=\"nm\">' + esc(host.name) + '</div><div class=\"ro\">' + esc(host.role) + '</div></div></div>' +\n      '<p class=\"wnf-pop__q\">' + esc(cardQuestion()) + '</p>' +\n      '<p class=\"wnf-pop__sub\">' + esc(cardSub()) + '</p>' +\n      '<button class=\"wnf-cta wnf-cta--gold\" data-act=\"chat\">' + CHAT_SVG + ' Chat now</button>' +\n      '<button class=\"wnf-cta wnf-cta--ghost\" data-act=\"faq\">Browse FAQs</button>';\n    popEl.querySelector(\".wnf-x\").onclick = function () { ls(\"wnf_pop_dismissed\", \"1\"); track(\"wnf_chat_card_dismiss\"); dismissPop(); showMini(); };\n    popEl.querySelector('[data-act=\"chat\"]').onclick = function () { track(\"wnf_chat_card_click\", { act: \"chat\" }); openChat(\"chat\", \"card\"); };\n    popEl.querySelector('[data-act=\"faq\"]').onclick = function () { track(\"wnf_chat_card_click\", { act: \"faq\" }); openChat(\"faq\", \"card\"); };\n    root.appendChild(popEl);\n    track(\"wnf_chat_card_shown\", { host: host.name });\n  }\n  function dismissPop() { if (popEl) { popEl.remove(); popEl = null; } }\n\n  // ---- experiment arm \"sheet\": compact question sheet (phones) ------------------\n  // Replaces the dark card for the sheet arm only. It appears after real engagement\n  // (scrolled past the buy box, picked a finish/variant, or ~20s on the page), waits\n  // until the page is still, never covers Add to Cart / checkout / payment buttons /\n  // sticky buy bars / an open drawer, and gets out of the way if one comes into its\n  // space. Chips are the most common REAL first questions per page (ws_messages,\n  // 2026-09-05..10-03; Murphy from research/voice-of-customer.md). A tapped chip opens\n  // the chat and sends that question, so the answer starts immediately.\n  var PDP_KEYS = { pdp: 1, murphy: 1, fjords: 1, consigned: 1, stanton: 1, stylus: 1, nectar: 1, \"private-label\": 1 };\n  var MURPHY_Q = [\"Will it fit my room?\", \"Is the mattress comfortable?\", \"Can I see one open in Portland?\"];\n  var SHEET = {\n    murphy: { t: \"Questions about this bed?\", q: MURPHY_Q, photo: true },\n    \"col-murphy\": { t: \"Picking a Murphy bed?\", q: MURPHY_Q, photo: true },\n    pdp: { t: \"Questions about this piece?\", q: [\"Is it in stock?\", \"Will it fit my space?\", \"What does delivery cost?\"], photo: true },\n    \"private-label\": { t: \"Questions about this piece?\", q: [\"Is it in stock?\", \"Will it fit my space?\", \"What does delivery cost?\"], photo: true },\n    stanton: { t: \"Questions about this piece?\", q: [\"Can I see fabric swatches?\", \"What sizes does it come in?\", \"How long does it take?\"], photo: true },\n    stylus: { t: \"Questions about this piece?\", q: [\"Can I pick the fabric?\", \"How long does it take?\", \"Can I see it in person?\"], photo: true },\n    fjords: { t: \"Questions about this piece?\", q: [\"Can I sit in one first?\", \"What leather options are there?\", \"How long is the lead time?\"], photo: true },\n    consigned: { t: \"Questions about this piece?\", q: [\"Is this still available?\", \"Can you hold it for me?\", \"Can I see it in person?\"], photo: true },\n    nectar: { t: \"Questions about this mattress?\", q: [\"Can I try it in person?\", \"Which firmness should I pick?\", \"What's your return policy?\"], photo: false },\n    col: { t: \"Looking for the right piece?\", q: [\"Help me find the right piece\", \"Will it fit my space?\", \"Can I see these in person?\"], photo: true },\n    \"col-sofas\": { t: \"Looking for the right sofa?\", q: [\"Help me pick a sofa\", \"Will it fit my space?\", \"Can I sit on one first?\"], photo: true },\n    \"col-sectional\": { t: \"Looking for the right sectional?\", q: [\"Will it fit my space?\", \"Can I change the layout?\", \"Can I see one in person?\"], photo: true },\n    cart: { t: \"Questions before checkout?\", q: [\"How soon will it arrive?\", \"When is delivery free?\", \"What if it's not right?\"], photo: false },\n    home: { t: \"Need a hand finding something?\", q: [\"Help me find a piece\", \"Can I see pieces in person?\", \"Where's my order?\"], photo: false }\n  };\n  function sheetKey() {\n    if (PAGE.key === \"col\") {\n      var h = ((PAGE.collectionHandle || \"\") + \" \" + (PAGE.collectionTitle || \"\")).toLowerCase();\n      if (/murphy|cabinet.?bed|wall.?bed/.test(h)) return \"col-murphy\";\n    }\n    if (PAGE.key === \"cart\" && PAGE.cartCount === 0) return \"home\"; // nothing to check out yet\n    return copyKey();\n  }\n  function sheetCopy() {\n    var k = sheetKey(), c = SHEET[k];\n    if (c) return c;\n    var faqs = (copyFor().faqs || DEFAULT_FAQS).slice(0, 3).map(function (f) { return f.q; });\n    var isCol = /^col-/.test(k) && k !== \"col-mattress\";\n    return { t: isCol ? \"Looking for the right piece?\" : (k === \"design\" ? \"Planning a room?\" : \"Need a hand?\"), q: faqs, photo: isCol || k === \"design\" };\n  }\n  var SHEET_MIN_MS = 6000, SHEET_SETTLE_MS = 1200, SHEET_EST_H = 170;\n  var PROTECT_SEL = 'form[action*=\"/cart/add\"] [type=\"submit\"],form[action*=\"/cart/add\"] button[name=\"add\"],.shopify-payment-button,[data-shopify=\"payment-button\"],button[name=\"checkout\"],input[name=\"checkout\"],a[href*=\"/checkout\"],[data-wnf-avoid]';\n  var BAR_SEL = '[id*=\"sticky\" i],[class*=\"sticky\" i],[class*=\"msticky\" i],[class*=\"atc\" i],#PBarNextFrameWrapper';\n  var sheetEl = null, sheetGuardT = null, sheetRaf = 0;\n  function visibleBox(e) {\n    var s = window.getComputedStyle(e);\n    if (s.display === \"none\" || s.visibility === \"hidden\" || +s.opacity === 0) return null;\n    var r = e.getBoundingClientRect();\n    return r.width > 0 && r.height > 0 && r.bottom > 0 && r.top < window.innerHeight ? r : null;\n  }\n  // Bottom-pinned bars (sticky Add to Cart, configurator bars, Shopify's preview bar):\n  // the sheet sits above the tallest one.\n  function bottomBars() {\n    var out = [], vh = window.innerHeight, iw = window.innerWidth;\n    var bars = document.querySelectorAll(BAR_SEL);\n    for (var i = 0; i < bars.length; i++) {\n      var b = bars[i];\n      if (root && (b === root || root.contains(b))) continue;\n      var pos = window.getComputedStyle(b).position;\n      if (pos !== \"fixed\" && pos !== \"sticky\") continue;\n      var r = visibleBox(b);\n      if (!r || r.height < 20 || r.height > 180 || r.width < iw * 0.5) continue;\n      if (r.bottom > vh - 90) out.push(r);\n    }\n    return out;\n  }\n  function sheetLift() {\n    var vh = window.innerHeight, lift = 0;\n    bottomBars().forEach(function (r) { lift = Math.max(lift, vh - r.top); });\n    return lift ? Math.round(lift + 8) : 0;\n  }\n  function sheetRect(lift, h) {\n    var bottom = window.innerHeight - 10 - lift;\n    return { left: 10, right: window.innerWidth - 10, top: bottom - h, bottom: bottom };\n  }\n  function overlaps(a, b) { return a.left < b.right && a.right > b.left && a.top < b.bottom && a.bottom > b.top; }\n  // What the sheet must never cover. Returns a reason string or \"\".\n  function sheetBlocker(rect) {\n    var els = document.querySelectorAll(PROTECT_SEL);\n    for (var i = 0; i < els.length; i++) {\n      if (root && root.contains(els[i])) continue;\n      var r = visibleBox(els[i]);\n      if (r && overlaps(rect, r)) return \"buy_button\";\n    }\n    var bars = bottomBars();\n    for (var j = 0; j < bars.length; j++) if (overlaps(rect, bars[j])) return \"sticky_bar\";\n    if (drawerOpen()) return \"drawer\";\n    var a = document.activeElement;\n    // A focused text field elsewhere (search, ZIP) means the soft keyboard is up.\n    if (a && (!root || !root.contains(a)) && (a.tagName === \"TEXTAREA\" || (a.tagName === \"INPUT\" && /^(text|search|email|tel|number|url|password|)$/i.test(a.getAttribute(\"type\") || \"\")))) return \"typing\";\n    return \"\";\n  }\n  function drawerOpen() {\n    var b = document.body, d = document.documentElement;\n    if (/\\bjs-drawer-open/.test((b && b.className) || \"\") || /\\bjs-drawer-open/.test((d && d.className) || \"\")) return true;\n    var cand = document.querySelectorAll('#CartDrawer,cart-drawer,.cart-drawer,[id*=\"CartDrawer\" i],.drawer--is-open,[aria-modal=\"true\"]');\n    for (var i = 0; i < cand.length; i++) {\n      if (root && root.contains(cand[i])) continue;\n      var r = visibleBox(cand[i]);\n      if (r && r.width > 120 && r.height > 120) return true;\n    }\n    return false;\n  }\n  // Engagement triggers. Dwell counts visible time since navigation (the widget itself\n  // loads on first touch). PDPs: past the buy box, a variant/finish pick, or 20s.\n  function sheetTriggers(onTrigger) {\n    var k = PAGE.key, pdpLike = !!PDP_KEYS[k], done = false;\n    var rule = pdpLike ? { dwell: 20000, scroll: null } : k === \"col\" ? { dwell: 20000, scroll: 0.5 } : k === \"cart\" ? { dwell: 20000, scroll: null } : { dwell: 25000, scroll: 0.6 };\n    var visMs = document.hidden ? 0 : ((window.performance && performance.now && performance.now()) || 0), last = Date.now();\n    var dwellT = setInterval(function () { var now = Date.now(); if (!document.hidden) visMs += now - last; last = now; if (visMs >= rule.dwell) fire(\"dwell\"); }, 1000);\n    var io = null;\n    if (pdpLike) {\n      var atc = document.querySelector('form[action*=\"/cart/add\"] [type=\"submit\"],form[action*=\"/cart/add\"] button[name=\"add\"]');\n      if (atc && window.IntersectionObserver) {\n        io = new IntersectionObserver(function (es) { es.forEach(function (e) { if (!e.isIntersecting && e.boundingClientRect.bottom <= 0) fire(\"buybox\"); }); });\n        io.observe(atc);\n      } else rule.scroll = 0.4;\n    }\n    function onScroll() {\n      if (rule.scroll == null) return;\n      if (window.scrollY / (document.body.scrollHeight - window.innerHeight + 1) >= rule.scroll) fire(\"scroll\");\n    }\n    function onChange(e) {\n      if (!pdpLike || !e.isTrusted) return;\n      var t = e.target;\n      // Swatches often sit outside the form and join it with form=\"\u2026\" (Motion theme).\n      var inBuyForm = t && t.form && /\\/cart\\/add/.test(t.form.getAttribute(\"action\") || \"\");\n      if (t && (inBuyForm || (t.closest && t.closest('form[action*=\"/cart/add\"],variant-radios,variant-selects,[class*=\"swatch\" i],[class*=\"variant\" i],[data-wnf-variant]')))) fire(\"variant\");\n    }\n    function fire(why) {\n      if (done) return; done = true;\n      clearInterval(dwellT); window.removeEventListener(\"scroll\", onScroll); document.removeEventListener(\"change\", onChange, true); if (io) io.disconnect();\n      onTrigger(why);\n    }\n    window.addEventListener(\"scroll\", onScroll, { passive: true });\n    document.addEventListener(\"change\", onChange, true);\n  }\n  // Show only once the page is still (no scroll/touch for 1.2s), at least 6s after\n  // landing, and when the sheet's space is clear. Otherwise keep waiting quietly.\n  function sheetScheduler(why) {\n    var lastAct = Date.now();\n    function act() { lastAct = Date.now(); }\n    var evs = [\"scroll\", \"touchstart\", \"touchmove\", \"wheel\", \"keydown\"];\n    evs.forEach(function (ev) { window.addEventListener(ev, act, { passive: true }); });\n    var iv = setInterval(function () {\n      if (ss(\"wnf_pop_done\") || ls(\"wnf_pop_dismissed\") || document.querySelector(\"style[data-wnf-commercial-chat]\")) return stop();\n      if (panel && panel.classList.contains(\"open\")) return;\n      var onPage = (window.performance && performance.now && performance.now()) || SHEET_MIN_MS;\n      if (onPage < SHEET_MIN_MS || Date.now() - lastAct < SHEET_SETTLE_MS || document.hidden) return;\n      if (sheetBlocker(sheetRect(sheetLift(), SHEET_EST_H))) return;\n      stop(); showSheet(why);\n    }, 300);\n    function stop() { clearInterval(iv); evs.forEach(function (ev) { window.removeEventListener(ev, act, { passive: true }); }); }\n  }\n  function showSheet(why) {\n    if (sheetEl || popEl || !root) return;\n    if (ss(\"wnf_pop_done\") || ls(\"wnf_pop_dismissed\")) return;\n    ss(\"wnf_pop_done\", \"1\"); // same once-per-session rule as the dark card\n    var c = sheetCopy();\n    lastPrompt = c.t;\n    hideMini();\n    sheetEl = el(\"div\", { class: \"wnf-sheet\", role: \"dialog\", \"aria-label\": \"Questions for Joey, Local Owner\" });\n    sheetEl.innerHTML =\n      '<button class=\"wnf-sheet__x\" type=\"button\" aria-label=\"Dismiss\">' + CLOSE_SVG + '</button>' +\n      '<div class=\"wnf-sheet__hd\">' + avatar() +\n        '<div style=\"min-width:0\"><p class=\"wnf-sheet__t\">' + esc(c.t) + '</p>' +\n        '<div class=\"wnf-sheet__by\">' + esc(host.name + \" \u00B7 \" + host.role) + '<span aria-hidden=\"true\">\u00B7</span><i></i>' + esc(storeHoursNote()) + '</div></div></div>' +\n      '<div class=\"wnf-sheet__rail\" role=\"group\" aria-label=\"Tap a question\">' +\n        c.q.map(function (q, i) { return '<button class=\"wnf-chip\" type=\"button\" data-i=\"' + i + '\">' + esc(q) + '</button>'; }).join(\"\") +\n        '<button class=\"wnf-chip wnf-chip--own\" type=\"button\" data-own=\"1\">Type your own</button></div>' +\n      '<div class=\"wnf-sheet__ft\">' +\n        (c.photo ? '<button class=\"wnf-sheet__photo\" type=\"button\">' + CLIP_SVG + ' Send a photo of your room</button>' : '') +\n        '<span class=\"wnf-sheet__note\">Most answers in under a minute</span></div>' +\n      (c.photo ? '<input class=\"wnf-sheet__file\" type=\"file\" accept=\"image/*\" multiple hidden aria-hidden=\"true\">' : '');\n    root.appendChild(sheetEl);\n    root.classList.add(\"wnf--sheet-up\");\n    placeSheet();\n    sheetEl.querySelector(\".wnf-sheet__x\").onclick = function () {\n      ls(\"wnf_pop_dismissed\", \"1\"); track(\"wnf_chat_card_dismiss\", { format: \"sheet\" }); closeSheet();\n    };\n    Array.prototype.forEach.call(sheetEl.querySelectorAll(\".wnf-chip\"), function (b) {\n      b.onclick = function () {\n        if (b.getAttribute(\"data-own\")) {\n          track(\"wnf_chat_card_click\", { act: \"type\", format: \"sheet\" });\n          closeSheet(true);\n          if (shouldUseChatPage()) return goToChatPage(\"chat\", { src: \"sheet\" });\n          return openPanel(\"chat\", \"sheet\");\n        }\n        var q = c.q[+b.getAttribute(\"data-i\")];\n        track(\"wnf_chat_card_click\", { act: \"chip\", q: q, format: \"sheet\" });\n        closeSheet(true);\n        if (shouldUseChatPage()) return goToChatPage(\"chat\", { ask: q, src: \"sheet\" });\n        openPanel(\"chat\", \"sheet\"); nextMsgSrc = \"sheet\"; submit(q);\n      };\n    });\n    var photoBtn = sheetEl.querySelector(\".wnf-sheet__photo\"), fileEl = sheetEl.querySelector(\".wnf-sheet__file\");\n    if (photoBtn && fileEl) {\n      photoBtn.onclick = function () { track(\"wnf_chat_card_click\", { act: \"photo\", format: \"sheet\" }); fileEl.click(); };\n      fileEl.addEventListener(\"change\", function () {\n        var files = Array.prototype.slice.call(fileEl.files || []); fileEl.value = \"\";\n        if (!files.length) return;\n        track(\"wnf_chat_photo_pick\", { src: \"sheet\", n: files.length });\n        if (!shouldUseChatPage()) { closeSheet(true); openPanel(\"chat\", \"sheet\"); handleFiles(files); return; }\n        stashPhotos(files, function () { closeSheet(true); goToChatPage(\"chat\", { intent: \"photo\", src: \"sheet\" }); });\n      });\n    }\n    track(\"wnf_chat_card_shown\", { host: host.name, format: \"sheet\", trigger: why });\n    var onMove = function () { if (sheetRaf) return; sheetRaf = (window.requestAnimationFrame || setTimeout)(function () { sheetRaf = 0; sheetGuard(); }, 16); };\n    window.addEventListener(\"scroll\", onMove, { passive: true });\n    window.addEventListener(\"resize\", onMove);\n    document.addEventListener(\"focusin\", onMove);\n    document.addEventListener(\"click\", onMove, true);\n    sheetGuardT = setInterval(sheetGuard, 500);\n    sheetEl._unbind = function () { window.removeEventListener(\"scroll\", onMove); window.removeEventListener(\"resize\", onMove); document.removeEventListener(\"focusin\", onMove); document.removeEventListener(\"click\", onMove, true); };\n  }\n  function placeSheet() {\n    if (!sheetEl) return 0;\n    var lift = sheetLift();\n    sheetEl.style.setProperty(\"--wnf-sheet-lift\", lift + \"px\");\n    return lift;\n  }\n  // Runs on scroll/resize/focus/click and every 500ms while the sheet is up.\n  function sheetGuard() {\n    if (!sheetEl) return;\n    var lift = placeSheet();\n    var why = sheetBlocker(sheetRect(lift, sheetEl.offsetHeight || SHEET_EST_H));\n    if (why) { track(\"wnf_chat_card_yield\", { reason: why, format: \"sheet\" }); closeSheet(); }\n  }\n  function closeSheet(instant) {\n    if (!sheetEl) return;\n    var node = sheetEl; sheetEl = null;\n    if (sheetGuardT) { clearInterval(sheetGuardT); sheetGuardT = null; }\n    if (node._unbind) node._unbind();\n    if (root) root.classList.remove(\"wnf--sheet-up\");\n    if (instant) { node.remove(); }\n    else { node.classList.add(\"out\"); setTimeout(function () { node.remove(); }, 220); }\n    showMini();\n  }\n  // Downscale the picked photos and hand them to the full-page chat in sessionStorage.\n  // If storage is full, fewer photos (or just the photo prompt) still get there.\n  function stashPhotos(files, done) {\n    var imgs = files.filter(function (f) { return f && String(f.type).indexOf(\"image/\") === 0; }).slice(0, MAX_ATTS), out = [];\n    (function next(i) {\n      if (i >= imgs.length) {\n        for (var n = out.length; n > 0; n--) {\n          try { sessionStorage.setItem(PHOTO_KEY, JSON.stringify(out.slice(0, n))); break; } catch (e) {}\n        }\n        return done();\n      }\n      downscaleImage(imgs[i], function (res) { if (res) out.push({ d: res.previewUrl, w: res.w, h: res.h }); next(i + 1); });\n    })(0);\n  }\n  // Guardrail metric for the experiment: Add to Cart, observed passively (no fetch\n  // patching). Counted once per 4s across the AJAX request and the form submit.\n  function mxWatchAtc() {\n    var lastAt = 0;\n    function hit(src) { var now = Date.now(); if (now - lastAt < 4000) return; lastAt = now; track(\"wnf_chat_mx_atc\", { src: src }); }\n    try {\n      new PerformanceObserver(function (list) {\n        list.getEntries().forEach(function (e) { if (/\\/cart\\/add(\\.js)?(\\?|$)/.test(e.name || \"\")) hit(\"request\"); });\n      }).observe({ type: \"resource\", buffered: true });\n    } catch (e) {}\n    document.addEventListener(\"submit\", function (e) { var f = e.target; if (f && /\\/cart\\/add/.test(f.getAttribute && f.getAttribute(\"action\") || \"\")) hit(\"form\"); }, true);\n  }\n\n  // ---- always-visible subtle nudge bubble -------------------------------------\n  // Shown from boot on every page; tap opens chat. Hidden while the dark card or the\n  // panel is up (they own the corner), then restored. Dismiss (\u00D7) hides it for the\n  // session only \u2014 it returns next visit, so it stays a persistent, low-key nudge.\n  function showMini() {\n    if (document.querySelector(\"style[data-wnf-commercial-chat]\")) return;\n    if (miniEl || miniDismissed || !root) return;\n    if (ss(\"wnf_mini_dismissed\")) { miniDismissed = true; return; }\n    if (popEl || sheetEl || (panel && panel.classList.contains(\"open\"))) return;\n    miniEl = el(\"div\", { class: \"wnf-mini\", role: \"button\", tabindex: \"0\", \"aria-label\": \"Open chat \u2014 \" + bubbleLine() });\n    miniEl.innerHTML =\n      '<button class=\"wnf-mini__x\" aria-label=\"Dismiss\">\u00D7</button>' + avatar() +\n      '<div class=\"wnf-mini__tx\"><div class=\"wnf-mini__nm\">' + esc(host.name + ' \u00B7 ' + host.role) + '</div>' +\n      '<div class=\"wnf-mini__ln\">' + esc(bubbleLine()) + '</div></div>';\n    miniEl.querySelector(\".wnf-mini__x\").onclick = function (e) {\n      e.stopPropagation(); ss(\"wnf_mini_dismissed\", \"1\"); miniDismissed = true; track(\"wnf_chat_mini_dismiss\", { page: copyKey() }); hideMini();\n    };\n    miniEl.onclick = function () { track(\"wnf_chat_mini_click\", { page: copyKey() }); openChat(\"chat\", \"mini\"); };\n    miniEl.onkeydown = function (e) { if (e.key === \"Enter\" || e.key === \" \") { e.preventDefault(); openChat(\"chat\", \"mini\"); } };\n    root.appendChild(miniEl);\n    track(\"wnf_chat_mini_shown\", { page: copyKey() });\n  }\n  function hideMini() { if (miniEl) { miniEl.remove(); miniEl = null; } }\n\n  // ---- launcher lift over sticky bottom bars (mobile only) --------------------\n  var _liftRAF = 0;\n  function onLift() { if (_liftRAF) return; _liftRAF = (window.requestAnimationFrame || setTimeout)(function () { _liftRAF = 0; syncLift(); }, 100); }\n  function syncLift() {\n    if (!root) return;\n    if (!isMobileView()) { root.style.setProperty(\"--wnf-lift\", \"0px\"); return; }\n    var vh = window.innerHeight, iw = window.innerWidth, lift = 0;\n    // Any sticky/fixed, bottom-pinned, wide, short bar = a sticky purchase/CTA bar.\n    var bars = document.querySelectorAll('[id*=\"sticky\" i],[class*=\"sticky\" i],[id*=\"msticky\" i],[class*=\"msticky\" i],[class*=\"atc\" i]');\n    for (var i = 0; i < bars.length; i++) {\n      var b = bars[i];\n      if (b === root || root.contains(b)) continue;\n      var s = window.getComputedStyle(b);\n      if ((s.position !== \"fixed\" && s.position !== \"sticky\") || s.display === \"none\" || s.visibility === \"hidden\" || s.opacity === \"0\") continue;\n      var r = b.getBoundingClientRect();\n      if (r.height < 20 || r.height > 180 || r.width < iw * 0.5) continue; // skip headers/sidebars/tiny chips\n      if (r.bottom > vh - 90 && r.top < vh) lift = Math.max(lift, vh - r.top); // bottom-pinned + on-screen\n    }\n    root.style.setProperty(\"--wnf-lift\", lift ? (lift + 12) + \"px\" : \"0px\");\n  }\n\n  // ---- boot -------------------------------------------------------------------\n  function boot() {\n    if (PAGE_MODE) return bootPage();   // the dedicated chat page renders inline, no launcher\n    if (booted) return; booted = true;\n    var style = el(\"style\"); style.textContent = CSS; document.head.appendChild(style);\n    root = el(\"div\", { class: \"wnf\" + (OPEN ? \"\" : \" wnf--closed\") });\n    var launch = el(\"button\", { class: \"wnf-launch\", \"aria-label\": \"Chat with us\" }, '<span class=\"wnf-dot\"></span>' + CHAT_SVG);\n    launch.onclick = function () { (panel && panel.classList.contains(\"open\")) ? closePanel() : openChat(\"chat\", \"launcher\"); };\n    root.appendChild(launch);\n    document.body.appendChild(root);\n    track(\"wnf_chat_exposure\", { host: host.name });\n    showMini(); // subtle per-page nudge, visible immediately next to the launcher\n\n    // Keep the corner launcher ABOVE any sticky bottom bar (PDP sticky add-to-cart,\n    // Foxify, the custom configurator stickies) on mobile so the chat bubble never\n    // covers the purchase button. Selector-agnostic: measures any visible bottom-pinned\n    // wide bar and lifts the launcher by its height. Desktop is untouched.\n    syncLift();\n    window.addEventListener(\"scroll\", onLift, { passive: true });\n    window.addEventListener(\"resize\", onLift);\n    setInterval(syncLift, 1200); // backstop for bars that appear/hide without a scroll\n\n    var arm = mxArm();\n    if (arm) {\n      mxWatchAtc();\n      try { if (typeof window.gtag === \"function\") window.gtag(\"set\", \"user_properties\", { wnf_mx_arm: arm }); } catch (e) {}\n      if (mxNewAssign) track(\"wnf_chat_mx_assign\");\n    }\n    if (arm === \"sheet\") { sheetTriggers(sheetScheduler); return; }\n\n    var TM = timingFor();\n    var fired = false;\n    function fire() { if (fired) return; fired = true; clearTimeout(t); window.removeEventListener(\"scroll\", onScroll); document.removeEventListener(\"mouseout\", onExit); showPop(); }\n    function onScroll() {\n      var sc = window.scrollY / (document.body.scrollHeight - window.innerHeight + 1);\n      if (sc >= TM.s) fire();\n    }\n    // Desktop exit-intent (cursor leaving the top of the viewport) \u2014 used on cart to\n    // catch checkout abandoners. Coarse-pointer/mobile has no hover, so it just no-ops.\n    function onExit(e) { if (e.clientY <= 0 && !e.relatedTarget && !e.toElement) fire(); }\n    var t = setTimeout(fire, TM.d);\n    window.addEventListener(\"scroll\", onScroll, { passive: true });\n    if (TM.exit) document.addEventListener(\"mouseout\", onExit);\n  }\n\n  // Public hook so any on-page \"chat with us\" CTA (e.g. the Stanton configurator's\n  // Design Whisperer button) can open this widget directly.\n  // Optional intent: WNFChatOpen({ intent: \"photo\" }) opens the chat with the photo\n  // prompt ready (phones carry it through the full-page navigation). No argument =\n  // exactly the previous behaviour.\n  // wnf-chat-open-canonical-2026-10-10: WNFChatOpen({ src: \"product\" }) names the CTA in wnf_chat_open (default \"cta\").\n  // The separate wnf_chat_cta_open event is retired: the photo intent is now an \"intent\" parameter on wnf_chat_open.\n  window.WNFChatOpen = function (opts) {\n    var intent = opts && typeof opts === \"object\" && opts.intent === \"photo\" ? \"photo\" : \"\";\n    var src = opts && typeof opts === \"object\" && typeof opts.src === \"string\" && opts.src ? opts.src.slice(0, 20) : \"cta\";\n    if (shouldUseChatPage()) return intent ? goToChatPage(\"chat\", { intent: intent, src: \"cta\" }, src) : goToChatPage(\"chat\", undefined, src);\n    boot(); openPanel(\"chat\", src, intent);\n    if (intent) showPhotoPrompt();\n  };\n  // If an on-page CTA called the loader's WNFChatOpen stub before this (lazy) script\n  // finished loading, honor that queued intent now \u2014 fixes the \"nothing happens\" race\n  // where the button's poll could expire before the widget booted. A loader stub that\n  // queues its argument (an object) passes the intent through.\n  if (window.__wnfOpenQueued) { var _q = window.__wnfOpenQueued; window.__wnfOpenQueued = false; try { window.WNFChatOpen(typeof _q === \"object\" ? _q : undefined); } catch (e) {} }\n\n  boot();\n})();\n"],
  "mappings": "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",
  "names": ["ft", "val", "lastAt"]
}
