{
  "version": 3,
  "sources": ["/cdn/shop/t/1064/assets/spangle-v4.js?auto=format%2Ccompress"],
  "sourcesContent": ["/* Ninja Transfers \u2014 Spangle on v4: Step-2 color chooser + interactive dot preview.\n *\n * Loaded ONLY by the spangle_colors block's snippet (spangle template), and\n * additionally self-gated on [data-nt-spg] \u2014 it can never act on the other\n * v4 templates.\n *\n * Chooser: up to 3 selects (slot state machine per the mock \u2014 one live field,\n * dashed \"+ Add another Color\" ghosts). Selection state is published as\n *   window.__ntSpangleColors = [{name, swatch}]\n * and every change dispatches `nt:spangle-colors-changed` on document.\n *\n * Preview \u2014 how the dots are made:\n *   1. The uploaded design is rasterised to a FINE coverage mask (~512px on\n *      the long axis): which pixels are art, and which of the (up to 3)\n *      dominant design colors each belongs to.\n *   2. A spangle lattice is laid over it: a legibility floor of 64 spangles\n *      across, going denser for large print widths (~5.2 per inch, read from\n *      the stage's own ruler; max 110). Small designs never drop below the\n *      floor \u2014 a physical-only pitch turned small text into blobs.\n *   3. Stones are packed largest-first over that mask \u2014 4mm in open fill,\n *      3mm and 2mm as the standard mix, 1mm only where nothing bigger fits\n *      (the real sizes, per Justin 2026-09-03). Each size lays its own\n *      lattice at its own pitch, takes only cells whose coverage its stone\n *      needs, and can never overlap a stone already placed. Each stone's\n *      color is the design color most of its pixels belong to.\n *   Layouts: 1 square lattice, 2 staggered rows.\n *\n * Dot colors: design color N (largest area first) -> the spangle picked in\n * picker N; unpicked = black. Pickers are capped at the detected color count\n * (1/2/3); more than 3 colors, or a photo/gradient, opens a puff-style modal\n * (\"Looks like you uploaded an image with a lot of color\").\n *\n * The same render is exported as a tight transparent PNG for the size-guide\n * garments ([data-bsv4-sg-design]) in place of the flat logo; an attribute\n * observer re-applies it after the engine's own src writes (write-only-if-\n * different \u2014 no loop). The stage overlay is a positioned SIBLING of the\n * engine-owned stage, driven by `bsv4:preview-ready` \u2014 zero engine changes.\n *\n * Cart: implements the engine's family adapter seam \u2014 window.__bsv4ItemProps\n * ('_Spangle Colors' as \"A, B\" \u2014 legacy value format, underscore so the cart hides it \u2014 and\n * 'Spangle Layout' as \"Pattern N\"), window.__bsv4CartGate (>= 1 color), and\n * window.__bsv4TierExactCents (tier prices in exact cents like the legacy\n * spangle table). Any error leaves the page as stock v4.\n */\n(function () {\n  'use strict';\n\n  // Fine-mask long axis. Raised from 512 with the size ladder: the 1mm pass\n  // lays a lattice at 3x the base pitch, so at a 15in print (127 base cells)\n  // its cells are ~1.6px on a 900px mask \u2014 under 512 they were sub-pixel.\n  var FINE_MAX = 1000;        // 2026-09-08 learning set: thin outlines (hollow FOOTBALL) broke up at 900/600px\n  var ALPHA_MIN = 40;         // pixel counts as art above this alpha\n  var WHITE_BG_MIN = 246;     // near-white opaque pixels = background (JPGs)\n  // Chroma-direction distance under which two bins are ONE ink. Measured on\n  // the sandbox: the one-color Cricut logo splits into bins 0.094 apart (89.9%\n  // + 10.1%, both clearing the 4% floor, which is why it counted as 2), while\n  // a real light-blue + navy pair sits 0.229 apart. 0.15 separates them with\n  // room on both sides; 0.22 was riding the navy boundary.\n  var CHROMA_MERGE = 0.15;\n  var COVERAGE_MIN = 0.35;    // cell coverage needed for a spangle (thin strokes survive)\n  // ONE stone size, 3mm (Justin 2026-09-03: \"lets ONLY display these as 3mm\n  // spangles\" \u2014 mixing 2mm in muddied the render). Fill style comes from the\n  // vendor's production files: concentric rows hugging each feature's outline\n  // (contour rows), and one continuous overhanging row down anything too thin\n  // for two rows. Small-detail detection keeps a 2mm-radius yardstick so\n  // single-row text is not read as \"too small\".\n  // Strokes narrower than this (mm, AT THE CHOSEN PRINT SIZE) are one spangle\n  // wide: under two 2mm stones. Justin's \"anything under 25px\" measured on\n  // the NT logo file is ~3.7mm at its 5.81in print. Read at print scale, not\n  // file pixels: a 400px upload of a bold logo is not thin (measured: the\n  // file-pixel version made every Cricut letter a 2mm spine).\n  var THIN_MM = 4;\n  var SINGLE_ROW_MAX = 2.45;  // strokes under this many stones wide are ONE row (2.5 is the first width where two rings + a center row fit)\n  var SMALL_TEXT_H = 7;\n  // Stone size is decided PER ELEMENT by the engine (Justin 2026-09-03, final:\n  // \"I NEED you to be able to know where to use 3mm and where to use 4mm and\n  // where to use 1mm and where to use 2mm to recreate designs\" \u2014 the way an\n  // ERA / Corel operator sizes each object). stoneMode 0 = auto; a nonzero\n  // value forces one size (test hook only). Sizes in play: 1, 2, 3, 4 mm.\n  var stoneMode = 0;\n  // Single-row elements take a stone about as wide as the stroke:\n  // Justin 2026-09-03: \"I care more about the preview looking good ... than\n  // follow rules and make the image look bad.\" Decisions are made per TEXT\n  // LINE (letters sharing a baseline get one treatment, like an operator\n  // sizing a word) and lean toward what reads well in the vendor's mockups.\n  var SINGLE_ROW_STONES = 1.75;                          // a stroke under this many STONES wide is one center row; wider gets an outline ring + rows (vendor pairs 2026-09-08: Catalyst's 2-3 stone interiors are two rows of small stones, not one big centre row)\n  var DESIGN_2MM_SHARE = 0.35;                           // whole design drops to 2mm when this share of its art is strokes two 3mm rows cannot fill / small text\n  var BG_ENCLOSED_MIN_SHARE = 0.20;                      // enclosed pockets of the border colour count as ART only when they are this share of the art (Wildcat's white face 66%); letter counters (~5%) stay background\n  var OUTLINE_MIN_MM = 2.2;\n  var OUTLINE_SPACING = 1.8;                             // outline stones sit this many diameters apart (dotted, like the vendor)                              // thin text with room for two edges -> 1mm OUTLINE (vendor's TRANSFERS mockup); thinner -> 1mm center line\n  var TINY_TEXT_MM = 10, SMALL_TEXT_MM = 21;             // text under these heights: tiny -> 1mm, small -> 2mm\n  var SINGLE_2MM_MAX = 2.8;                              // large single-row strokes: 2mm up to this, then 3mm\n  var FILL_2MM_MAX = 6.0;                                // a filled stroke under this (mm) cannot hold two 3mm rows -> counts toward the 2mm-design share. No automatic 4mm: the vendor keeps one ~3mm size even on 10in letters (UE, Tigers)\n  var NARROW_FILL_MM = 6.5;                              // fills under this at their WIDEST are laid in 2mm (two 3mm rows at the bead pitch need ~6.5mm; vendor's white stripes are two rows of SS10)\n  var LINE_3MM_MIN_MM = 1.8;                             // an isolated single-row line at least this wide takes the 3mm stone in a 3mm design (vendor: heart frame, 1.0-1.5 D_large lines)\n  var FRAME_3MM_MAX_MM = 5.8;                            // an isolated uniform frame/border stroke up to this wide collapses to ONE row of 3mm instead of 2-3 rows of 2mm (vendor: Catalyst box)\n  var THIN_SPLIT_STONES = 1.5;                           // parts of a feature under this many SMALL stones wide are split off as their own thin features (an outline fused to a thick band)\n  var R_FILL = 0.5;           // stone radius in 3mm cells: a 3mm stone is one cell wide\n  var STONE_GAP = 1.15;       // spacing pitch = this x diameter (vendor 2026-09-08: beads sit ~15% apart along and across rows, never touching-solid)\n  // Overlap guard: two stones' centres must clear this share of their summed\n  // radii. A little under 1 so the stones of a tight inner ring (chord shorter\n  // than arc) still pass; drawn at 0.97 r they never visibly merge.\n  var GUARD = 1.0;            // stones never overlap (vendor); the bead gap lives in STONE_GAP\n  var INNER_GUARD = 1.0;      // vendor learning set 2026-09-08: stones never overlap\n  var FILL_GUARD = 1.0;       // gap stones: a full stone must fit\n  var CENTER_GUARD = 0.9;     // a PLANNED middle row (odd row count) may close its bead gap (touching) so a 2.6-stone script stroke reads filled, not hollow\n  var COVER_GUARD = 0.84;     // small fillers in real holes may close the bead gap (a 2mm stone in a 3mm channel)\n  var HOLE_MIN_AIR = 0.5;     // a hole is worth a filler only when the air sliver is at least half a radius\n  var COV_MIX = 0.20;         // below this a base cell is background, not art\n  // \"Too fine for spangles\" thresholds \u2014 recalibrated for the size ladder.\n  var DETAIL_MIN_STONES = 12; // below this nothing meaningful is rendered yet\n  // Warn only when the artwork is almost ENTIRELY thinner than the smallest\n  // stone. Measured at the default print size (4.44in), share of art under a\n  // 2mm stone's radius: bold logo .193, RED/BLUE/GREEN block text .291, NINJA\n  // TRANSFERS .517 \u2014 all producible and must not warn \u2014 versus hairline art\n  // .998. The metric rises as the chosen SIZE shrinks (at 4.44in a lot of any\n  // design is thinner than a stone), so the bar has to sit high or the modal\n  // blocks work we can obviously make. It did: at .25 it blocked all three.\n  // Warn when this share of the artwork sits in features that received no\n  // stones \u2014 i.e. detail the customer would simply not get. Calibrated below.\n  var DETAIL_VANISH_MAX = 0.02;\n  var DETAIL_ZERO_FEATURES = 6;\n  // A feature holding fewer than this many stones is not reproducible, so it\n  // is left out of the preview entirely rather than drawn as a few specks.\n  // A feature counts as small detail when this share of ITS artwork is\n  // thinner than a 2mm stone; the flagged features must total at least\n  // DETAIL_SMALL_SHARE_MIN of the design so a stray speck cannot trip it.\n  var FEATURE_THIN_MAX = 0.85;\n  // ...or when this share of the feature was background before gap closing \u2014\n  // detail cut OUT of a solid area. A deliberate thin keyline (FHS) is a few\n  // percent; text knocked out of a patch is far more.\n  var FEATURE_FILLED_MAX = 0.15;\n  // Small features may total this share of the artwork before the design is\n  // blocked; below it they are removed from the preview and the note under\n  // the preview says so. (Justin: \"90% or more spangle-able -> let it through\".)\n  var DETAIL_SMALL_SHARE_MIN = 0.10;\n  // A spangle MOCKUP fed back in as artwork is a field of hundreds of separate\n  // stones; a real logo is a handful of connected shapes. Feature count is the\n  // discriminator. (A periodicity measure was tried first and is useless here:\n  // letters alternate along a scan row exactly like a lattice does, so real\n  // artwork scored 0.42-0.52 on it, higher than the threshold.)\n  var MOCKUP_MIN_FEATURES = 150;\n  var MOCKUP_DETECT = false;     // the 'this looks like a spangle mockup' block is disabled (Justin 2026-09-03)\n  // TRUE physical density (Justin's A/B, 2026-09-03): stones sit nearly\n  // touching, so an inch holds 25.4/diameter of them \u2014 8.47 for the 3mm base,\n  // not the 5.2 that was here (which is a 4.9mm stone). At 5.2, with a 64\n  // floor on top, a 4in print rendered ~8 stones across a letter stroke and\n  // the letterforms blobbed together; production puts 25-30 rows across the\n  // same cap height. There is deliberately NO legibility floor any more: the\n  // preview shows the stone count the customer's chosen SIZE actually buys,\n  // and the too-fine warning covers the case where that is not enough.\n  var DOTS_PER_INCH = 25.4 / 3;\n  var DOTS_FLOOR = 10;        // only to keep a degenerate size from rendering nothing\n  var DOTS_MAX = 140;         // 15in x 8.47 = 127, plus headroom\n  var THUMB_DOTS_MAX = 44;    // tile thumbnails: never denser than this\n  var EXPORT_CELL_PX = 10;    // tight PNG for size guide: px per lattice cell\n  // Before any color is picked, each DETECTED design color renders in its own\n  // grey so the preview reads as a design with distinct areas rather than one\n  // black blob (Justin 2026-09-03): near-black, mid grey, light grey.\n  var DEFAULT_RGBS = [[26, 26, 26], [124, 124, 124], [193, 193, 193]];\n  var DEFAULT_RGB = DEFAULT_RGBS[0];\n\n  // render colour per swatch name (median of the sequin's lit mid-tones); the\n  // snippet also carries these as data-rgb \u2014 this map is the offline fallback\n  var FALLBACK = {\n    'Aqua': [2, 141, 207],\n    'Black': [17, 14, 9],\n    'Fuschia': [212, 2, 69],\n    'Gold': [201, 175, 5],\n    'Green': [4, 119, 12],\n    'Grincy Green': [135, 192, 23],\n    'Hot Pink': [237, 78, 188],\n    'Lt Blue': [53, 207, 226],\n    'Lt Pink': [220, 99, 212],\n    'Lt Rainbow': [191, 237, 254],\n    'Maroon': [77, 1, 8],\n    'Navy': [2, 16, 70],\n    'Orange': [218, 39, 3],\n    'Platinum': [175, 178, 183],\n    'Purple': [103, 21, 212],\n    'Rainbow': [45, 113, 163],\n    'Red': [178, 1, 2],\n    'Royal': [12, 74, 231],\n    'Silver': [187, 205, 220],\n    'Tan': [209, 175, 94],\n    'White': [208, 208, 212],\n    'Yellow': [159, 193, 81]\n  };\n\n  var root = null;       // [data-nt-spg] (colors card)\n  var layoutEl = null;   // [data-nt-spg-layout] (pattern tiles)\n  var stage = null;      // [data-bsv4-canvas]\n  var wrap = null, canvas = null, chip = null;\n  var mask = null, maskSrc = '';   // fine coverage mask of the current design\n  var latticeCache = {};            // key \"pat:dots\" -> lattice\n  var pattern = 1;        // the only layout \u2014 the tiles were removed 2026-09-03\n  var showingDots = true;\n  var renderTimer = null;\n  var swatchCache = {};\n  var currentDataUrl = '';\n  var sgObserver = null;\n  var lastPicks = [null, null, null];\n  var thumbStats = null;\n\n  /* ---------------- chooser ---------------------------------------------- */\n\n  function slots() { return [].slice.call(root.querySelectorAll('[data-spg-slot]')); }\n\n  function publishSelection() {\n    var out = [];\n    slots().forEach(function (slot) {\n      if (slot.hidden || slot.classList.contains('nt-spg__slot--empty')) return;\n      var sel = slot.querySelector('[data-spg-select]');\n      if (!sel || !sel.value) return;\n      var opt = sel.options[sel.selectedIndex];\n      out.push({ name: sel.value, swatch: opt ? opt.getAttribute('data-swatch') : null });\n    });\n    window.__ntSpangleColors = out;\n    try {\n      document.dispatchEvent(new CustomEvent('nt:spangle-colors-changed', { detail: { colors: out } }));\n    } catch (e) { /* preview below still re-renders via direct call */ }\n    rerender();\n  }\n\n  function syncDot(slot) {\n    var sel = slot.querySelector('[data-spg-select]');\n    var dot = slot.querySelector('[data-spg-dot]');\n    if (!sel || !dot) return;\n    var opt = sel.options[sel.selectedIndex];\n    var url = sel.value && opt ? opt.getAttribute('data-swatch') : null;\n    if (url) {\n      dot.style.backgroundImage = 'url(\"' + url + '\")';\n      dot.hidden = false;\n    } else {\n      dot.style.backgroundImage = '';\n      dot.hidden = true;\n    }\n  }\n\n  /* Native <select> menus cannot show images, so each picker gets a custom\n     dropdown showing the sequin swatch beside every color. The native select\n     stays as the source of truth (value + option data-swatch) \u2014 every other\n     path (cart props, dot mapping, resets, tests) keeps reading it. */\n  function enhanceSelect(sel) {\n    var field = sel.closest('.nt-spg__field');\n    if (!field || sel.__ntDd) return;\n    var dd = document.createElement('div');\n    dd.className = 'nt-spg-dd';\n    var btn = document.createElement('button');\n    btn.type = 'button';\n    btn.className = 'nt-spg-dd__btn';\n    btn.setAttribute('aria-haspopup', 'listbox');\n    btn.setAttribute('aria-expanded', 'false');\n    var list = document.createElement('ul');\n    list.className = 'nt-spg-dd__list';\n    list.setAttribute('role', 'listbox');\n    list.hidden = true;\n    [].slice.call(sel.options).forEach(function (opt) {\n      if (!opt.value) return;\n      var li = document.createElement('li');\n      li.className = 'nt-spg-dd__opt';\n      li.setAttribute('role', 'option');\n      li.setAttribute('data-value', opt.value);\n      li.innerHTML = '<span class=\"nt-spg-dd__sw\" style=\"background-image:url(&quot;' + opt.getAttribute('data-swatch') + '&quot;)\"></span>' +\n        '<span class=\"nt-spg-dd__name\">' + opt.textContent + '</span>';\n      list.appendChild(li);\n    });\n    function render() {\n      var opt = sel.options[sel.selectedIndex];\n      var sw = sel.value && opt ? opt.getAttribute('data-swatch') : null;\n      btn.innerHTML = (sw ? '<span class=\"nt-spg-dd__sw\" style=\"background-image:url(&quot;' + sw + '&quot;)\"></span>' : '') +\n        '<span class=\"nt-spg-dd__name' + (sel.value ? '' : ' nt-spg-dd__name--placeholder') + '\">' + (sel.value || 'Pick a Color') + '</span>' +\n        '<span class=\"nt-spg-dd__caret\" aria-hidden=\"true\"></span>';\n      [].slice.call(list.children).forEach(function (li) {\n        li.setAttribute('aria-selected', li.getAttribute('data-value') === sel.value ? 'true' : 'false');\n      });\n    }\n    function open() { list.hidden = false; btn.setAttribute('aria-expanded', 'true'); dd.classList.add('is-open'); }\n    function close() { list.hidden = true; btn.setAttribute('aria-expanded', 'false'); dd.classList.remove('is-open'); }\n    btn.addEventListener('click', function (e) { e.preventDefault(); if (list.hidden) open(); else close(); });\n    list.addEventListener('click', function (e) {\n      var li = e.target.closest ? e.target.closest('.nt-spg-dd__opt') : null;\n      if (!li) return;\n      sel.value = li.getAttribute('data-value');\n      sel.dispatchEvent(new Event('change', { bubbles: true }));\n      close();\n      btn.focus();\n    });\n    document.addEventListener('click', function (e) { if (!dd.contains(e.target)) close(); });\n    document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); });\n    sel.addEventListener('change', render);\n    sel.__ntDd = { render: render };\n    sel.classList.add('nt-spg__select--native');\n    field.classList.add('is-enhanced');\n    dd.appendChild(btn);\n    dd.appendChild(list);\n    field.insertBefore(dd, sel);\n    render();\n  }\n\n  function refreshDropdowns() {\n    slots().forEach(function (slot) {\n      var sel = slot.querySelector('[data-spg-select]');\n      if (sel && sel.__ntDd) sel.__ntDd.render();\n    });\n  }\n\n  function initChooser() {\n    slots().forEach(function (slot) {\n      var sel = slot.querySelector('[data-spg-select]');\n      if (sel) enhanceSelect(sel);\n    });\n    root.addEventListener('change', function (e) {\n      var sel = e.target && e.target.closest ? e.target.closest('[data-spg-select]') : null;\n      if (!sel) return;\n      syncDot(sel.closest('[data-spg-slot]'));\n      publishSelection();\n    });\n    root.addEventListener('click', function (e) {\n      var t = e.target;\n      var add = t && t.closest ? t.closest('[data-spg-add]') : null;\n      if (add) {\n        var empty = slots().filter(function (s) { return !s.hidden && s.classList.contains('nt-spg__slot--empty'); })[0];\n        if (empty) {\n          empty.classList.remove('nt-spg__slot--empty');\n          var f = empty.querySelector('.nt-spg__field');\n          if (f) f.hidden = false;\n          var sel = empty.querySelector('[data-spg-select]');\n          if (sel) sel.focus();\n        }\n        return;\n      }\n      var rem = t && t.closest ? t.closest('[data-spg-remove]') : null;\n      if (rem) {\n        // clear the pick, keep the field \u2014 every visible slot maps to a\n        // detected design color, so it stays as \"Pick a Color\"\n        var slot = rem.closest('[data-spg-slot]');\n        var sel2 = slot.querySelector('[data-spg-select]');\n        if (sel2) sel2.value = '';\n        syncDot(slot);\n        refreshDropdowns();\n        publishSelection();\n      }\n    });\n  }\n\n  /* ---------------- detected-color cap + design-color chips ---------------- */\n\n  // Colour card visibility: hidden ('pending') from the moment a new design\n  // starts sampling until its colours are known (Justin 2026-09-08: the\n  // default picker flashed during loading, then auto-filled).\n  function setColorsPending(on) {\n    if (!root) return;\n    root.classList.toggle('nt-spg--pending', !!on);\n  }\n\n  function applyDetectedMax(n) {\n    if (!root) return;\n    var maxCfg = parseInt(root.getAttribute('data-max'), 10) || 3;\n    var lim = Math.max(1, Math.min(maxCfg, n || 3));\n    var changed = false;\n    slots().forEach(function (slot) {\n      var i = parseInt(slot.getAttribute('data-spg-slot'), 10);\n      var hide = i > lim;\n      slot.hidden = hide;\n      var sel = slot.querySelector('[data-spg-select]');\n      var f = slot.querySelector('.nt-spg__field');\n      if (hide) {\n        // beyond the detected color count: clear and collapse\n        if (!slot.classList.contains('nt-spg__slot--empty')) {\n          if (sel) sel.value = '';\n          syncDot(slot);\n          slot.classList.add('nt-spg__slot--empty');\n          if (f) f.hidden = true;\n          changed = true;\n        }\n        return;\n      }\n      // Justin 2026-09-02: a detected color gets its picker open immediately \u2014\n      // reading \"Pick a Color\" \u2014 instead of making the customer hit \"+ Add\n      // another Color\" for colors we already found.\n      if (slot.classList.contains('nt-spg__slot--empty')) {\n        slot.classList.remove('nt-spg__slot--empty');\n        if (f) f.hidden = false;\n      }\n    });\n    /* The heading counts what was actually found. Its class changed when the\n       phone pin stopped lifting it (2026-09-15), so both are looked up. */\n    var h = root.querySelector('.nt-spg__step') || root.querySelector('.bsv4-step');\n    if (h) {\n      if (!h.getAttribute('data-orig')) h.setAttribute('data-orig', h.innerHTML);\n      var orig = h.getAttribute('data-orig');\n      /* \"Choose 1 Color\" / \"Choose 2 Colors\" / \"Choose 3 Colors\" \u2014 the count\n         found, no \"up to\" (Justin 2026-09-15). */\n      h.innerHTML = orig.replace(/(up to )?\\d+ Colors?/i, lim === 1 ? '1 Color' : lim + ' Colors');\n    }\n    var pal = (mask && mask.palette) || [];\n    slots().forEach(function (slot) {\n      var i = parseInt(slot.getAttribute('data-spg-slot'), 10) - 1;\n      var chipEl = slot.querySelector('[data-spg-design-color]');\n      if (!chipEl) return;\n      if (pal[i]) {\n        chipEl.style.backgroundColor = 'rgb(' + pal[i][0] + ',' + pal[i][1] + ',' + pal[i][2] + ')';\n        chipEl.hidden = false;\n      } else {\n        chipEl.hidden = true;\n      }\n    });\n    showNote('colors', !!(mask && mask.complex));\n    root.setAttribute('data-detected-colors', String(lim));\n    refreshDropdowns();\n    if (changed) publishSelection();\n  }\n\n  /* ---------------- art-won't-work modals + inline notes -------------------- */\n\n  var modalEl = null;\n  var modalShownFor = null; // uploadEpoch the modal was shown for\n  var uploadEpoch = 0;      // bumped on every fresh intake (bsv4:files-received)\n\n  // Two reasons a design can't be made in spangles. Same shell, same two ways\n  // out (simplify and re-upload, or switch to DTF); only the copy differs.\n  var MODAL_COPY = {\n    colors: {\n      title: 'Looks like you uploaded an image with a lot of color',\n      body: 'Spangles support up to 3 solid colors &mdash; no gradients or photos. Upload a simpler version, or use DTF Transfers for full color.'\n    },\n    mockup: {\n      title: 'This looks like a spangle mockup, not artwork',\n      body: 'Upload your original design instead &mdash; a digital image in 1 to 3 solid colors. We build the spangle layout for you.'\n    },\n    detail: {\n      title: 'Some details in your design are too small for spangles',\n      body: 'Spangles are 3mm discs, so hairlines and small text drop out. Remove the fine details and upload again, or use DTF Transfers to keep them.'\n    }\n  };\n\n  function buildModal() {\n    if (modalEl) return modalEl;\n    modalEl = document.createElement('div');\n    modalEl.className = 'nt-spg-modal';\n    modalEl.hidden = true;\n    modalEl.setAttribute('role', 'dialog');\n    modalEl.setAttribute('aria-modal', 'true');\n    modalEl.setAttribute('aria-labelledby', 'nt-spg-modal-title');\n    modalEl.innerHTML =\n      '<div class=\"nt-spg-modal__card\">' +\n        '<h3 class=\"nt-spg-modal__title\" id=\"nt-spg-modal-title\"></h3>' +\n        '<p class=\"nt-spg-modal__body\"></p>' +\n        '<div class=\"nt-spg-modal__drop\" data-spg-modal-drop>' +\n          '<svg class=\"nt-spg-modal__drop-icon\" viewBox=\"0 0 24 24\" width=\"34\" height=\"34\" aria-hidden=\"true\">' +\n            '<path fill=\"#019AFF\" d=\"M17.5 18.5a4.75 4.75 0 0 0 .95-9.4 6.2 6.2 0 0 0-12.1 1.15A4.1 4.1 0 0 0 7 18.5h10.5z\"/>' +\n            '<path d=\"M12 16.5v-5.2m0 0-2.2 2.2m2.2-2.2 2.2 2.2\" fill=\"none\" stroke=\"#fff\" stroke-width=\"1.9\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>' +\n          '</svg>' +\n          '<p class=\"nt-spg-modal__drop-txt\">Drag and drop your file here</p>' +\n          '<button type=\"button\" class=\"nt-spg-modal__cta nt-spg-modal__cta--inline\" data-spg-modal-browse>Browse</button>' +\n          '<input type=\"file\" class=\"nt-spg-modal__file\" data-spg-modal-input hidden>' +\n        '</div>' +\n        '<a class=\"nt-spg-modal__link\" href=\"/products/dtf-transfers\" data-spg-modal-dtf>Redirect to DTF Transfers By Size</a>' +\n        '<button type=\"button\" class=\"nt-spg-modal__link nt-spg-modal__link--preview\" data-spg-modal-preview hidden>Preview it anyway</button>' +\n      '</div>';\n    // Deliberately NOT dismissable (Justin 2026-09-02): no Escape handler and\n    // no backdrop click. The art cannot be made in spangles, so the customer\n    // has to choose \u2014 replace it here, or go to DTF Transfers.\n    var fileInput = modalEl.querySelector('[data-spg-modal-input]');\n    // mirror the engine's own accepted types so the two pickers can't disagree\n    var engInput = document.querySelector('[data-bsv4-block=\"upload_box\"] input[type=file]');\n    if (engInput && engInput.getAttribute('accept')) {\n      fileInput.setAttribute('accept', engInput.getAttribute('accept'));\n    }\n    fileInput.addEventListener('change', function () { handoffToEngine(fileInput.files); });\n\n    var dropZone = modalEl.querySelector('[data-spg-modal-drop]');\n    ['dragenter', 'dragover'].forEach(function (evt) {\n      dropZone.addEventListener(evt, function (e) {\n        e.preventDefault(); e.stopPropagation();\n        dropZone.classList.add('is-over');\n      });\n    });\n    ['dragleave', 'dragend'].forEach(function (evt) {\n      dropZone.addEventListener(evt, function () { dropZone.classList.remove('is-over'); });\n    });\n    dropZone.addEventListener('drop', function (e) {\n      e.preventDefault(); e.stopPropagation();\n      dropZone.classList.remove('is-over');\n      handoffToEngine(e.dataTransfer && e.dataTransfer.files);\n    });\n\n    modalEl.addEventListener('click', function (e) {\n      var t = e.target;\n      if (t.closest && t.closest('[data-spg-modal-dtf]')) return; // plain navigation\n      if (t.closest && t.closest('[data-spg-modal-browse]')) { fileInput.click(); return; }\n      // \"Preview it anyway\" (Justin 2026-09-03): the too-detailed dialog is\n      // advice, not a wall \u2014 the render behind it already leaves out what\n      // cannot be built, so letting them look IS the explanation.\n      if (t.closest && t.closest('[data-spg-modal-preview]')) { modalEl.hidden = true; return; }\n      if (t.closest && t.closest('[data-spg-modal-drop]')) return; // clicks inside the zone\n    });\n    document.body.appendChild(modalEl);\n    return modalEl;\n  }\n\n  // The engine's own handoff reader (dev/bysize-v4/src/handoffs.js) takes\n  // ?file=<url> and re-intakes it, so the DTF link can carry the customer's\n  // upload across instead of making them upload twice. Lowercase `file` is\n  // what BOTH consumers read \u2014 the v4 handoff and legacy pdp_transferBySize.\n  // Clear the current design through the engine's OWN delete path, accepting\n  // its \"Remove File\" confirm on the customer's behalf \u2014 they already chose to\n  // replace the design in this dialog, so a second yes/no is just friction.\n  // Required, not optional: uploader.js refuses intake in single-file mode\n  // while a design exists (\"remove the current design first\"), so feeding the\n  // input without this is a silent no-op.\n  function engineState() {\n    try { return (window.__bsv4 && window.__bsv4.getState && window.__bsv4.getState()) || null; }\n    catch (e) { return null; }\n  }\n\n  function isEmpty() {\n    var st = engineState();\n    return !st || st.status === 'empty' || !(st.files && st.files.length);\n  }\n\n  // tiny debug ring (window.__ntSpgTrace) \u2014 no console noise, capped\n  function trace(msg) {\n    var t = (window.__ntSpgTrace = window.__ntSpgTrace || []);\n    if (t.length > 60) t.shift();\n    t.push(msg);\n  }\n\n  // Replace the current design with `picked` and stop as soon as the engine\n  // confirms it. One interval, not a chain of nested timers: the delete and\n  // the intake both resolve asynchronously and in either order, so each tick\n  // just looks at the engine's state and does the next useful thing. Facts\n  // this encodes (all measured on the sandbox 2026-09-02):\n  //   - uploader.js REFUSES intake in single-file mode while a design exists\n  //     (\"remove the current design first\"), so the old one must go first.\n  //   - a single design deletes immediately, with no confirm dialog; if one\n  //     ever appears, accept it (the customer already chose to replace).\n  //   - the delete re-renders the upload card, so the input must be re-queried\n  //     and a change event fired before the uploader rebinds is unheard.\n  // Done when state carries the new file NAME \u2014 status alone can't tell the\n  // old design from the new one.\n  function replaceDesign(picked) {\n    var input0 = document.querySelector('[data-bsv4-block=\"upload_box\"] input[type=file]');\n    if (!input0 || !picked.length) return;\n    var wantName = picked[0].name;\n    var ticks = 0;\n\n    function took() {\n      var st = engineState();\n      var f = st && st.files && st.files[0];\n      return !!(f && (f.name === wantName || f.fileName === wantName));\n    }\n\n    var timer = setInterval(function () {\n      if (took()) { trace('replace: engine took it on tick ' + ticks); clearInterval(timer); return; }\n      if (++ticks > 40) { trace('replace: gave up after 10s'); clearInterval(timer); return; }\n\n      var st = engineState();\n      if (st && st.status === 'uploading') return; // mid-flight, let it land\n\n      if (st && st.files && st.files.length) {\n        var del = document.querySelector('[data-bsv4-file-delete]');\n        if (del) del.click();\n        var yes = document.querySelector('[data-bsv4-confirm-yes]');\n        if (yes) yes.click();\n        return; // next tick feeds, once the state is actually empty\n      }\n\n      var input = document.querySelector('[data-bsv4-block=\"upload_box\"] input[type=file]');\n      if (!input || !input.isConnected) return;\n      try {\n        var dt = new DataTransfer();\n        for (var i = 0; i < picked.length; i++) dt.items.add(picked[i]);\n        try { input.files = dt.files; }\n        catch (e) { Object.defineProperty(input, 'files', { value: dt.files, configurable: true }); }\n      } catch (err) { return; }\n      input.dispatchEvent(new Event('change', { bubbles: true }));\n    }, 250);\n  }\n\n  function handoffToEngine(files) {\n    if (!files || !files.length) return;\n    var picked = [].slice.call(files);\n    // close first: the new intake bumps uploadEpoch, so if the replacement is\n    // also unusable the warning can open again for it\n    if (modalEl) modalEl.hidden = true;\n    replaceDesign(picked);\n    var box = document.querySelector('[data-bsv4-block=\"upload_box\"]');\n    if (box) { try { box.scrollIntoView({ block: 'center', behavior: 'smooth' }); } catch (e) {} }\n  }\n\n  function uploadedFileUrl() {\n    try {\n      var st = window.__bsv4 && window.__bsv4.getState && window.__bsv4.getState();\n      var f = st && st.files && st.files[0];\n      var u = f && (f.fileURL || f.url || f.src);\n      if (u) return String(u).split('?')[0];\n    } catch (e) { /* fall back to the stage image below */ }\n    var img = stage ? stage.querySelector('img') : null;\n    var s = (img && (img.currentSrc || img.src)) || '';\n    return /^https?:/i.test(s) ? s.split('?')[0] : '';\n  }\n\n  function showModal(variant) {\n    var el = buildModal();\n    var copy = MODAL_COPY[variant] || MODAL_COPY.colors;\n    el.querySelector('.nt-spg-modal__title').textContent = copy.title;\n    el.querySelector('.nt-spg-modal__body').innerHTML = copy.body;\n    var link = el.querySelector('[data-spg-modal-dtf]');\n    var prev = el.querySelector('[data-spg-modal-preview]');\n    if (prev) prev.hidden = (variant !== 'detail');\n    var fileUrl = uploadedFileUrl();\n    link.setAttribute('href', '/products/dtf-transfers' + (fileUrl ? '?file=' + encodeURIComponent(fileUrl) : ''));\n    el.hidden = false;\n  }\n\n  // Persistent inline notes, one slot per reason, in the Step-2 card.\n  var NOTE_TEXT = {\n    mockup: 'This looks like a spangle mockup. Please upload the original design as a digital image in 1 to 3 colors.',\n    colors: 'Spangles support up to 3 colors. Please upload a simpler image.',\n    detail: 'Fine lines and small text will drop out. Remove the small details and upload again.'\n  };\n\n  function showNote(variant, show) {\n    if (!root) return;\n    var cls = 'nt-spg__warn nt-spg__warn--' + variant;\n    // document-wide: the detail note lives in the stage, not the colors card\n    var el = document.querySelector('.nt-spg__warn--' + variant);\n    if (!el) {\n      el = document.createElement('p');\n      el.className = cls;\n      el.setAttribute('role', 'alert');\n      el.textContent = NOTE_TEXT[variant];\n      // Justin 2026-09-03: after \"Preview it anyway\" the small-detail warning\n      // is a RED block directly above the tan NOTE under the preview \u2014 the\n      // customer is looking at the render, so the caveat sits with it.\n      var stageNote = variant === 'detail' ? document.querySelector('[data-nt-spg-note]') : null;\n      if (stageNote && stageNote.parentNode) {\n        el.className += ' nt-spg__warn--stage';\n        stageNote.parentNode.insertBefore(el, stageNote);\n      } else {\n        var title = root.querySelector('.bsv4-step');\n        if (title && title.nextSibling) root.insertBefore(el, title.nextSibling); else root.appendChild(el);\n      }\n    }\n    el.hidden = !show;\n  }\n\n  // Share of the artwork that spangles cannot hold at this lattice: `dropCov`\n  // is art that renders as nothing, `small` are the stones that only exist\n  // because a full-size one wouldn't fit. Either running high means the design\n  // is finer than 3mm discs can reproduce.\n  function detailAudit() {\n    if (!mask) return null;\n    var g = lattice(pattern, dotsAcross());\n    var s = g.stats || {};\n    var by = s.byMm || {};\n    var stones = (by[1] || 0) + (by[2] || 0) + (by[3] || 0) + (by[4] || 0);\n    return {\n      stones: stones,\n      byMm: by,\n      // share of the artwork sitting in features that got no stones\n      vanished: s.artArea ? (s.vanished || 0) / s.artArea : 0,\n      features: s.features || 0,\n      // features that received NO stones at all: a tiny tagline under a bold\n      // logo is a dozen of these, but only ~1% of the artwork by area, so a\n      // share-based test alone never catches it\n      zeroFeatures: s.zeroFeatures || 0,\n      // features whose own artwork is almost entirely thinner than a stone\n      smallFeatures: s.smallFeatures || 0,\n      smallShare: s.artArea ? (s.smallArea || 0) / s.artArea : 0,\n      droppedStones: s.droppedStones || 0,\n      stoneMm: s.stoneMm, pitchAdj: s.pitchAdj, feats: s.feats,\n      designMm: s.designMm, narrowShare: s.narrowShare, passCount: s.passCount, tightShare: s.tightShare, palette: mask && mask.palette, fams: window.__ntSpgFams || null,\n      fineShare: stones ? ((by[1] || 0) + (by[2] || 0)) / stones : 0\n    };\n  }\n\n  function detailTooFine() {\n    var a = detailAudit();\n    if (!a) return false;\n    // Block only when small detail is a real share of the artwork (>= 10%);\n    // under that it is quietly left out of the render instead. The one other\n    // block: the design produced next to nothing at all.\n    return a.smallShare >= DETAIL_SMALL_SHARE_MIN || a.stones < DETAIL_MIN_STONES;\n  }\n\n  // One interruption per intake, at most. Colors wins when both apply \u2014 it is\n  // the harder constraint and its copy already points at DTF.\n  function evaluateWarnings() {\n    var aud = detailAudit();\n    var isMockup = MOCKUP_DETECT && (!!(aud && aud.features >= MOCKUP_MIN_FEATURES));   // Justin 2026-09-03: OFF for now (false positives)\n    var manyColors = !!(mask && mask.complex);\n    var fine = detailTooFine();\n    showNote('mockup', isMockup);\n    showNote('colors', manyColors && !isMockup);\n    showNote('detail', fine && !isMockup);\n    if (!isMockup && !manyColors && !fine) { if (modalEl) modalEl.hidden = true; return; }\n    if (modalShownFor === uploadEpoch) return;\n    // the stage re-renders the same design under different URLs (bg-removed /\n    // model variants), so key on the intake epoch, never on the src\n    modalShownFor = uploadEpoch;\n    showModal(isMockup ? 'mockup' : (manyColors ? 'colors' : 'detail'));\n  }\n\n  /* ---------------- layout tiles ------------------------------------------ */\n\n  function layoutTiles() {\n    return [].slice.call(document.querySelectorAll('[data-nt-spg-layout] [data-spg-pattern]'));\n  }\n\n  function initLayout() {\n    layoutEl = document.querySelector('[data-nt-spg-layout]');\n    if (!layoutEl) return;\n    document.addEventListener('click', function (e) {\n      var tile = e.target && e.target.closest ? e.target.closest('[data-nt-spg-layout] [data-spg-pattern]') : null;\n      if (!tile) return;\n      var p = parseInt(tile.getAttribute('data-spg-pattern'), 10);\n      if (!(p >= 1 && p <= 3)) return;\n      pattern = p;\n      layoutTiles().forEach(function (t) {\n        var on = t === tile;\n        t.classList.toggle('is-active', on);\n        t.setAttribute('aria-pressed', on ? 'true' : 'false');\n      });\n      rerender();\n    });\n  }\n\n  /* ---------------- palette (chosen spangle colors) ------------------------- */\n\n  function colorRgb(sel, done) {\n    if (swatchCache[sel.name]) return done(swatchCache[sel.name]);\n    var fallback = FALLBACK[sel.name] || DEFAULT_RGB;\n    // exact render colour from the option (data-rgb), with an optional mode\n    // ('rainbow' / 'lt_rainbow' -> every stone its own hue); sampling the\n    // photographed swatch averaged in its white surround and washed out\n    if (sel.rgb && /^\\d+,\\d+,\\d+$/.test(sel.rgb)) {\n      var fixed = sel.rgb.split(',').map(Number);\n      if (sel.mode) fixed.mode = sel.mode;\n      swatchCache[sel.name] = fixed; return done(fixed);\n    }\n    if (!sel.swatch) { swatchCache[sel.name] = fallback; return done(fallback); }\n    var img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.onload = function () {\n      try {\n        var c = document.createElement('canvas');\n        c.width = 12; c.height = 12;\n        var x = c.getContext('2d');\n        x.drawImage(img, 0, 0, 12, 12);\n        var d = x.getImageData(0, 0, 12, 12).data;\n        var r = 0, g = 0, b = 0, n = 0;\n        for (var i = 0; i < d.length; i += 4) {\n          if (d[i + 3] > 128) { r += d[i]; g += d[i + 1]; b += d[i + 2]; n++; }\n        }\n        var rgb = n ? [Math.round(r / n), Math.round(g / n), Math.round(b / n)] : fallback;\n        swatchCache[sel.name] = rgb;\n        done(rgb);\n      } catch (e) { swatchCache[sel.name] = fallback; done(fallback); }\n    };\n    img.onerror = function () { swatchCache[sel.name] = fallback; done(fallback); };\n    img.src = sel.swatch;\n  }\n\n  // picks[i] = rgb chosen in picker i+1 (null = unpicked -> black)\n  function resolvePalette(done) {\n    var picks = [null, null, null];\n    var pending = 0;\n    slots().forEach(function (slot, i) {\n      if (slot.hidden || slot.classList.contains('nt-spg__slot--empty')) return;\n      var sel = slot.querySelector('[data-spg-select]');\n      if (!sel || !sel.value) return;\n      var opt = sel.options[sel.selectedIndex];\n      pending++;\n      colorRgb({ name: sel.value, swatch: opt ? opt.getAttribute('data-swatch') : null, rgb: opt ? opt.getAttribute('data-rgb') : null, mode: opt ? opt.getAttribute('data-mode') : null }, function (rgb) {\n        picks[i] = rgb;\n        if (--pending === 0) done(picks);\n      });\n    });\n    if (!pending) done(picks);\n  }\n\n  /* ---------------- fine coverage mask + color detection ------------------- */\n\n  function sampleDesign(src, done) {\n    var img = new Image();\n    img.crossOrigin = 'anonymous';\n    img.onload = function () {\n      try {\n        var w = img.naturalWidth, h = img.naturalHeight;\n        if (!w || !h) return done(null);\n        var fw = w >= h ? FINE_MAX : Math.max(16, Math.round(FINE_MAX * w / h));\n        var fh = w >= h ? Math.max(16, Math.round(FINE_MAX * h / w)) : FINE_MAX;\n        var c = document.createElement('canvas');\n        c.width = fw; c.height = fh;\n        var x = c.getContext('2d', { willReadFrequently: true });\n        x.drawImage(img, 0, 0, fw, fh);\n        // White is BACKGROUND only for opaque images (JPG on white). A file\n        // with real transparency (a PNG keyline logo) uses white as a\n        // color \u2014 Justin 2026-09-03: \"it's not identifying the outline of\n        // white\" \u2014 so the near-white test is skipped when >0.5% of pixels\n        // are transparent.\n        var dTest = x.getImageData(0, 0, fw, fh).data, tCount = 0, tp;\n        for (tp = 3; tp < dTest.length; tp += 4 * 7) if (dTest[tp] < ALPHA_MIN) tCount++;\n        var keepWhite = tCount > (dTest.length / 28) * 0.005;\n        var d = x.getImageData(0, 0, fw, fh).data;\n        var cov = new Uint8Array(fw * fh);\n        var bins = {};\n        var covered = 0;\n        // Background of an OPAQUE file = the colour touching the image border\n        // (white, black or grey), flood-filled inward from the border (2026-09-08\n        // learning set: Catalyst on black, Wildcat on grey). Enclosed pockets of\n        // that colour are ART only when together they are a real share of the\n        // design (the Wildcat's white face); small pockets (letter counters) stay\n        // background. Transparent files keep every opaque pixel, white included.\n        var bgMask = null;\n        if (!keepWhite) {\n          var bgClass = function (pp2) {\n            var r2 = d[pp2], g2 = d[pp2 + 1], b2 = d[pp2 + 2];\n            var mx2 = Math.max(r2, g2, b2), mn2 = Math.min(r2, g2, b2);\n            if (mn2 >= WHITE_BG_MIN) return 1;                       // white\n            if (mx2 < 40) return 2;                                  // black\n            if (mx2 - mn2 < 22 && mn2 >= 60 && mx2 < 215) return 3;  // grey\n            return 0;\n          };\n          var cls = new Uint8Array(fw * fh), votes = [0, 0, 0, 0], bi, bx, by;\n          for (bi = 0; bi < fw * fh; bi++) cls[bi] = bgClass(bi * 4);\n          for (bx = 0; bx < fw; bx++) { votes[cls[bx]]++; votes[cls[(fh - 1) * fw + bx]]++; }\n          for (by = 0; by < fh; by++) { votes[cls[by * fw]]++; votes[cls[by * fw + fw - 1]]++; }\n          var bgc = votes[1] >= votes[2] && votes[1] >= votes[3] ? 1 : (votes[2] >= votes[3] ? 2 : 3);\n          if (votes[bgc] > (2 * (fw + fh)) * 0.5) {\n            bgMask = new Uint8Array(fw * fh);\n            var qst = [], qi, nx2, ny2, ni2, px2, py2;\n            var push = function (ii) { if (cls[ii] === bgc && !bgMask[ii]) { bgMask[ii] = 1; qst.push(ii); } };\n            for (bx = 0; bx < fw; bx++) { push(bx); push((fh - 1) * fw + bx); }\n            for (by = 0; by < fh; by++) { push(by * fw); push(by * fw + fw - 1); }\n            while (qst.length) {\n              qi = qst.pop(); px2 = qi % fw; py2 = (qi / fw) | 0;\n              if (px2 > 0) push(qi - 1); if (px2 < fw - 1) push(qi + 1);\n              if (py2 > 0) push(qi - fw); if (py2 < fh - 1) push(qi + fw);\n            }\n            // enclosed pockets of the background colour: art or background?\n            var encl = 0, artN = 0;\n            for (bi = 0; bi < fw * fh; bi++) { if (d[bi * 4 + 3] < ALPHA_MIN) continue; if (bgMask[bi]) continue; if (cls[bi] === bgc) encl++; else artN++; }\n            if (encl < BG_ENCLOSED_MIN_SHARE * Math.max(1, artN)) { for (bi = 0; bi < fw * fh; bi++) if (cls[bi] === bgc) bgMask[bi] = 1; }\n          }\n        }\n        for (var i = 0, p = 0; i < fw * fh; i++, p += 4) {\n          if (d[p + 3] < ALPHA_MIN) continue;\n          var r = d[p], g = d[p + 1], b = d[p + 2];\n          if (bgMask) { if (bgMask[i]) continue; }\n          else if (!keepWhite && r >= WHITE_BG_MIN && g >= WHITE_BG_MIN && b >= WHITE_BG_MIN) continue;\n          cov[i] = 1; covered++;\n          // Bin by CHROMA, not by raw RGB level (2026-09-02). Antialiasing\n          // renders one ink as a ramp of lightnesses; binning on level put a\n          // black glyph's grey edge into several bins, each clearing the 4%\n          // \"strong color\" floor, so plain black-on-white line art was flagged\n          // as \"a lot of color\". Normalising by the max channel collapses a\n          // ramp to a single family, and near-black / low-saturation pixels\n          // all join one neutral family. Distinct inks stay distinct: red\n          // -> 4,0,0 vs royal -> 0,1,4.\n          var mx = r > g ? (r > b ? r : b) : (g > b ? g : b);\n          var mn = r < g ? (r < b ? r : b) : (g < b ? g : b);\n          var key;\n          if (mx < 26 || (mx - mn) / mx < 0.16) {\n            // neutrals split by lightness (2026-09-08: the Tigers paw's white\n            // stripes and its black stripes fell into ONE family and the white\n            // rendered as black stones)\n            key = mx < 90 ? 'n0' : (mx < 190 ? 'n1' : 'n2');\n          } else {\n            key = ((r / mx * 4) | 0) + ',' + ((g / mx * 4) | 0) + ',' + ((b / mx * 4) | 0);\n          }\n          var bin = bins[key] || (bins[key] = { n: 0, best: null, sub: {} });\n          bin.n++;\n          // keep per-level sub-bins so the family's swatch is its dominant\n          // level (near-black for AA'd black text), not the ramp's average\n          var sk = ((r / 52) | 0) + ',' + ((g / 52) | 0) + ',' + ((b / 52) | 0);\n          var sb = bin.sub[sk] || (bin.sub[sk] = { n: 0, r: 0, g: 0, b: 0 });\n          sb.n++; sb.r += r; sb.g += g; sb.b += b;\n        }\n        if (!covered) return done(null);\n\n        // A family's swatch is its dominant lightness level, not the average\n        // of the ramp (near-black for AA'd black text, not mid-grey).\n        function repOf(bn) {\n          var keys = Object.keys(bn.sub);\n          var top = bn.sub[keys[0]];\n          for (var si = 1; si < keys.length; si++) {\n            if (bn.sub[keys[si]].n > top.n) top = bn.sub[keys[si]];\n          }\n          return [Math.round(top.r / top.n), Math.round(top.g / top.n), Math.round(top.b / top.n)];\n        }\n\n        // Chroma DIRECTION of a color: the same ink at any lightness points the\n        // same way, so two shades of one green share a direction while red and\n        // orange don't. Near-black/neutral has no direction \u2014 call it grey.\n        function dirOf(rgb) {\n          var mx = Math.max(rgb[0], rgb[1], rgb[2]), mn = Math.min(rgb[0], rgb[1], rgb[2]);\n          if (mx < 8) return [1, 1, 1, 0];\n          // 4th component: lightness band for neutrals, so black / grey / white\n          // stay separate families; chromatic inks ignore it (0)\n          var neutral = (mx - mn) / mx < 0.16;\n          return [rgb[0] / mx, rgb[1] / mx, rgb[2] / mx, neutral ? (mx < 90 ? 0 : (mx < 190 ? 0.5 : 1)) : 0];\n        }\n\n        function dirDist(a, b) {\n          var dr = a[0] - b[0], dg = a[1] - b[1], db = a[2] - b[2], dl = (a[3] || 0) - (b[3] || 0);\n          return Math.sqrt(dr * dr + dg * dg + db * db + dl * dl);\n        }\n\n        // Merge families that are the same ink (Justin 2026-09-02: a one-color\n        // Cricut logo counted as 2). Chroma binning alone still splits an ink\n        // whose pixels straddle a quantization boundary \u2014 bins are a grid, and\n        // a grid always has edges. So bin finely, then MERGE by chroma\n        // distance, largest family first, before any threshold is applied.\n        var all = Object.keys(bins).map(function (k) {\n          var bn = bins[k];\n          bn.rep = repOf(bn);\n          bn.dir = dirOf(bn.rep);\n          return bn;\n        }).sort(function (p1, p2) { return p2.n - p1.n; });\n\n        var fams = [];\n        var rgbDist = function (a, b) { var dr = a[0] - b[0], dg = a[1] - b[1], db = a[2] - b[2]; return Math.sqrt(dr * dr + dg * dg + db * db); };\n        var isDark = function (rgb) { return Math.max(rgb[0], rgb[1], rgb[2]) < 80; };\n        for (var ai = 0; ai < all.length; ai++) {\n          var bn2 = all[ai], merged = false;\n          for (var fi = 0; fi < fams.length; fi++) {\n            var dd0 = dirDist(bn2.dir, fams[fi].dir);\n            // same ink: same chroma direction; OR nearly the same RGB (two navies\n            // 11,34,63 vs 19,35,59 sat 0.156 apart in direction \u2014 the Wildcat's\n            // phantom third colour, 2026-09-08); dark inks get a looser direction\n            // test because tiny channel values make their direction noisy\n            if (dd0 < CHROMA_MERGE || rgbDist(bn2.rep, fams[fi].rep) < 30 || (isDark(bn2.rep) && isDark(fams[fi].rep) && dd0 < 0.4)) {\n              fams[fi].n += bn2.n;\n              merged = true;\n              break;\n            }\n          }\n          if (!merged) fams.push({ n: bn2.n, rep: bn2.rep, dir: bn2.dir });\n        }\n        fams.sort(function (p1, p2) { return p2.n - p1.n; });\n\n        var strongFloor = Math.max(3, covered * 0.04);\n        var strong = fams.filter(function (fm) { return fm.n >= strongFloor; });\n        if (!strong.length) strong = [fams[0]];\n        // JPEG anti-alias fringe (2026-09-08 judge, Wildcat): the steel-blue band\n        // where navy meets white cleared the 4% floor and became a third colour\n        // that ringed every edge. A colour that is never wider than ~3px anywhere\n        // (max chamfer distance < 2px on the fine mask) is an edge, not an ink.\n        if (strong.length > 1) {\n          var famOf = function (rgb) {\n            var bi2 = -1, bd2 = Infinity, fk, fd, frep;\n            for (fk = 0; fk < strong.length; fk++) { frep = strong[fk].rep; fd = (rgb[0] - frep[0]) * (rgb[0] - frep[0]) + (rgb[1] - frep[1]) * (rgb[1] - frep[1]) + (rgb[2] - frep[2]) * (rgb[2] - frep[2]); if (fd < bd2) { bd2 = fd; bi2 = fk; } }\n            return bi2;\n          };\n          var famMask = [], fq2, qq2, pq2;\n          for (fq2 = 0; fq2 < strong.length; fq2++) famMask.push(new Uint8Array(fw * fh));\n          for (qq2 = 0, pq2 = 0; qq2 < fw * fh; qq2++, pq2 += 4) { if (!cov[qq2]) continue; famMask[famOf([d[pq2], d[pq2 + 1], d[pq2 + 2]])][qq2] = 1; }\n          var keep = [];\n          for (fq2 = 0; fq2 < strong.length; fq2++) {\n            var Df = chamfer(famMask[fq2], fw, fh), deep = 0, tot = 0, qd;\n            for (qd = 0; qd < Df.length; qd++) { if (!famMask[fq2][qd]) continue; tot++; if (Df[qd] >= 2.0) deep++; }\n            var hasBody = tot > 0 && deep / tot >= 0.05;\n            if (hasBody || (keep.length === 0 && fq2 === strong.length - 1)) keep.push(strong[fq2]);\n          }\n          if (keep.length) strong = keep;\n        }\n        // Vendor rules (2026-09-08 learning set):\n        //  - a WEAK white family on a transparent file is a knockout channel\n        //    (CONCORD's inline, the UE star's ring), not a stone colour: those\n        //    pixels become background instead of folding into the nearest ink\n        //  - near-black is the garment: when other colours carry the design\n        //    (black under half the art), black areas get no stones and no ring\n        //    (Tigers' letters and zebra stripes, Catalyst's gaps). A black-only\n        //    or black-majority design keeps black as its colour.\n        //  - Justin 2026-10-27: black is dropped only when it would push the\n        //    design past 3 colours. With room (3 or fewer incl. black) it stays\n        //    a stone colour (red/black/white cheer logo on a light shirt).\n        var isWhiteFam = function (fm) { return Math.min(fm.rep[0], fm.rep[1], fm.rep[2]) >= 200 && fm.dir[3] === 1; };\n        var isBlackFam = function (fm) { return Math.max(fm.rep[0], fm.rep[1], fm.rep[2]) < 40; };\n        var voidFams = [];\n        if (keepWhite) fams.forEach(function (fm) { if (fm.n < strongFloor && isWhiteFam(fm)) voidFams.push(fm); });\n        var blackArea = 0; strong.forEach(function (fm) { if (isBlackFam(fm)) blackArea += fm.n; });\n        if (blackArea && strong.length > 3 && blackArea < 0.5 * covered) {\n          strong = strong.filter(function (fm) { if (isBlackFam(fm)) { voidFams.push(fm); return false; } return true; });\n        }\n        var palette = strong.slice(0, 3).map(function (fm) { return fm.rep; });\n        var voidReps = voidFams.map(function (fm) { return fm.rep; });\n        try { window.__ntSpgFams = { covered: covered, fams: fams.slice(0, 8).map(function (fm) { return { rep: fm.rep, n: fm.n, share: +(fm.n / covered).toFixed(3) }; }), palette: palette, voids: voidReps }; } catch (e) {}\n        var weakFloor = Math.max(2, covered * 0.01);\n        var complex = strong.length > 3 ||\n          fams.filter(function (fm) { return fm.n >= weakFloor; }).length > 8;\n\n        // per-pixel palette index (nearest dominant color)\n        var pidx = new Uint8Array(fw * fh);\n        for (var q = 0, pp = 0; q < fw * fh; q++, pp += 4) {\n          if (!cov[q]) continue;\n          var best = 0, bestD = Infinity, vi, vd, vdr, vdg, vdb;\n          for (var ci = 0; ci < palette.length; ci++) {\n            var pc = palette[ci];\n            var dr = d[pp] - pc[0], dg = d[pp + 1] - pc[1], db = d[pp + 2] - pc[2];\n            var dist = dr * dr + dg * dg + db * db;\n            if (dist < bestD) { bestD = dist; best = ci; }\n          }\n          // nearer to a void colour (garment black / knockout white) than to\n          // any stone colour: no stone here\n          for (vi = 0; vi < voidReps.length; vi++) {\n            vdr = d[pp] - voidReps[vi][0]; vdg = d[pp + 1] - voidReps[vi][1]; vdb = d[pp + 2] - voidReps[vi][2];\n            vd = vdr * vdr + vdg * vdg + vdb * vdb;\n            if (vd < bestD) { cov[q] = 0; covered--; best = -1; break; }\n          }\n          if (best >= 0) pidx[q] = best;\n        }\n        done({ fw: fw, fh: fh, cov: cov, pidx: pidx, palette: palette, colors: palette.length, complex: complex, srcW: w, srcH: h });\n      } catch (e) { done(null); }\n    };\n    img.onerror = function () { done(null); };\n    img.src = /^https?:/i.test(src)\n      ? src + (src.indexOf('?') === -1 ? '?' : '&') + 'w=1200&fm=png'\n      : src;\n  }\n\n  /* ---------------- lattice: physical pitch + centroid-snapped dots --------- */\n\n  // Density follows the CHOSEN print size, read from the stage's own ruler\n  // ([data-bsv4-dim-w]), at the real 3mm pitch. A small print genuinely buys\n  // few stones; showing that is the point.\n  function dotsAcross() {\n    var n = DOTS_FLOOR;\n    try {\n      var el = stage && stage.querySelector('[data-bsv4-dim-w]');\n      var inches = el ? parseFloat((el.textContent || '').replace(/[^\\d.]/g, '')) : NaN;\n      if (!(isFinite(inches) && inches > 0) && mask && mask.fw && mask.fh) {\n        // No ruler yet (headless test, or the stage before its first size):\n        // assume the smallest sellable print, 3in on the short side. Without\n        // this the floor (10 across) made every stroke read as hairline.\n        inches = 3 * Math.max(1, mask.fw / mask.fh);\n      }\n      if (isFinite(inches) && inches > 0) n = Math.max(n, Math.round(inches * DOTS_PER_INCH));\n    } catch (e) { /* keep the floor */ }\n    return Math.min(DOTS_MAX, n);\n  }\n\n  // Coverage + centroid + majority color of one lattice cell (fine px box).\n  function cellStats(m, x0, y0, x1, y1) {\n    x0 = Math.max(0, Math.round(x0)); y0 = Math.max(0, Math.round(y0));\n    x1 = Math.min(m.fw, Math.round(x1)); y1 = Math.min(m.fh, Math.round(y1));\n    var n = 0, total = 0, sx = 0, sy = 0, cc = [0, 0, 0];\n    for (var y = y0; y < y1; y++) {\n      var row = y * m.fw;\n      for (var x = x0; x < x1; x++) {\n        total++;\n        if (!m.cov[row + x]) continue;\n        n++; sx += x + 0.5; sy += y + 0.5; cc[m.pidx[row + x]]++;\n      }\n    }\n    if (!total) return null;\n    var c = cc[0] >= cc[1] && cc[0] >= cc[2] ? 0 : (cc[1] >= cc[2] ? 1 : 2);\n    return { cov: n / total, n: n, cx: n ? sx / n : 0, cy: n ? sy / n : 0, c: c };\n  }\n\n  // Returns { gw, gh, dots:[{cx, cy, r, c}] } in CELL units for pattern `pat`.\n  // Distance transform: for every art pixel, how far (px) to the nearest\n  // background pixel. Two-pass chamfer, cached on the mask. This is what lets\n  // stones follow the artwork's CONTOUR instead of a global lattice \u2014 the\n  // production files Justin shared (2026-09-03) are built that way: an outline\n  // row hugging every edge, then concentric rows working inward.\n  // Chamfer distance transform: 0 at every pixel where seed[i] is falsy,\n  // growing outward into the pixels where it is truthy.\n  function chamfer(seed, fw, fh) {\n    var N = fw * fh, D = new Float32Array(N), i, x, y, best;\n    for (i = 0; i < N; i++) D[i] = seed[i] ? 1e9 : 0;\n    for (y = 0; y < fh; y++) {\n      for (x = 0; x < fw; x++) {\n        i = y * fw + x;\n        if (!D[i]) continue;\n        best = D[i];\n        if (x > 0 && D[i - 1] + 1 < best) best = D[i - 1] + 1;\n        if (y > 0 && D[i - fw] + 1 < best) best = D[i - fw] + 1;\n        if (x > 0 && y > 0 && D[i - fw - 1] + 1.414 < best) best = D[i - fw - 1] + 1.414;\n        if (x < fw - 1 && y > 0 && D[i - fw + 1] + 1.414 < best) best = D[i - fw + 1] + 1.414;\n        D[i] = best;\n      }\n    }\n    for (y = fh - 1; y >= 0; y--) {\n      for (x = fw - 1; x >= 0; x--) {\n        i = y * fw + x;\n        if (!D[i]) continue;\n        best = D[i];\n        if (x < fw - 1 && D[i + 1] + 1 < best) best = D[i + 1] + 1;\n        if (y < fh - 1 && D[i + fw] + 1 < best) best = D[i + fw] + 1;\n        if (x < fw - 1 && y < fh - 1 && D[i + fw + 1] + 1.414 < best) best = D[i + fw + 1] + 1.414;\n        if (x > 0 && y < fh - 1 && D[i + fw - 1] + 1.414 < best) best = D[i + fw - 1] + 1.414;\n        D[i] = best;\n      }\n    }\n    return D;\n  }\n\n  function distanceMap(m) {\n    if (!m.__D) m.__D = chamfer(m.cov, m.fw, m.fh);\n    return m.__D;\n  }\n\n  // Close gaps narrower than a stone. Justin's FHS Broncos pair: the source\n  // has a thin WHITE keyline between the purple letters and their outer edge,\n  // and the production spangle output ignores it \u2014 the purple fill runs\n  // straight through. Physically obvious: you cannot place a stone in a gap\n  // thinner than a stone. Our sampler treats white as background, so without\n  // this every such keyline punches a hairline hole through the artwork.\n  // closing = erode(dilate(A, k), k), both via chamfer.\n  function closeGaps(m, k) {\n    var N = m.fw * m.fh, i;\n    var toArt = chamfer(inv(m.cov, N), m.fw, m.fh);   // distance to nearest art\n    var dil = new Uint8Array(N);\n    for (i = 0; i < N; i++) dil[i] = (m.cov[i] || toArt[i] <= k) ? 1 : 0;\n    var toBg = chamfer(dil, m.fw, m.fh);              // distance to non-dilated\n    var out = new Uint8Array(N);\n    for (i = 0; i < N; i++) out[i] = (dil[i] && toBg[i] > k) ? 1 : 0;\n    return out;\n  }\n\n  function inv(a, N) {\n    var o = new Uint8Array(N), i;\n    for (i = 0; i < N; i++) o[i] = a[i] ? 0 : 1;\n    return o;\n  }\n\n  // Art pixels bucketed by whole-px distance, so a contour row reads only the\n  // band it needs instead of scanning the whole mask once per row.\n  function distIndex(m) {\n    if (m.__byDist) return m.__byDist;\n    var D = distanceMap(m), by = [], maxD = 0, i, d;\n    for (i = 0; i < D.length; i++) {\n      if (!D[i]) continue;\n      d = D[i] | 0;\n      (by[d] = by[d] || []).push(i);\n      if (d > maxD) maxD = d;\n    }\n    m.__byDist = { by: by, maxD: maxD };\n    return m.__byDist;\n  }\n\n  // Palette index under a stone: the 3x3 majority at its centre. Crisper than\n  // a cell average, which is what keeps color boundaries sharp \u2014 in the\n  // production files a single row of stones traces each color edge.\n  function colorAt(m, px, py) {\n    // Reads cov0 (the artwork as uploaded), never the gap-closed mask: a\n    // stone sitting in a closed keyline must take the color of the artwork\n    // around it, not of the white pixels it now covers.\n    var src = m.cov0 || m.cov;\n    var x = px | 0, y = py | 0, cc = [0, 0, 0], dx, dy, xx, yy, i;\n    for (dy = -2; dy <= 2; dy++) {\n      for (dx = -2; dx <= 2; dx++) {\n        xx = x + dx; yy = y + dy;\n        if (xx < 0 || yy < 0 || xx >= m.fw || yy >= m.fh) continue;\n        i = yy * m.fw + xx;\n        if (src[i]) cc[m.pidx[i]]++;\n      }\n    }\n    if (!cc[0] && !cc[1] && !cc[2]) return 0;\n    return cc[0] >= cc[1] && cc[0] >= cc[2] ? 0 : (cc[1] >= cc[2] ? 1 : 2);\n  }\n\n  // Geometry mask for a given density: the artwork with sub-stone gaps closed,\n  // plus its distance transform. Cached per `across` because the closing\n  // radius is a stone radius, which depends on the print size.\n  function geomFor(m, across) {\n    if (m.__geomAcross === across) return m.__geom;\n    var cs = m.fw / across;\n    var N = m.fw * m.fh, nc = Math.max(1, (m.palette || [0]).length), c, i;\n    // PER COLOUR (2026-09-08, vendor learning set): the vendor lays every\n    // colour region as its own shape \u2014 an outline ring hugging the colour\n    // boundary, rows inside it. One lattice over the union of all colours put\n    // rows across colour edges and coloured stones after the fact (the Tigers\n    // render was one orange/black mass). So the geometry is built colour by\n    // colour: closing, distance transform and features all stop at a colour\n    // boundary.\n    // Closing radius ~0.6mm: only anti-aliasing cracks and hairline keylines\n    // close. The old 2mm-stone radius filled the white inline of CONCORD's\n    // letters, which the vendor keeps as a channel between two rings.\n    var k = R_FILL * cs * (0.4);\n    var cov = new Uint8Array(N), pidxG = new Uint8Array(N), D = new Float32Array(N), Dorig = new Float32Array(N);\n    for (c = 0; c < nc; c++) {\n      var mc = new Uint8Array(N);\n      for (i = 0; i < N; i++) mc[i] = (m.cov[i] && m.pidx[i] === c) ? 1 : 0;\n      var closedC = closeGaps({ cov: mc, fw: m.fw, fh: m.fh }, k);\n      var Dc = chamfer(closedC, m.fw, m.fh);\n      var D0c = chamfer(mc, m.fw, m.fh);\n      for (i = 0; i < N; i++) {\n        if (!closedC[i]) continue;\n        // a closed pixel may belong to two colours' closings: keep the deeper one\n        if (cov[i] && D[i] >= Dc[i]) continue;\n        cov[i] = 1; pidxG[i] = c; D[i] = Dc[i]; Dorig[i] = D0c[i];\n      }\n    }\n    var g = {\n      fw: m.fw, fh: m.fh,\n      cov: cov,                             // geometry: per-colour, cracks closed\n      cov0: m.cov,                          // the artwork as uploaded\n      pidx: pidxG,                          // colour of every geometry pixel\n      pidx0: m.pidx, palette: m.palette\n    };\n    g.__D = D;\n    g.__Dorig = Dorig;\n    g.srcScale = (m.srcW || m.fw) / m.fw;   // source px per fine-mask px\n    m.__geomAcross = across;\n    m.__geom = g;\n    return g;\n  }\n\n  function lattice(pat, across) {\n    var key = pat + ':' + across + ':' + stoneMode;\n    if (latticeCache[key]) return latticeCache[key];\n    var m = geomFor(mask, across);\n    var cs = m.fw / across;                 // 3mm pitch, in fine-mask px\n    var grid = {\n      gw: across,\n      gh: m.fh / cs,\n      dots: [],\n      stats: { byMm: { 1: 0, 2: 0, 3: 0, 4: 0 }, artPx: 0, thinPx: 0 }\n    };\n\n    // Occupancy index, one bucket per 3mm cell, so no-overlap stays O(1).\n    var buckets = {};\n    function fits(px, py, r, g) {\n      var bx = (px / cs) | 0, by = (py / cs) | 0, dx, dy, arr, k, o, ox, oy, need, gg = g || GUARD;\n      for (dx = -2; dx <= 2; dx++) {\n        for (dy = -2; dy <= 2; dy++) {\n          arr = buckets[(bx + dx) + ':' + (by + dy)];\n          if (!arr) continue;\n          for (k = 0; k < arr.length; k++) {\n            o = arr[k]; ox = o.x - px; oy = o.y - py; need = (o.r + r) * gg;\n            if (ox * ox + oy * oy < need * need) return false;\n          }\n        }\n      }\n      return true;\n    }\n    var curF = -1;   // feature being laid: its colour is the stone's colour (per-colour features)\n    var curPass = 'init', passCount = {};\n    function place(px, py, r, mm) {\n      var bk = ((px / cs) | 0) + ':' + ((py / cs) | 0);\n      (buckets[bk] = buckets[bk] || []).push({ x: px, y: py, r: r, f: curF });\n      passCount[curPass] = (passCount[curPass] || 0) + 1;\n      var col = curF >= 0 && featColor[curF] !== undefined ? featColor[curF] : colorAt(m, px, py);\n      grid.dots.push({ cx: px / cs, cy: py / cs, r: (r / cs) * 0.97, c: col, mm: mm });\n      grid.stats.byMm[mm]++;\n    }\n\n    var D0 = m.__D;\n    function radiusOf2(mm) { return R_FILL * cs * (mm / 3); }\n    var r3 = radiusOf2(3);\n    // Every stone placed is 3mm (Justin 2026-09-03: \"ONLY display these as\n    // 3mm spangles\" \u2014 mixing 2mm in was muddying the render). A 2mm radius\n    // survives only as the SMALL-DETAIL yardstick: a stroke thinner than that\n    // is too fine to carry a stone; anything between gets one overhanging\n    // 3mm row, the way the vendor sets TRANSFERS.\n    var rDetail = radiusOf2(1.0);   // vendor learning set 2026-09-08: strokes are traced with overhanging stones down to ~0.5 D (1mm); only finer is 'too small'\n\n    var D = D0;\n    var Dorig = m.__Dorig || D0;\n\n    // ---- 1. Label connected FEATURES first. Every decision below is made\n    // per feature, the way the vendor's software works: NINJA is one 3mm job,\n    // the thin TRANSFERS line one 2mm job (Justin 2026-09-03, comparing our\n    // render to theirs: \"all the same size\", \"solid, single spangles\").\n    // Deciding per CELL instead mixed sizes inside one word and left holes\n    // in the thin rows.\n    var N = m.fw * m.fh;\n    var lbl, featColor, areas, thin, filled, maxD, sumD, bx0, bx1, by0, by1, sx, sy, sxx, syy, sxy, stack, nLab, si2, ax2, ay2, cur, px3, py3, i3, k3;\n    // Two labelling passes (2026-09-08 judge): a thin outline fused to a thick\n    // band (FOOTBALL's letters on their baseline band) took the band's fill\n    // treatment and vanished. Pass 1 labels by colour, measures the local\n    // half-width Hv, and classes every pixel thin (< 1.5 small stones wide) or\n    // thick; pass 2 relabels so thin and thick parts are separate features.\n    var thinClass = null, Hd, Hv, Hv0, HvMax, hy, hx, hi, labPass;\n    for (labPass = 0; labPass < 2; labPass++) {\n    lbl = new Int32Array(N).fill(-1);\n    featColor = [];\n    areas = []; thin = []; filled = []; maxD = []; sumD = []; bx0 = []; bx1 = []; by0 = []; by1 = [];\n    sx = []; sy = []; sxx = []; syy = []; sxy = [];   // moments -> each feature's own slant\n    stack = []; nLab = 0;\n    for (ay2 = 0; ay2 < m.fh; ay2++) {\n      for (ax2 = 0; ax2 < m.fw; ax2++) {\n        i3 = ay2 * m.fw + ax2;\n        if (!m.cov[i3] || lbl[i3] !== -1) continue;\n        cur = nLab++;\n        var cCur = m.pidx[i3];\n        featColor[cur] = cCur;\n        areas[cur] = 0; thin[cur] = 0; filled[cur] = 0; maxD[cur] = 0; sumD[cur] = 0;\n        sx[cur] = 0; sy[cur] = 0; sxx[cur] = 0; syy[cur] = 0; sxy[cur] = 0;\n        bx0[cur] = ax2; bx1[cur] = ax2; by0[cur] = ay2; by1[cur] = ay2;\n        stack.length = 0; stack.push(i3); lbl[i3] = cur;\n        while (stack.length) {\n          k3 = stack.pop();\n          areas[cur]++;\n          if (Dorig[k3] < rDetail) thin[cur]++;\n          if (!m.cov0[k3]) filled[cur]++;   // was background before gap closing\n          if (D[k3] > maxD[cur]) maxD[cur] = D[k3];\n          sumD[cur] += D[k3];\n          px3 = k3 % m.fw; py3 = (k3 / m.fw) | 0;\n          sx[cur] += px3; sy[cur] += py3; sxx[cur] += px3 * px3; syy[cur] += py3 * py3; sxy[cur] += px3 * py3;\n          if (px3 < bx0[cur]) bx0[cur] = px3; if (px3 > bx1[cur]) bx1[cur] = px3;\n          if (py3 < by0[cur]) by0[cur] = py3; if (py3 > by1[cur]) by1[cur] = py3;\n          var tcCur = thinClass ? thinClass[k3] : 0;\n          if (px3 > 0 && m.cov[k3 - 1] && lbl[k3 - 1] === -1 && m.pidx[k3 - 1] === cCur && (!thinClass || thinClass[k3 - 1] === tcCur)) { lbl[k3 - 1] = cur; stack.push(k3 - 1); }\n          if (px3 < m.fw - 1 && m.cov[k3 + 1] && lbl[k3 + 1] === -1 && m.pidx[k3 + 1] === cCur && (!thinClass || thinClass[k3 + 1] === tcCur)) { lbl[k3 + 1] = cur; stack.push(k3 + 1); }\n          if (py3 > 0 && m.cov[k3 - m.fw] && lbl[k3 - m.fw] === -1 && m.pidx[k3 - m.fw] === cCur && (!thinClass || thinClass[k3 - m.fw] === tcCur)) { lbl[k3 - m.fw] = cur; stack.push(k3 - m.fw); }\n          if (py3 < m.fh - 1 && m.cov[k3 + m.fw] && lbl[k3 + m.fw] === -1 && m.pidx[k3 + m.fw] === cCur && (!thinClass || thinClass[k3 + m.fw] === tcCur)) { lbl[k3 + m.fw] = cur; stack.push(k3 + m.fw); }\n        }\n      }\n    }\n\n    // ---- 2. Fill each feature with ONE size.\n    //   size:  3mm if a 3mm stone fits with room to spare, else 2mm.\n    //   style: enough width for two rows -> straight staggered lattice,\n    //          clipped to the feature (the vendor's regular rows);\n    //          otherwise ONE continuous row along the stroke's spine.\n    // Contour rows \u2014 how the vendor's software (Sierra Hotfix ERA) fills:\n    // concentric rows hugging each feature's outline, then a center line down\n    // whatever is left (Justin's Cricut sample 2026-09-03: the i is exactly\n    // four columns, the c four rings). A row is a level set of the distance\n    // transform. Every ring / center line is first TRACED into an ordered\n    // path, then stones are distributed EVENLY along it \u2014 a closed ring gets\n    // round(L / pitch) stones with no seam, an open line an inset at both\n    // ends so no stone hangs off a stroke end (the dots under TRANSFERS).\n    var NB = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]];\n    var stamp = new Int32Array(N), epoch = 0;\n    var stampRun = new Int32Array(N);   // walked pixels: run number (1-based); retired pixels: 0\n    var fwid = m.fw;\n\n    // Walk a one-pixel band into ordered runs of [x, y, x, y, ...]. A seed is\n    // usually mid-path, so each run is traced forward then backward from it.\n    var traceRuns = function (f, onBand) {\n      epoch++;\n      var x0 = Math.max(1, bx0[f]), x1 = Math.min(fwid - 2, bx1[f]);\n      var y0 = Math.max(1, by0[f]), y1 = Math.min(m.fh - 2, by1[f]);\n      var runs = [], y, x, i, runNo = 0;\n      function walk(sx, sy, out, first) {\n        var cx = sx, cy = sy, dxp = 0, dyp = 0, steps = 0, best, bestScore, k, nx, ny, ni, score, seen;\n        for (;;) {\n          stamp[cy * fwid + cx] = epoch; stampRun[cy * fwid + cx] = runNo;\n          if (!(steps === 0 && !first)) out.push(cx, cy);   // seed already in the run on the backward pass\n          best = -1; bestScore = -Infinity;\n          for (k = 0; k < 8; k++) {\n            nx = cx + NB[k][0]; ny = cy + NB[k][1];\n            if (nx < x0 || nx > x1 || ny < y0 || ny > y1) continue;\n            ni = ny * fwid + nx;\n            if (!onBand(ni)) continue;\n            // a junction is another WALKED run, not this walk's own retired\n            // lane pixels (audit: those flagged nearly every stroke end as a\n            // junction, so end insets never applied and stones hung off ends)\n            if (stamp[ni] === epoch) { if (stampRun[ni] > 0 && stampRun[ni] !== runNo) seen = true; continue; }\n            score = dxp * NB[k][0] + dyp * NB[k][1];   // keep heading the same way\n            if (score > bestScore) { bestScore = score; best = k; }\n          }\n          // the band can be two pixels wide on a diagonal: retire the parallel\n          // pixels so they do not seed a second, offset run \u2014 but not at the\n          // seed itself, whose other neighbour is the backward continuation\n          if (steps > 0) {\n            for (k = 0; k < 8; k++) {\n              if (k === best) continue;\n              nx = cx + NB[k][0]; ny = cy + NB[k][1];\n              if (nx < x0 || nx > x1 || ny < y0 || ny > y1) continue;\n              ni = ny * fwid + nx;\n              if (onBand(ni)) { stamp[ni] = epoch; stampRun[ni] = 0; }\n            }\n          }\n          if (best < 0) {\n            // bridge a one-pixel break in the band before giving up: look two\n            // pixels out, preferring the current heading\n            var jx = 0, jy = 0, jScore = -Infinity, ax, ay;\n            for (ay = -2; ay <= 2; ay++) {\n              for (ax = -2; ax <= 2; ax++) {\n                if (Math.abs(ax) < 2 && Math.abs(ay) < 2) continue;\n                nx = cx + ax; ny = cy + ay;\n                if (nx < x0 || nx > x1 || ny < y0 || ny > y1) continue;\n                ni = ny * fwid + nx;\n                if (stamp[ni] === epoch || !onBand(ni)) continue;\n                score = dxp * ax + dyp * ay;\n                if (score > jScore) { jScore = score; jx = ax; jy = ay; }\n              }\n            }\n            if (jScore === -Infinity || (dxp || dyp) && jScore <= 0) return !!seen;   // true: stopped against another run (a junction), not a stroke end\n            seen = false;\n            dxp = jx > 0 ? 1 : jx < 0 ? -1 : 0; dyp = jy > 0 ? 1 : jy < 0 ? -1 : 0;\n            cx += jx; cy += jy; steps++;\n            continue;\n          }\n          seen = false;\n          dxp = NB[best][0]; dyp = NB[best][1]; cx += dxp; cy += dyp; steps++;\n        }\n      }\n      for (y = y0; y <= y1; y++) {\n        for (x = x0; x <= x1; x++) {\n          i = y * fwid + x;\n          if (stamp[i] === epoch || !onBand(i)) continue;\n          var fwdRun = [], backRun = [];\n          runNo++;\n          var jEnd = walk(x, y, fwdRun, true);\n          var jStart = walk(x, y, backRun, false);\n          // backward half reversed, then the forward half\n          var run = [], q;\n          for (q = backRun.length - 2; q >= 0; q -= 2) run.push(backRun[q], backRun[q + 1]);\n          for (q = 0; q < fwdRun.length; q++) run.push(fwdRun[q]);\n          runs.push({ pts: run, jStart: jStart, jEnd: jEnd });\n        }\n      }\n      // Link fragments: a raster break or a retired pixel splits one path\n      // into runs whose ends sit a pixel or two apart; each split cost a\n      // stone (the two end stones collide and one is rejected). Join ends\n      // within 3px, in either orientation, until nothing joins.\n      function rev(P) { var o = [], q2; for (q2 = P.length - 2; q2 >= 0; q2 -= 2) o.push(P[q2], P[q2 + 1]); return o; }\n      function near(x1, y1, x2, y2) { return Math.abs(x1 - x2) <= 2 && Math.abs(y1 - y2) <= 2; }\n      var joinedAny = true, a, b, A, B, J;\n      while (joinedAny) {\n        joinedAny = false;\n        outer: for (a = 0; a < runs.length; a++) {\n          A = runs[a].pts; if (A.length < 4) continue;\n          for (b = a + 1; b < runs.length; b++) {\n            B = runs[b].pts; if (B.length < 4) continue;\n            var aL = A.length, bL = B.length;\n            if (near(A[aL - 2], A[aL - 1], B[0], B[1])) J = { pts: A.concat(B), jStart: runs[a].jStart, jEnd: runs[b].jEnd };\n            else if (near(A[aL - 2], A[aL - 1], B[bL - 2], B[bL - 1])) J = { pts: A.concat(rev(B)), jStart: runs[a].jStart, jEnd: runs[b].jStart };\n            else if (near(A[0], A[1], B[bL - 2], B[bL - 1])) J = { pts: B.concat(A), jStart: runs[b].jStart, jEnd: runs[a].jEnd };\n            else if (near(A[0], A[1], B[0], B[1])) J = { pts: rev(B).concat(A), jStart: runs[b].jEnd, jEnd: runs[a].jEnd };\n            else continue;\n            runs[a] = J; runs.splice(b, 1); joinedAny = true; break outer;\n          }\n        }\n      }\n      // longest first: the main run of a ring claims its phase before any\n      // leftover can drop a stray stone that blocks it (audit 2026-09-03)\n      runs.sort(function (A2, B2) { return B2.pts.length - A2.pts.length; });\n      return runs;\n    };\n\n    // Medial axis: a distance-transform pixel no lower (within the chamfer's\n    // rounding) than ANY of its eight neighbours. The old one-axis test\n    // (\"a maximum along x OR along y\") passed broad bands inside curved\n    // letters \u2014 it read the stroke width low (NINJA sized as 2mm) and handed\n    // the center line whole regions to fill (the chaotic Cricut interiors).\n    var RIDGE_TOL = 0.6;   // chamfer alternates by up to 0.41 along a diagonal ridge; 0.4 broke the axis into fragments\n    var isRidge = function (i, lo) {\n      var d = D[i];\n      if (d < lo) return false;\n      var t = d + RIDGE_TOL;\n      return t >= D[i - 1] && t >= D[i + 1] && t >= D[i - fwid] && t >= D[i + fwid] &&\n             t >= D[i - fwid - 1] && t >= D[i - fwid + 1] && t >= D[i + fwid - 1] && t >= D[i + fwid + 1];\n    };\n\n    // Local half-width: for every art pixel, the distance-to-edge of the\n    // NEAREST medial-axis pixel of its own feature (a chamfer pass that carries\n    // the seed's value along). A ring is laid only where the stroke has room\n    // for it AND its mirror ring from the other edge; where it does not, the\n    // center line owns the middle instead. Without this the two innermost\n    // rings collided and the overlap guard kept alternating survivors \u2014 the\n    // scatter inside the Cricut c and the SPANGLES letters.\n    Hd = new Float32Array(N); Hv = new Float32Array(N);\n    for (hi = 0; hi < N; hi++) { Hd[hi] = 1e9; Hv[hi] = 0; }\n    for (hy = 1; hy < m.fh - 1; hy++) {\n      for (hx = 1; hx < fwid - 1; hx++) {\n        hi = hy * fwid + hx;\n        if (lbl[hi] >= 0 && isRidge(hi, 0.5)) { Hd[hi] = 0; Hv[hi] = D[hi]; }\n      }\n    }\n    var hRelax = function (i, n, wgt) {\n      if (lbl[n] !== lbl[i]) return;\n      var c = Hd[n] + wgt;\n      if (c < Hd[i]) { Hd[i] = c; Hv[i] = Hv[n]; }\n    };\n    for (hy = 1; hy < m.fh - 1; hy++) {\n      for (hx = 1; hx < fwid - 1; hx++) {\n        hi = hy * fwid + hx;\n        if (lbl[hi] < 0) continue;\n        hRelax(hi, hi - 1, 1); hRelax(hi, hi - fwid, 1); hRelax(hi, hi - fwid - 1, 1.41421); hRelax(hi, hi - fwid + 1, 1.41421);\n      }\n    }\n    for (hy = m.fh - 2; hy >= 1; hy--) {\n      for (hx = fwid - 2; hx >= 1; hx--) {\n        hi = hy * fwid + hx;\n        if (lbl[hi] < 0) continue;\n        hRelax(hi, hi + 1, 1); hRelax(hi, hi + fwid, 1); hRelax(hi, hi + fwid - 1, 1.41421); hRelax(hi, hi + fwid + 1, 1.41421);\n      }\n    }\n\n    // Smooth the half-width map inside each feature (two 3x3 passes, same\n    // label only): the chamfer transform is ~8% rough on curves, and that\n    // roughness made ring positions flicker along the Cricut c and the S.\n    Hv0 = new Float32Array(Hv);   // raw copy: single-row bands read this (smoothing lifts Hv above D near joins)\n    var Hs = new Float32Array(N), pass, sm, cnt, ox, oy, nn;\n    for (pass = 0; pass < 4; pass++) {\n      for (hy = 1; hy < m.fh - 1; hy++) {\n        for (hx = 1; hx < fwid - 1; hx++) {\n          hi = hy * fwid + hx;\n          if (lbl[hi] < 0) { Hs[hi] = 0; continue; }\n          sm = 0; cnt = 0;\n          for (oy = -1; oy <= 1; oy++) {\n            for (ox = -1; ox <= 1; ox++) {\n              nn = hi + oy * fwid + ox;\n              if (lbl[nn] !== lbl[hi] || Hd[nn] >= 1e9) continue;\n              sm += Hv[nn]; cnt++;\n            }\n          }\n          Hs[hi] = cnt ? sm / cnt : Hv[hi];\n        }\n      }\n      for (hi = 0; hi < N; hi++) if (lbl[hi] >= 0 && Hd[hi] < 1e9) Hv[hi] = Hs[hi];\n    }\n\n    // Max-filtered half-width for ring gating (audit 2026-09-03): the nearest-\n    // ridge map takes its value from corner branches at stem ends and slab\n    // serifs, far below the stem's real half-width, and rings vanished there.\n    // A separable running max over one 3mm-stone radius fixes the gate.\n    HvMax = new Float32Array(N); var HvTmp = new Float32Array(N), rad = Math.max(2, Math.round(r3)), mx, mq, mi2;\n    for (hy = 0; hy < m.fh; hy++) {\n      for (hx = 0; hx < fwid; hx++) {\n        hi = hy * fwid + hx; mx = 0;\n        if (lbl[hi] >= 0) for (mq = Math.max(0, hx - rad); mq <= Math.min(fwid - 1, hx + rad); mq++) { mi2 = hy * fwid + mq; if (lbl[mi2] === lbl[hi] && Hv[mi2] > mx) mx = Hv[mi2]; }\n        HvTmp[hi] = mx;\n      }\n    }\n    for (hy = 0; hy < m.fh; hy++) {\n      for (hx = 0; hx < fwid; hx++) {\n        hi = hy * fwid + hx; mx = 0;\n        if (lbl[hi] >= 0) for (mq = Math.max(0, hy - rad); mq <= Math.min(m.fh - 1, hy + rad); mq++) { mi2 = mq * fwid + hx; if (lbl[mi2] === lbl[hi] && HvTmp[mi2] > mx) mx = HvTmp[mi2]; }\n        HvMax[hi] = mx;\n      }\n    }\n    if (labPass === 0) {\n      // class every art pixel: thin (< 1.5 small stones wide, by the smoothed\n      // local half-width) or thick; pass 2 will not connect the two classes.\n      // Only features that really are MIXED (15-85% thin) are worth splitting;\n      // a uniformly thin keyline or a solid letter stays whole.\n      var thinW = THIN_SPLIT_STONES * 2 * radiusOf2(2), thinCnt = new Int32Array(nLab || 1), tq;\n      thinClass = new Uint8Array(N);\n      for (tq = 0; tq < N; tq++) { if (lbl[tq] < 0) continue; if (2 * Hv[tq] < thinW) { thinClass[tq] = 1; thinCnt[lbl[tq]]++; } }\n      var mixed = new Uint8Array(nLab || 1), anyMixed = false;\n      for (tq = 0; tq < nLab; tq++) { var shr = thinCnt[tq] / (areas[tq] || 1); if (shr > 0.15 && shr < 0.85 && areas[tq] > 200) { mixed[tq] = 1; anyMixed = true; } }\n      if (!anyMixed) break;\n      for (tq = 0; tq < N; tq++) if (lbl[tq] >= 0 && !mixed[lbl[tq]]) thinClass[tq] = 0;\n      // only LONG thin parts split off (a hollow letter's outline riding a\n      // band); a short narrow neck inside an organic shape (the Wildcat's\n      // white cheeks) stays with its region \u2014 splitting those shattered the\n      // face into hundreds of specks (2026-09-08)\n      var seenT = new Uint8Array(N), stT = [], minDiag = 4 * STONE_GAP * 2 * radiusOf2(2), tqi, tqk, tqx, tqy, tbx0, tbx1, tby0, tby1, comp;\n      for (tq = 0; tq < N; tq++) {\n        if (!thinClass[tq] || seenT[tq]) continue;\n        comp = []; stT.length = 0; stT.push(tq); seenT[tq] = 1; tbx0 = tbx1 = tq % fwid; tby0 = tby1 = (tq / fwid) | 0;\n        while (stT.length) {\n          tqk = stT.pop(); comp.push(tqk); tqx = tqk % fwid; tqy = (tqk / fwid) | 0;\n          if (tqx < tbx0) tbx0 = tqx; if (tqx > tbx1) tbx1 = tqx; if (tqy < tby0) tby0 = tqy; if (tqy > tby1) tby1 = tqy;\n          if (tqx > 0 && thinClass[tqk - 1] && !seenT[tqk - 1] && lbl[tqk - 1] === lbl[tqk]) { seenT[tqk - 1] = 1; stT.push(tqk - 1); }\n          if (tqx < fwid - 1 && thinClass[tqk + 1] && !seenT[tqk + 1] && lbl[tqk + 1] === lbl[tqk]) { seenT[tqk + 1] = 1; stT.push(tqk + 1); }\n          if (tqy > 0 && thinClass[tqk - fwid] && !seenT[tqk - fwid] && lbl[tqk - fwid] === lbl[tqk]) { seenT[tqk - fwid] = 1; stT.push(tqk - fwid); }\n          if (tqy < m.fh - 1 && thinClass[tqk + fwid] && !seenT[tqk + fwid] && lbl[tqk + fwid] === lbl[tqk]) { seenT[tqk + fwid] = 1; stT.push(tqk + fwid); }\n        }\n        var diagT = Math.sqrt((tbx1 - tbx0) * (tbx1 - tbx0) + (tby1 - tby0) * (tby1 - tby0));\n        if (diagT < minDiag || comp.length < 30) { for (tqi = 0; tqi < comp.length; tqi++) thinClass[comp[tqi]] = 0; }\n      }\n      continue;\n    }\n    break;\n    }\n\n    // Per-pixel row structure, per FEATURE (its own stone size pF/rF):\n    //   k = 0  the outline ring, half a pitch in (needs room for its mirror)\n    //   k >= 1 inner rows spread EVENLY across whatever width is left between\n    //          the two outline rings \u2014 round(width / pitch) of them, squeezed\n    //          (INNER_GUARD) where the width is not a whole number of pitches.\n    // The outline rings never move, so joins stay clean; only the middle\n    // adapts, which is what the vendor's own centers look like. Justin\n    // 2026-09-03 on the N and A: \"the Ns need more fill\" \u2014 an inner row that\n    // only existed where a full pitch fit left the diagonal hollow.\n    function dkAt(i, k) {\n      var f = lbl[i];\n      if (f < 0) return -1;\n      var p = pF[f];\n      // outline ring: gated on the max-filtered width so a corner basin at a\n      // stem end cannot cut it; inner rows: positioned from the LOCAL width,\n      // because that is the width they have to fill\n      var rr = rF[f];\n      if (k === 0) return HvMax[i] >= 0.9 * p ? rr : -1;   // outline ring: stone tangent to the edge\n      // FIXED pitch inward (2026-09-08, vendor learning set): ring k sits k\n      // pitches inside the outline ring, the same level set everywhere in the\n      // feature, so rings run unbroken around corners \u2014 the UE's E reads as a\n      // grid of nested rectangles, the U's bowl as concentric arcs. Rows that\n      // were re-spaced to the local width met at different phases where an\n      // arm joins a stem and the interiors jumbled. Whatever the last ring\n      // leaves open in the middle is the gap/cover passes' job (squeezed\n      // stones, as in the vendor's own middles).\n      var dk;\n      if (featEven[f]) {\n        // UNIFORM stroke (letters, script, bands): n = round(w / p) rows spread\n        // evenly across the feature's typical width, outer rows tangent to the\n        // edge, spacing 1.0-1.4 pitch (vendor rule: 2 rows for 2-2.5 D, 3 for\n        // 2.9-4.6 D). Planned from the TYPICAL width only, so every row is one\n        // level set that runs unbroken through joins \u2014 the arms and stem of an\n        // E share rows instead of meeting at different phases.\n        var sE = featStep[f], half = featW[f] / 2;\n        dk = rr + k * sE;\n        if (dk > half - 0.45 * p) return -1;           // past the middle: the mirror row / centre row covers it\n        return dk <= HvMax[i] - 0.3 * p ? dk : -1;\n      }\n      // VARIABLE-width shape (paw, football, star): fixed-pitch rings inward\n      // from the outline; the middle is the gap/cover passes' job\n      dk = rr + k * p;\n      return dk <= HvMax[i] - 0.4 * p ? dk : -1;\n    }\n    function rAt(i) { var f = lbl[i]; return f >= 0 ? rF[f] : r3; }\n    function pitchAt(i) { var f = lbl[i]; return f >= 0 ? pF[f] : STONE_GAP * 2 * r3; }\n\n    // Ridge across the stroke (single-row center lines): a maximum along at\n    // least one of the four pixel axes (x, y, both diagonals) with at least\n    // one neighbour on that axis STRICTLY lower. The 8-neighbour test rejects\n    // any ridge pixel with a slope along it \u2014 the distance transform rises\n    // toward a junction, so every crossbar lost its last ~20px before the\n    // stem and kept only a far-end stone. The plain one-axis test admits every\n    // pixel of a flat bar (equal neighbours); the strict side rules that out.\n    function ridge1(i, lo) {\n      var d = D[i];\n      if (d < lo) return false;\n      // tight tolerance: across a stroke the distance transform changes by\n      // ~1 per pixel, so 0.15 keeps the band to the true center line; the\n      // 0.6 used for the multi-row axis let off-center pixels in via the\n      // diagonal axes and shattered every letter into dozens of runs\n      var t = d + 0.15, a, b;\n      a = D[i - 1]; b = D[i + 1];\n      if (t >= a && t >= b && (d > a + 0.3 || d > b + 0.3)) return true;\n      a = D[i - fwid]; b = D[i + fwid];\n      if (t >= a && t >= b && (d > a + 0.3 || d > b + 0.3)) return true;\n      a = D[i - fwid - 1]; b = D[i + fwid + 1];\n      if (t >= a && t >= b && (d > a + 0.3 || d > b + 0.3)) return true;\n      a = D[i - fwid + 1]; b = D[i + fwid - 1];\n      if (t >= a && t >= b && (d > a + 0.3 || d > b + 0.3)) return true;\n      return false;\n    }\n\n    // Slide a ring stone along the distance gradient so it sits EXACTLY at\n    // its ring's distance (the band is a pixel wide; a half-pixel drift is\n    // enough to fail the next ring's overlap guard).\n    function snapAt(px, py, k) {\n      var xi = px | 0, yi = py | 0;\n      if (xi < 1 || yi < 1 || xi >= fwid - 1 || yi >= m.fh - 1) return [px, py];\n      var i = yi * fwid + xi, dk = dkAt(i, k);\n      if (dk < 0) return [px, py];\n      var gx = (D[i + 1] - D[i - 1]) * 0.5, gy = (D[i + fwid] - D[i - fwid]) * 0.5;\n      var gl = Math.sqrt(gx * gx + gy * gy);\n      if (gl < 0.3) return [px, py];\n      var off = (dk - D[i]) / gl;\n      return [px + gx * off, py + gy * off];\n    }\n\n    // Distribute stones evenly along one traced run of ring k.\n    function layRun(item, k, mm) {\n      var raw = item.pts, pts = raw.length >> 1;\n      if (pts < 2) return;\n      var rSum = 0, pSum = 0, q, ii;\n      for (q = 0; q < pts; q++) { ii = raw[2 * q + 1] * fwid + raw[2 * q]; rSum += rAt(ii); pSum += pitchAt(ii); }\n      var r = rSum / pts, pitch = pSum / pts;\n      var ex0 = raw[0] - raw[2 * pts - 2], ey0 = raw[1] - raw[2 * pts - 1];\n      var closed = pts > 8 && Math.abs(ex0) <= 2 && Math.abs(ey0) <= 2;\n      // A traced band is two or three pixels wide on a diagonal, so the raw\n      // walk zigzags; a five-point moving average straightens it before the\n      // stones go down (the wobble in the TRANSFERS rows).\n      var run = new Float32Array(raw.length), a, b, w2, sx, sy, c2;\n      for (q = 0; q < pts; q++) {\n        sx = 0; sy = 0; c2 = 0;\n        for (w2 = -3; w2 <= 3; w2++) {\n          a = q + w2;\n          if (closed) a = (a + pts) % pts; else if (a < 0 || a >= pts) continue;\n          sx += raw[2 * a]; sy += raw[2 * a + 1]; c2++;\n        }\n        run[2 * q] = sx / c2; run[2 * q + 1] = sy / c2;\n      }\n      var cum = new Float32Array(pts), L = 0, i, ddx, ddy;\n      for (i = 1; i < pts; i++) {\n        ddx = run[2 * i] - run[2 * i - 2]; ddy = run[2 * i + 1] - run[2 * i - 1];\n        L += Math.sqrt(ddx * ddx + ddy * ddy); cum[i] = L;\n      }\n      var ex = run[0] - run[2 * pts - 2], ey = run[1] - run[2 * pts - 1];\n      if (closed) L += Math.sqrt(ex * ex + ey * ey) || 1;\n      // Skeleton pruning for center lines (Justin 2026-09-03): the medial axis\n      // forks toward both corners of every square stroke end and sprouts a\n      // stub at every junction \u2014 the little \"Y\" branches on the R, N and A.\n      // A dangling branch (junction at one end, free at the other) shorter\n      // than the stroke width is such a fork, not a stroke: drop it.\n      // Insets keep a stone from hanging off a stroke END; a run that stopped\n      // against another run (a junction) gets none there, so nothing goes\n      // missing where strokes meet.\n      // Only a single-row stroke has ends a stone can hang off; a ring\n      // fragment (the band broke on a raster step) is not a stroke end, and\n      // insetting it punched a hole at every break inside NINJA.\n      // A center line's free end is a corner FORK of the medial axis (the walk\n      // runs down the stem and on into one corner): trim each free end back by\n      // half the stroke width, to where the true axis ends. Junction ends are\n      // handled by the clearance walk below.\n      var endTrim = item.single ? r * 0.3 : r * 0.55;   // center lines: keep short strokes (an R's leg) whole\n      var insetA = (closed || !item.single || item.jStart) ? 0 : endTrim;\n      var insetB = (closed || !item.single || item.jEnd) ? 0 : endTrim;\n      // At a junction the run starts ON the crossing run's center line, so a\n      // stone half a step in collides with the crossing run's stone and the\n      // guard drops it \u2014 every crossbar of an E kept only its far-end stone\n      // (\"vertical dashes with dots\"). Walk in from the junction to the first\n      // point that clears the stones already placed, and start there.\n      function clearFrom(fromStart) {\n        var lim = Math.min(L * 0.6, pitch * 1.3), off, tt, kk2 = 0, segc, xa2, ya2, xb2, yb2, qx, qy;\n        for (off = 0; off <= lim; off += 2) {\n          tt = fromStart ? off : L - off;\n          if (fromStart) { while (kk2 < pts - 1 && cum[kk2 + 1] < tt) kk2++; }\n          else { kk2 = pts - 2; while (kk2 > 0 && cum[kk2] > tt) kk2--; }\n          segc = kk2 < pts - 1 ? cum[kk2 + 1] - cum[kk2] : 1;\n          var tq = segc ? (tt - cum[kk2]) / segc : 0; if (tq > 1) tq = 1; if (tq < 0) tq = 0;\n          xa2 = run[2 * kk2]; ya2 = run[2 * kk2 + 1];\n          xb2 = kk2 < pts - 1 ? run[2 * kk2 + 2] : xa2; yb2 = kk2 < pts - 1 ? run[2 * kk2 + 3] : ya2;\n          qx = xa2 + (xb2 - xa2) * tq + 0.5; qy = ya2 + (yb2 - ya2) * tq + 0.5;\n          if (fits(qx, qy, r, item.guard)) return off;\n        }\n        return lim;\n      }\n      if (!closed && item.jStart) insetA = Math.max(insetA, clearFrom(true));\n      if (!closed && item.jEnd) insetB = Math.max(insetB, clearFrom(false));\n      var span = L - insetA - insetB;\n      if (item.single && !closed && span < r * 0.4 && !item.jStart && !item.jEnd) return;   // a spur, not a stroke\n      if (span <= 0) return;\n      // a leftover under half a pitch is a walker artefact, not a row: a stone\n      // there sits at a random phase and blocks the real row's stones (audit)\n      if (!closed && span < 0.5 * pitch) return;\n      // a short spur hanging off a junction (the R's bowl meeting its stem,\n      // an A's crossbar stub) reads as a stray stone: prune under one pitch\n      if (!closed && item.single && (item.jStart || item.jEnd) && span < 1.0 * pitch) return;\n      // FLOOR the count so the spacing can never fall under the overlap\n      // guard's distance: rounding up put 4 stones on a 2.55-pitch bar at\n      // 0.85 pitch, the guard rejected every other one, and a hole was left\n      // where two stones should have been (the gaps in TRANSFERS, the ragged\n      // small inner rings).\n      // Count and spacing (audit 2026-09-03): stones are CENTER-anchored in the\n      // span \u2014 target = inset + (j + 1/2) * step \u2014 with n = round(span / pitch)\n      // so the step stays within [0.67, 1.33] pitch, then capped: a step over\n      // 1.2 pitch takes one more stone (the guard tolerates the squeeze), a\n      // step under the guard distance one fewer. The old end-anchored\n      // formula stretched m stones over a span that needed m+1 and left a\n      // stone-sized gap in every 1-2 pitch fragment \u2014 exactly the joins.\n      var gmin = (item.guard || GUARD) * pitch * 1.01;\n      var n, step;\n      if (closed) {\n        n = Math.max(1, Math.round(L / pitch));\n        if (L / n > 1.1 * pitch) n++;\n        while (n > 1 && L / n < gmin) n--;\n        step = L / n;\n      } else {\n        n = Math.max(1, Math.round(span / pitch));\n        if (span / n > 1.1 * pitch) n++;\n        while (n > 1 && span / n < gmin) n--;\n        step = span / n;\n      }\n      var j, target, k2 = 0, seg, t, xa, ya, xb, yb, px, py, sp, tryOff, t0;\n      for (j = 0; j < n; j++) {\n        t0 = closed ? j * step : insetA + (j + 0.5) * step;\n        // audit finding 2: a rejected stone used to be dropped outright; now it\n        // is retried a little further along the run before giving up\n        for (tryOff = 0; tryOff < 5; tryOff++) {\n        target = t0 + [0, 0.15, -0.15, 0.3, -0.3][tryOff] * step;\n        if (target < 0) target = 0;\n        if (target > cum[pts - 1]) target = cum[pts - 1];\n        while (k2 > 0 && cum[k2] > target) k2--;\n        while (k2 < pts - 1 && cum[k2 + 1] < target) k2++;\n        seg = k2 < pts - 1 ? cum[k2 + 1] - cum[k2] : 1;\n        t = seg ? (target - cum[k2]) / seg : 0; if (t > 1) t = 1; if (t < 0) t = 0;\n        xa = run[2 * k2]; ya = run[2 * k2 + 1];\n        xb = k2 < pts - 1 ? run[2 * k2 + 2] : xa; yb = k2 < pts - 1 ? run[2 * k2 + 3] : ya;\n        px = xa + (xb - xa) * t + 0.5; py = ya + (yb - ya) * t + 0.5;\n        if (!item.noSnap) { sp = snapAt(px, py, k); px = sp[0]; py = sp[1]; }\n        if (fits(px, py, r, item.guard)) { place(px, py, r, mm); break; }\n        }\n      }\n    }\n\n    // Outline style (Justin 2026-09-03, vendor TRANSFERS mockup): stones sit\n    // ON the letter's outline \u2014 centres on the boundary, half a stone out \u2014\n    // with a stone anchored at every corner and the rest spaced evenly\n    // between corners. A ring offset half a stone INSIDE the shape (the\n    // distance level set) rounds every corner and stroke end and read as\n    // bubble letters; the vendor's read as crisp double lines.\n    function layOutline(item, r, mm, pitch) {\n      var raw = item.pts, pts = raw.length >> 1;\n      if (pts < 3) return;\n      var ex0 = raw[0] - raw[2 * pts - 2], ey0 = raw[1] - raw[2 * pts - 1];\n      var closed = pts > 8 && Math.abs(ex0) <= 2 && Math.abs(ey0) <= 2;\n      var P = new Float32Array(raw.length), q, w2, a, sx, sy, c2, i;\n      for (q = 0; q < pts; q++) {\n        sx = 0; sy = 0; c2 = 0;\n        for (w2 = -1; w2 <= 1; w2++) { a = q + w2; if (closed) a = (a + pts) % pts; else if (a < 0 || a >= pts) continue; sx += raw[2 * a]; sy += raw[2 * a + 1]; c2++; }\n        P[2 * q] = sx / c2; P[2 * q + 1] = sy / c2;\n      }\n      // turning angle over +/- K points; corners = local maxima over ~40 deg\n      var K = 4, turn = new Float32Array(pts), i0, i1, dx0, dy0, dx1, dy1;\n      for (i = 0; i < pts; i++) {\n        i0 = i - K; i1 = i + K;\n        if (closed) { i0 = (i0 + pts) % pts; i1 = (i1 + pts) % pts; } else if (i0 < 0 || i1 >= pts) { turn[i] = 0; continue; }\n        dx0 = P[2 * i] - P[2 * i0]; dy0 = P[2 * i + 1] - P[2 * i0 + 1]; dx1 = P[2 * i1] - P[2 * i]; dy1 = P[2 * i1 + 1] - P[2 * i + 1];\n        turn[i] = Math.abs(Math.atan2(dx0 * dy1 - dy0 * dx1, dx0 * dx1 + dy0 * dy1));\n      }\n      var corners = [], lastC = -999, isMax;\n      for (i = 0; i < pts; i++) {\n        if (turn[i] < 0.7) continue;\n        isMax = true;\n        for (w2 = -K; w2 <= K; w2++) { a = i + w2; if (closed) a = (a + pts) % pts; else if (a < 0 || a >= pts) continue; if (turn[a] > turn[i]) { isMax = false; break; } }\n        if (!isMax || i - lastC < K) continue;\n        corners.push(i); lastC = i;\n      }\n      if (!closed) { if (corners.indexOf(0) < 0) corners.unshift(0); if (corners.indexOf(pts - 1) < 0) corners.push(pts - 1); }\n      var cum = new Float32Array(pts), L = 0, ddx, ddy;\n      for (i = 1; i < pts; i++) { ddx = P[2 * i] - P[2 * i - 2]; ddy = P[2 * i + 1] - P[2 * i - 1]; L += Math.sqrt(ddx * ddx + ddy * ddy); cum[i] = L; }\n      var closeLen = closed ? Math.sqrt(Math.pow(P[0] - P[2 * pts - 2], 2) + Math.pow(P[1] - P[2 * pts - 1], 2)) : 0;\n      var total = L + closeLen;\n      if (total < pitch * 0.5) return;\n      function at(t) {\n        if (t >= total) t -= total;\n        if (t >= L) { var f2 = closeLen ? (t - L) / closeLen : 0; return [P[2 * pts - 2] + (P[0] - P[2 * pts - 2]) * f2 + 0.5, P[2 * pts - 1] + (P[1] - P[2 * pts - 1]) * f2 + 0.5]; }\n        var lo = 0, hi = pts - 1, mid;\n        while (lo < hi) { mid = (lo + hi + 1) >> 1; if (cum[mid] <= t) lo = mid; else hi = mid - 1; }\n        var seg = lo < pts - 1 ? cum[lo + 1] - cum[lo] : 1, tq = seg ? (t - cum[lo]) / seg : 0;\n        var xb = lo < pts - 1 ? P[2 * lo + 2] : P[2 * lo], yb = lo < pts - 1 ? P[2 * lo + 3] : P[2 * lo + 1];\n        return [P[2 * lo] + (xb - P[2 * lo]) * tq + 0.5, P[2 * lo + 1] + (yb - P[2 * lo + 1]) * tq + 0.5];\n      }\n      var pt, n0, tA, tB, Ls, ns, j, tt;\n      if (!corners.length) {\n        n0 = Math.max(1, Math.round(total / pitch));\n        for (q = 0; q < n0; q++) { pt = at(q * total / n0); if (fits(pt[0], pt[1], r, 0.9)) place(pt[0], pt[1], r, mm); }\n        return;\n      }\n      var anchors = corners.map(function (ci) { return cum[ci]; });\n      for (q = 0; q < anchors.length; q++) { pt = at(anchors[q]); if (fits(pt[0], pt[1], r, 0.9)) place(pt[0], pt[1], r, mm); }\n      var segs = anchors.length - (closed ? 0 : 1);\n      for (q = 0; q < segs; q++) {\n        tA = anchors[q]; tB = q + 1 < anchors.length ? anchors[q + 1] : anchors[0] + total;\n        Ls = tB - tA; ns = Math.max(1, Math.round(Ls / pitch));\n        for (j = 1; j < ns; j++) { tt = tA + j * (Ls / ns); pt = at(tt); if (fits(pt[0], pt[1], r, 0.9)) place(pt[0], pt[1], r, mm); }\n      }\n    }\n\n    // Center line for thin text (Justin: \"recreate the text with 1 spangle\n    // width\"): Zhang-Suen thinning of the ORIGINAL artwork inside the\n    // feature to a 1-px skeleton, then spur pruning \u2014 a branch from a free\n    // end to a junction shorter than 0.6 x the stroke width is the medial\n    // axis forking into a square stroke end's corners, not a stroke. The\n    // ridge-band approach hooked into one corner at every stroke end.\n    function skeletonOf(f) {\n      var x0 = Math.max(1, bx0[f] - 1), x1 = Math.min(fwid - 2, bx1[f] + 1), y0 = Math.max(1, by0[f] - 1), y1 = Math.min(m.fh - 2, by1[f] + 1);\n      var W = x1 - x0 + 3, H = y1 - y0 + 3, g = new Uint8Array(W * H), x, y, i, k, n;\n      for (y = y0; y <= y1; y++) for (x = x0; x <= x1; x++) { i = y * fwid + x; if (lbl[i] === f && m.cov0[i]) g[(y - y0 + 1) * W + (x - x0 + 1)] = 1; }\n      var changed = true, pass, del = [], A, B, iter = 0, p2, p3, p4, p5, p6, p7, p8, p9;\n      while (changed && iter < 300) {\n        changed = false; iter++;\n        for (pass = 0; pass < 2; pass++) {\n          del.length = 0;\n          for (y = 1; y < H - 1; y++) {\n            for (x = 1; x < W - 1; x++) {\n              k = y * W + x; if (!g[k]) continue;\n              p2 = g[k - W]; p3 = g[k - W + 1]; p4 = g[k + 1]; p5 = g[k + W + 1]; p6 = g[k + W]; p7 = g[k + W - 1]; p8 = g[k - 1]; p9 = g[k - W - 1];\n              B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; if (B < 2 || B > 6) continue;\n              A = (!p2 && p3) + (!p3 && p4) + (!p4 && p5) + (!p5 && p6) + (!p6 && p7) + (!p7 && p8) + (!p8 && p9) + (!p9 && p2); if (A !== 1) continue;\n              if (pass === 0) { if (p2 * p4 * p6 !== 0 || p4 * p6 * p8 !== 0) continue; } else { if (p2 * p4 * p8 !== 0 || p2 * p6 * p8 !== 0) continue; }\n              del.push(k);\n            }\n          }\n          for (n = 0; n < del.length; n++) g[del[n]] = 0;\n          if (del.length) changed = true;\n        }\n      }\n      function nbrs(kk) { var c = 0, dd; for (dd = 0; dd < 8; dd++) if (g[kk + NB[dd][1] * W + NB[dd][0]]) c++; return c; }\n      var minLen = 0.6 * featW[f], round, ends, path, cur, prev, nb, dd, kk, guard, q2;\n      for (round = 0; round < 2; round++) {\n        ends = [];\n        for (y = 1; y < H - 1; y++) for (x = 1; x < W - 1; x++) { k = y * W + x; if (g[k] && nbrs(k) === 1) ends.push(k); }\n        for (n = 0; n < ends.length; n++) {\n          if (!g[ends[n]]) continue;\n          path = []; cur = ends[n]; prev = -1; guard = 0;\n          for (;;) {\n            path.push(cur);\n            nb = [];\n            for (dd = 0; dd < 8; dd++) { kk = cur + NB[dd][1] * W + NB[dd][0]; if (g[kk] && kk !== prev && path.indexOf(kk) < 0) nb.push(kk); }\n            if (nb.length !== 1 || ++guard > 5000) break;\n            prev = cur; cur = nb[0];\n            if (nbrs(cur) >= 3) { nb = [cur]; break; }     // reached a junction: stop before it\n          }\n          // prune only a branch that ends at a junction (a fork), never an isolated stroke \u2014\n          // and never a branch that CONTINUES another branch through the junction: at\n          // the top of an N the short piece above the diagonal's junction is the stem's\n          // own tip (Justin: \"N is still looking weird\"), not a corner spur.\n          if (path.length < minLen && nb.length === 1 && cur !== path[path.length - 1] && nbrs(cur) >= 3) {\n            var jx = cur % W, jy = (cur / W) | 0, ex2 = path[0] % W, ey2 = (path[0] / W) | 0;\n            var sdx = ex2 - jx, sdy = ey2 - jy, sl = Math.sqrt(sdx * sdx + sdy * sdy) || 1; sdx /= sl; sdy /= sl;\n            var continues = false, dd2, kk2, wx, wy, wprev, wcur, wsteps, wnb, wdd, wkk, vdx, vdy, vl;\n            for (dd2 = 0; dd2 < 8 && !continues; dd2++) {\n              kk2 = cur + NB[dd2][1] * W + NB[dd2][0];\n              if (!g[kk2] || path.indexOf(kk2) >= 0) continue;\n              // walk ~8px along this other branch and take its direction from the junction\n              wprev = cur; wcur = kk2;\n              for (wsteps = 0; wsteps < 8; wsteps++) {\n                wnb = -1;\n                for (wdd = 0; wdd < 8; wdd++) { wkk = wcur + NB[wdd][1] * W + NB[wdd][0]; if (g[wkk] && wkk !== wprev && wkk !== cur) { if (wnb === -1) wnb = wkk; else { wnb = -2; break; } } }\n                if (wnb < 0) break;\n                wprev = wcur; wcur = wnb;\n              }\n              wx = wcur % W; wy = (wcur / W) | 0; vdx = wx - jx; vdy = wy - jy; vl = Math.sqrt(vdx * vdx + vdy * vdy) || 1; vdx /= vl; vdy /= vl;\n              // the spur is a continuation if it points opposite to this branch (angle > 150 deg)\n              if (sdx * vdx + sdy * vdy < -0.85) continues = true;\n            }\n            if (!continues) for (q2 = 0; q2 < path.length; q2++) g[path[q2]] = 0;\n          }\n        }\n      }\n      var out = new Uint8Array(N);\n      for (y = 1; y < H - 1; y++) for (x = 1; x < W - 1; x++) if (g[y * W + x]) out[(y + y0 - 1) * fwid + (x + x0 - 1)] = 1;\n      return out;\n    }\n\n    // Ring k of a feature: the pixels one raster step around its ring\n    // distance, traced and laid. Returns false once the feature has no k-th row.\n    function ringPass(f, k) {\n      var mm = featMm[f], runs, q;\n      if (featStyle[f] === 'outline') {\n        if (k > 0) return false;\n        // The ORIGINAL glyph boundary (Dorig), not the gap-closed mask: closing\n        // with a 2mm disc rounds every inside corner and swallows small\n        // counters \u2014 the R's bowl and the A's hole came out as blobs. Stones\n        // spaced ~1.8 diameters apart, as in the vendor's mockup: a dotted\n        // line reads thin and crisp where a touching row reads inflated.\n        runs = traceRuns(f, function (i) { return lbl[i] === f && Dorig[i] >= 0.5 && Dorig[i] < 1.5; });\n        for (q = 0; q < runs.length; q++) layOutline(runs[q], rF[f], mm, pF[f] * OUTLINE_SPACING);\n        return false;\n      }\n      if (featNf[f] === 1 && featStyle[f] !== 'outline') {\n        if (k > 0) return false;\n        // Single-row element: one-axis ridge (a maximum along x OR y) at least\n        // 0.6 r deep \u2014 the center line of a stroke from ~1.2 r wide up, stones\n        // overhanging a stroke thinner than themselves like the vendor's\n        // TRANSFERS. No snapping, insets at true stroke ends.\n        // Audit 2026-09-03: the one-axis local-max test admits EVERY pixel of a\n        // straight bar (D is constant along the stroke), so the \"row\" was the\n        // whole stroke, shredded into crossbars. The raw top band \u2014 within a\n        // raster step of the nearest ridge's D \u2014 is 1-2px wide on straight\n        // strokes and continuous through joins.\n        // depth floor 0.3 r: the thin horizontals of small italic text are\n        // narrower than the stone and the vendor still runs a row of stones\n        // down them (overhanging); 0.6 r dropped every crossbar of TRANSFERS\n        // 1px floor only: the small-detail audit already decides what is too\n        // thin to hold a stone; any higher floor here silently dropped the\n        // crossbars of small italic text (measured: bars 5-6px wide at 3mm)\n        var skel = skeletonOf(f);\n        runs = traceRuns(f, function (i) { return skel[i] === 1; });\n        // A thinned skeleton stops about half a stroke short of every stroke\n        // end (where its corner forks were pruned), so stems and diagonals\n        // ended soft and an N read rounded. Extend each free end straight\n        // along its own direction until it leaves the artwork, so the row\n        // runs into the corner like the vendor's.\n        var maxExt = Math.max(4, 0.7 * featW[f]);\n        function extendEnd(pts2, atStart) {\n          var np = pts2.length >> 1, K2 = Math.min(6, np - 1);\n          if (np < 3) return pts2;\n          var ax, ay, bx2, by2;\n          if (atStart) { ax = pts2[2 * K2]; ay = pts2[2 * K2 + 1]; bx2 = pts2[0]; by2 = pts2[1]; }\n          else { ax = pts2[2 * (np - 1 - K2)]; ay = pts2[2 * (np - 1 - K2) + 1]; bx2 = pts2[2 * np - 2]; by2 = pts2[2 * np - 1]; }\n          var dx = bx2 - ax, dy = by2 - ay, len = Math.sqrt(dx * dx + dy * dy);\n          if (len < 1) return pts2;\n          dx /= len; dy /= len;\n          var ext = [], cx2 = bx2, cy2 = by2, st, xi, yi, ii;\n          for (st = 1; st <= maxExt; st++) {\n            cx2 += dx; cy2 += dy; xi = Math.round(cx2); yi = Math.round(cy2);\n            if (xi < 1 || yi < 1 || xi >= fwid - 1 || yi >= m.fh - 1) break;\n            ii = yi * fwid + xi;\n            if (lbl[ii] !== f || !m.cov0[ii]) break;\n            ext.push(xi, yi);\n          }\n          if (!ext.length) return pts2;\n          if (atStart) { var rev2 = []; for (st = ext.length - 2; st >= 0; st -= 2) rev2.push(ext[st], ext[st + 1]); return rev2.concat(pts2); }\n          return pts2.concat(ext);\n        }\n        for (q = 0; q < runs.length; q++) {\n          var rp = runs[q].pts, np2 = rp.length >> 1;\n          var closedRun = np2 > 8 && Math.abs(rp[0] - rp[2 * np2 - 2]) <= 2 && Math.abs(rp[1] - rp[2 * np2 - 1]) <= 2;\n          if (closedRun) continue;\n          if (!runs[q].jStart) rp = extendEnd(rp, true);\n          if (!runs[q].jEnd) rp = extendEnd(rp, false);\n          runs[q].pts = rp;\n        }\n        var before = grid.dots.length;\n        featRuns[f] = runs.map(function (rr) { return rr.pts.length >> 1; });\n        for (q = 0; q < runs.length; q++) { runs[q].noSnap = true; runs[q].single = true; runs[q].f = f; layRun(runs[q], 0, mm); }\n        featPlaced[f] = grid.dots.length - before;\n        return false;\n      }\n      runs = traceRuns(f, function (i) {\n        if (lbl[i] !== f) return false;\n        var dk = dkAt(i, k);\n        return dk >= 0 && Math.abs(D[i] - dk) <= 0.75;\n      });\n      for (q = 0; q < runs.length; q++) { runs[q].guard = k === 0 ? GUARD : INNER_GUARD; layRun(runs[q], k, mm); }\n      return runs.length > 0;\n    }\n    // Last pass for a multi-row element: the distance transform's top band\n    // (its local maximum), laid with the loose guard so it only lands where\n    // the rows left something open \u2014 a serif or join too thin for the\n    // outline ring, a channel the inner rows missed.\n    function centerPass(f) {\n      var mm = featMm[f], lo = rF[f] * 0.6;\n      var pW = pF[f], runs, q;\n      if (featEven[f]) {\n        // the middle row IS the medial axis where the LOCAL row count is odd\n        // (round(width / spacing)); where it is even the two innermost rows\n        // already meet. Feature-wide parity misfired on a merged U+E whose\n        // stems hold 11 rows and arms 6.\n        var sE = featStep[f];\n        runs = traceRuns(f, function (i) {\n          if (lbl[i] !== f || Hv[i] < lo || Math.abs(D[i] - Hv[i]) > 0.75) return false;\n          return Math.round(2 * Hv[i] / sE) % 2 === 1;\n        });\n        // a planned middle row squeezes (up to ~22% overlap) rather than leave\n        // the stroke hollow: Justin's script letters must read filled\n        for (q = 0; q < runs.length; q++) { runs[q].noSnap = true; runs[q].guard = CENTER_GUARD; layRun(runs[q], 0, mm); }\n        return;\n      }\n      runs = traceRuns(f, function (i) { return lbl[i] === f && Hv[i] >= lo && (2 * Hv[i] - 2 * pW) < 0.6 * pW && Math.abs(D[i] - Hv[i]) <= 0.75; });\n      for (q = 0; q < runs.length; q++) { runs[q].noSnap = true; runs[q].guard = FILL_GUARD; layRun(runs[q], 0, mm); }\n    }\n\n    // Typical stroke width of a feature: twice the MEDIAN distance-to-edge\n    // along its medial axis (the stems, not the serifs and stroke ends).\n    var featIQR = [];   // spread of the stroke width along the medial axis (uniform stroke vs blob)\n    function ridgeWidth(f) {\n      var vals = [], x0 = Math.max(1, bx0[f]), x1 = Math.min(fwid - 2, bx1[f]);\n      var y0 = Math.max(1, by0[f]), y1 = Math.min(m.fh - 2, by1[f]), lo = r3 * 0.6, y, x, i;\n      for (y = y0; y <= y1; y++) {\n        for (x = x0; x <= x1; x++) {\n          i = y * fwid + x;\n          if (lbl[i] !== f || !isRidge(i, lo)) continue;\n          vals.push(D[i]);\n        }\n      }\n      if (!vals.length) { featIQR[f] = 0; return 0; }\n      vals.sort(function (a, b) { return a - b; });\n      var med = vals[vals.length >> 1];\n      featIQR[f] = med ? (vals[(vals.length * 3) >> 2] - vals[vals.length >> 2]) / med : 0;\n      return 2 * med;\n    }\n\n    // ---- 2. Stone size PER ELEMENT (Justin 2026-09-03: \"3 or 2mm but it\n    // should take over the whole element that it's filling \u2014 NINJA 3mm,\n    // TRANSFERS 2mm\"). A feature is 2mm when it is small text (under\n    // SMALL_TEXT_H 3mm-stones tall) or its stroke cannot hold two 3mm rows;\n    // otherwise 3mm. Each size's pitch is then nudged (max +/-15%) so that\n    // size's typical multi-row stroke is a whole number of rows \u2014 what a\n    // designer does in ERA by picking the stone to fit the stroke.\n    var pitch3 = STONE_GAP * 2 * radiusOf2(3), pitch2 = STONE_GAP * 2 * radiusOf2(2);\n    var pxPerMm = cs / 3;                                    // mask px per mm at the chosen print size\n    var featW = [], featMm = [], featNf = [], rF = [], pF = [], featH3 = [], featRuns = [], featPlaced = [], featSingle = [], featGrp = [], featStyle = [];\n    var wMmA = [], hMmA = [], gid = [];\n    for (si2 = 0; si2 < nLab; si2++) {\n      var meanD0 = areas[si2] ? sumD[si2] / areas[si2] : 0;\n      featW[si2] = ridgeWidth(si2) || Math.min(4 * meanD0, 2 * maxD[si2]);\n      featH3[si2] = (by1[si2] - by0[si2] + 1) / pitch3;   // height in 3mm stones (stats)\n      wMmA[si2] = featW[si2] / pxPerMm; hMmA[si2] = (by1[si2] - by0[si2] + 1) / pxPerMm;\n      gid[si2] = si2;\n    }\n    // group elements that share a text line: vertical overlap of half the\n    // smaller height and heights within 60% of each other\n    function gFind(a) { while (gid[a] !== a) { gid[a] = gid[gid[a]]; a = gid[a]; } return a; }\n    var ga, gb, ha, hb, ovl, ra, rb;\n    for (ga = 0; ga < nLab; ga++) {\n      if (areas[ga] < 8) continue;\n      for (gb = ga + 1; gb < nLab; gb++) {\n        if (areas[gb] < 8) continue;\n        ha = by1[ga] - by0[ga] + 1; hb = by1[gb] - by0[gb] + 1;\n        ovl = Math.min(by1[ga], by1[gb]) - Math.max(by0[ga], by0[gb]) + 1;\n        if (ovl >= 0.5 * Math.min(ha, hb) && Math.max(ha, hb) <= 1.6 * Math.min(ha, hb)) {\n          ra = gFind(ga); rb = gFind(gb); if (ra !== rb) gid[rb] = ra;\n        }\n      }\n    }\n    // per group: area-weighted median stroke and height decide for every member\n    var groups = {};\n    for (si2 = 0; si2 < nLab; si2++) { var gr = gFind(si2); featGrp[si2] = gr; (groups[gr] = groups[gr] || []).push(si2); }\n    function wMedian(list, vals) {\n      var srt = list.slice().sort(function (a, b) { return vals[a] - vals[b]; }), tot = 0, acc = 0, q;\n      for (q = 0; q < srt.length; q++) tot += areas[srt[q]];\n      for (q = 0; q < srt.length; q++) { acc += areas[srt[q]]; if (acc >= tot / 2) return vals[srt[q]]; }\n      return vals[srt[srt.length - 1]];\n    }\n    // ONE stone size for the whole design (2026-09-08, vendor learning set):\n    // every vendor mockup uses a single size \u2014 ~3mm as the workhorse, small\n    // stones throughout when the design is mostly narrow strokes (Catalyst).\n    // Mixing sizes inside one design (the Wildcat at 3mm + 4mm) read as chaos.\n    // 3mm unless a real share of the art is strokes two 3mm rows cannot fill\n    // or small text; then the whole design is 2mm. Never 4mm automatically.\n    var narrowArea = 0, totalArea = 0, gq;\n    for (gq = 0; gq < nLab; gq++) {\n      totalArea += areas[gq];\n      if (wMmA[gq] < FILL_2MM_MAX || hMmA[gq] < SMALL_TEXT_MM) narrowArea += areas[gq];\n    }\n    var designMm = (totalArea && narrowArea / totalArea >= DESIGN_2MM_SHARE) ? 2 : 3;\n    if (stoneMode >= 1 && stoneMode <= 4) designMm = stoneMode;\n    grid.stats.designMm = designMm;\n    grid.stats.narrowShare = totalArea ? +(narrowArea / totalArea).toFixed(3) : 0;\n    Object.keys(groups).forEach(function (key) {\n      var list = groups[key], q, fq;\n      // A group decides together only when it reads as a LINE OF TEXT: three\n      // or more members laid out wide (union box at least 2.5x wider than\n      // tall) and under 25mm tall. The Wildcat's face chained into one group\n      // through overlapping heights and its whole white fill inherited the\n      // narrow members' small stone (2026-09-08).\n      var ux0 = Infinity, ux1 = -Infinity, uy0 = Infinity, uy1 = -Infinity;\n      for (q = 0; q < list.length; q++) { fq = list[q]; if (bx0[fq] < ux0) ux0 = bx0[fq]; if (bx1[fq] > ux1) ux1 = bx1[fq]; if (by0[fq] < uy0) uy0 = by0[fq]; if (by1[fq] > uy1) uy1 = by1[fq]; }\n      var textLike = list.length >= 3 && (ux1 - ux0 + 1) >= 2.5 * (uy1 - uy0 + 1) && (uy1 - uy0 + 1) / pxPerMm <= 25;\n      var wGroup = wMedian(list, wMmA);\n      // single centre row only for a stroke under ~1.75 stones wide (a keyline,\n      // thin script); anything that can hold two rows gets outline ring + rows,\n      // which is what the vendor does with Catalyst's 2-3 stone interiors\n      // per ELEMENT (Justin 2026-09-03: one size per element, never mixed inside\n      // one): thin single-row elements \u2014 keylines, outlines, thin script \u2014 take\n      // the small stone; filled elements the design size. The vendor's two-size\n      // mode (Wildcat, Concord: small rings and lines, large fills).\n      for (q = 0; q < list.length; q++) {\n        fq = list[q];\n        var wG = textLike ? wGroup : wMmA[fq];\n        var single = wG < SINGLE_ROW_STONES * designMm;\n        // a fill whose WIDEST point is under ~2.5 large stones (7.5mm) is laid\n        // in the small stone too \u2014 three rows of 2mm read solid where two rows\n        // of 3mm leave a hollow channel (Catalyst interiors, the Wildcats\n        // script). The vendor's own test is the max distance-to-edge, so the\n        // Wildcat's cheeks (10mm at their widest, narrow branches elsewhere)\n        // keep the large stone like the vendor's fills do.\n        var wMax = 2 * maxD[fq] / pxPerMm;\n        var mmEl = single ? 2 : (wMax < NARROW_FILL_MM ? 2 : designMm);\n        // isolated uniform FRAME / border stroke (long, constant width, its own\n        // feature, up to ~5.8mm): ONE row of 3mm rather than 2-3 rows of 2mm \u2014\n        // the vendor's Catalyst box. Letters and script (varying width, short\n        // paths) keep their rows.\n        var isFrame = !single && wG >= 3.4 && featIQR[fq] < 0.2 && wG <= FRAME_3MM_MAX_MM && areas[fq] > 25 * featW[fq] * featW[fq];\n        if (isFrame) { single = true; mmEl = 3; }\n        // an isolated single-row line in a 3mm design takes the 3mm stone from\n        // ~1.8mm up (vendor: the Concord heart frame); finer lines stay 2mm\n        if (single && !isFrame && designMm === 3 && wG >= LINE_3MM_MIN_MM && !textLike) mmEl = 3;\n        if (stoneMode >= 1 && stoneMode <= 4) mmEl = stoneMode;\n        featSingle[fq] = single;\n        featStyle[fq] = single ? 'center' : 'fill';\n        featMm[fq] = mmEl;\n      }\n    });\n    // Nominal pitch only (audit 2026-09-03): the earlier +/-15% \"nudge\" that\n    // fitted a whole number of rows also rescaled the DRAWN stone, so a 3mm\n    // stone rendered anywhere from 2.55 to 3.45mm and every threshold moved\n    // with it. Leftover width is the inner rows' and center line's job.\n    var pitchOf = { 1: STONE_GAP * 2 * radiusOf2(1), 2: pitch2, 3: pitch3, 4: STONE_GAP * 2 * radiusOf2(4) }, sizeCount = { 1: 0, 2: 0, 3: 0, 4: 0 };\n    var featEven = [], featStep = [], featRows = [];\n    for (si2 = 0; si2 < nLab; si2++) {\n      pF[si2] = pitchOf[featMm[si2]]; rF[si2] = radiusOf2(featMm[si2]);   // drawn radius is the physical stone; pF carries the bead gap\n      sizeCount[featMm[si2]] += areas[si2];\n      // even-spread planning for uniform strokes: width spread along the axis\n      // under 35% of the median, at least two rows wide\n      var pE = pF[si2], wE = featW[si2], dE = 2 * rF[si2], nR = Math.max(2, Math.round(wE / pE)), stepE = nR > 1 ? (wE - dE) / (nR - 1) : pE;\n      while (nR > 2 && stepE < 0.87 * pE) { nR--; stepE = (wE - dE) / (nR - 1); }   // 0.87 p = touching stones\n      if (stepE > 1.25 * pE) { nR++; stepE = (wE - dE) / (nR - 1); }\n      featEven[si2] = !featSingle[si2] && featIQR[si2] < 0.35 && wE >= 1.9 * pE;\n      featStep[si2] = Math.max(0.87 * pE, Math.min(1.25 * pE, stepE));\n      featRows[si2] = nR;\n      // rows: small text \u2014 judged at the 3mm scale, so a 2mm element that is\n      // small text stays ONE row of 2mm (the vendor's TRANSFERS), not four\n      // rows because it is \"tall\" in its own smaller stones \u2014 or a stroke\n      // under SINGLE_ROW_MAX stones wide is one row; else rows by width\n      featNf[si2] = featSingle[si2] ? 1 : Math.max(2, Math.round(featW[si2] / pF[si2]));\n    }\n    grid.stats.stoneMm = stoneMode || 'auto';\n    grid.stats.sizeArea = sizeCount;\n    grid.stats.pitchAdj = 1;\n    grid.stats.feats = [];\n    for (si2 = 0; si2 < nLab; si2++) {\n      grid.stats.feats.push({ w: +(featW[si2] / pF[si2]).toFixed(2), wmm: +wMmA[si2].toFixed(1), hmm: +hMmA[si2].toFixed(1), grp: featGrp[si2], style: featStyle[si2], mm: featMm[si2], nf: featNf[si2], area: areas[si2], color: featColor[si2], even: !!featEven[si2], rows: featRows[si2], iqr: +(featIQR[si2] || 0).toFixed(2),\n        h: +((by1[si2] - by0[si2] + 1) / pF[si2]).toFixed(1),\n        thin: +(thin[si2] / (areas[si2] || 1)).toFixed(2), filled: +(filled[si2] / (areas[si2] || 1)).toFixed(2), maxD: +maxD[si2].toFixed(1) });\n    }\n    grid.stats.featRuns = featRuns; grid.stats.featPlaced = featPlaced;\n\n    // Gap fill (Justin 2026-09-03: \"make sure you are not just leaving out\n    // parts of the design\"): after the rows, scan a multi-row element on a\n    // half-radius grid for any spot inside the shape where a stone still\n    // fits \u2014 deepest spots first, 15% overlap allowed \u2014 and place it. Rows\n    // stay straight; whatever they missed at a join or an odd width is\n    // covered instead of left as air. Single-row elements are skipped: their\n    // sparseness is the point.\n    function gapFill(f) {\n      var mm = featMm[f], r = rF[f], step = Math.max(1, Math.floor(r / 2));\n      var x0 = Math.max(1, bx0[f]), x1 = Math.min(fwid - 2, bx1[f]), y0 = Math.max(1, by0[f]), y1 = Math.min(m.fh - 2, by1[f]);\n      var cand = [], y, x, i;\n      for (y = y0; y <= y1; y += step) {\n        for (x = x0; x <= x1; x += step) {\n          i = y * fwid + x;\n          if (lbl[i] !== f || D[i] < r * 0.95) continue;\n          cand.push(i);\n        }\n      }\n      cand.sort(function (a, b) { return D[b] - D[a]; });\n      for (var q = 0; q < cand.length; q++) {\n        i = cand[q];\n        var px = (i % fwid) + 0.5, py = ((i / fwid) | 0) + 0.5;\n        if (nearestAir(px, py) < r * HOLE_MIN_AIR) continue;     // a row seam, not a hole\n        if (fits(px, py, r, FILL_GUARD)) place(px, py, r, mm);\n      }\n    }\n\n    // distance from a point to the nearest stone EDGE (bucket index)\n    function nearestAir(px, py) {\n      var bx = (px / cs) | 0, by = (py / cs) | 0, dx, dy, arr, k, o, ox, oy, best = Infinity, dd;\n      for (dx = -2; dx <= 2; dx++) {\n        for (dy = -2; dy <= 2; dy++) {\n          arr = buckets[(bx + dx) + ':' + (by + dy)];\n          if (!arr) continue;\n          for (k = 0; k < arr.length; k++) { o = arr[k]; ox = o.x - px; oy = o.y - py; dd = Math.sqrt(ox * ox + oy * oy) - o.r; if (dd < best) best = dd; }\n        }\n      }\n      return best;\n    }\n    // Coverage pass (Justin 2026-09-03: \"keep it solid by using different sized\n    // spangles\"): every interior point still showing air gets the LARGEST\n    // stone that fits there without overlapping \u2014 the element's own size\n    // first, then 2mm, then 1mm tucked into the last slivers. This is how an\n    // operator solidifies a fill; the rows stay straight and the middle reads\n    // solid instead of open. Deepest points first.\n    var SIZES_DESC = [4, 3, 2];              // 2mm is the smallest stone that exists\n    function coverFill(f) {\n      var mmTop = featMm[f], rTop = rF[f], rMin = radiusOf2(2), step = Math.max(1, Math.floor(rMin / 2));\n      var x0 = Math.max(1, bx0[f]), x1 = Math.min(fwid - 2, bx1[f]), y0 = Math.max(1, by0[f]), y1 = Math.min(m.fh - 2, by1[f]);\n      var cand = [], y, x, i, q, si, mmv, rt, px, py;\n      for (y = y0; y <= y1; y += step) {\n        for (x = x0; x <= x1; x += step) {\n          i = y * fwid + x;\n          if (lbl[i] !== f || D[i] < rMin * 0.8) continue;\n          cand.push(i);\n        }\n      }\n      cand.sort(function (a, b) { return D[b] - D[a]; });\n      for (q = 0; q < cand.length; q++) {\n        i = cand[q]; px = (i % fwid) + 0.5; py = ((i / fwid) | 0) + 0.5;\n        if (nearestAir(px, py) < rTop * HOLE_MIN_AIR) continue;     // a row seam, not a hole (vendor: never squeeze)\n        // Justin 2026-09-03: \"still have gaps\" \u2014 with 2mm the smallest stone,\n        // sub-stone air can only be closed by letting stones overlap; the\n        // vendor's own middles are squeezed. Element size first, then 2mm,\n        // overlap up to ~35%.\n        for (si = 0; si < SIZES_DESC.length; si++) {\n          mmv = SIZES_DESC[si];\n          if (mmv > mmTop) continue;\n          rt = radiusOf2(mmv);\n          if (D[i] < rt * 0.9) continue;                     // would poke out of the shape\n          if (fits(px, py, rt, COVER_GUARD)) { place(px, py, rt, mmv); break; }\n        }\n      }\n    }\n\n    // ---- rows, outline inward, until the element has no deeper row; then\n    // the top band for whatever the rows left open; then fill any gap\n    // Vendor placement order (2026-09-08): single-row strokes of every colour\n    // first (keylines, outlines, thin script), then the outline ring of every\n    // filled shape, then interior rows, then the middles and fillers. Later\n    // stages conform to what is already down \u2014 a ring is interrupted where a\n    // keyline of another colour crosses it, never the other way round.\n    var kk, ringOpen = new Uint8Array(nLab || 1), anyOpen;\n    // Tiny features (2026-09-08 judge): a counter or sliver under ~3 stone\n    // areas is not outlined \u2014 the vendor drops it or, if a stone fits, sets\n    // ONE stone at its deepest point (dots, tear drops).\n    var tinyFlag = new Uint8Array(nLab || 1);\n    curPass = 'tiny';\n    for (si2 = 0; si2 < nLab; si2++) {\n      var rT = rF[si2], stoneArea = Math.PI * rT * rT;\n      if (areas[si2] >= 3 * stoneArea) continue;\n      tinyFlag[si2] = 1;\n      if (maxD[si2] < 0.75 * rT) continue;\n      var bestI = -1, bestD = -1, ty, tx, ti;\n      for (ty = by0[si2]; ty <= by1[si2]; ty++) for (tx = bx0[si2]; tx <= bx1[si2]; tx++) { ti = ty * fwid + tx; if (lbl[ti] === si2 && D[ti] > bestD) { bestD = D[ti]; bestI = ti; } }\n      if (bestI >= 0) { curF = si2; var tpx = (bestI % fwid) + 0.5, tpy = ((bestI / fwid) | 0) + 0.5; if (fits(tpx, tpy, rT, 0.9)) place(tpx, tpy, rT, featMm[si2]); }\n    }\n    curPass = 'stroke';\n    for (si2 = 0; si2 < nLab; si2++) { if (featNf[si2] === 1 && !tinyFlag[si2]) { curF = si2; ringPass(si2, 0); } }\n    curPass = 'ring0';\n    for (si2 = 0; si2 < nLab; si2++) { if (featNf[si2] >= 2 && !tinyFlag[si2]) { curF = si2; ringOpen[si2] = ringPass(si2, 0) ? 1 : 0; } }\n    curPass = 'rows';\n    for (kk = 1; kk < 64; kk++) {\n      anyOpen = false;\n      for (si2 = 0; si2 < nLab; si2++) {\n        if (featNf[si2] < 2 || !ringOpen[si2]) continue;\n        curF = si2;\n        if (ringPass(si2, kk)) anyOpen = true; else ringOpen[si2] = 0;\n      }\n      if (!anyOpen) break;\n    }\n    for (si2 = 0; si2 < nLab; si2++) {\n      if (featNf[si2] < 2 || tinyFlag[si2]) continue;\n      curF = si2;\n      curPass = 'center'; centerPass(si2);\n      curPass = 'gap'; gapFill(si2);\n      curPass = 'cover'; coverFill(si2);\n    }\n    curF = -1;\n    grid.stats.passCount = passCount;\n    // overlap audit: share of stones whose nearest neighbour sits closer than\n    // 0.85 x the sum of radii (a visibly squeezed pair)\n    (function () {\n      var tight = 0, total = 0, bkKey, arr, q1, q2, o1, o2, dx, dy, dd, need, bx, by, ax, ay, arr2;\n      for (bkKey in buckets) {\n        arr = buckets[bkKey]; bx = +bkKey.split(':')[0]; by = +bkKey.split(':')[1];\n        for (q1 = 0; q1 < arr.length; q1++) {\n          o1 = arr[q1]; total++;\n          var isTight = false;\n          for (ax = -1; ax <= 1 && !isTight; ax++) for (ay = -1; ay <= 1 && !isTight; ay++) {\n            arr2 = buckets[(bx + ax) + ':' + (by + ay)]; if (!arr2) continue;\n            for (q2 = 0; q2 < arr2.length; q2++) {\n              o2 = arr2[q2]; if (o2 === o1) continue;\n              dx = o1.x - o2.x; dy = o1.y - o2.y; dd = Math.sqrt(dx * dx + dy * dy); need = 0.85 * (o1.r + o2.r);\n              if (dd < need) { isTight = true; break; }\n            }\n          }\n          if (isTight) tight++;\n        }\n      }\n      grid.stats.tightShare = total ? +(tight / total).toFixed(3) : 0;\n    })();\n\n    // ---- 3. Audit on the same labels: stones per feature, and features whose\n    // own (unclosed) artwork is almost entirely thinner than a 2mm stone \u2014\n    // the words inside a tiny logo, a tagline under a bold mark. Those still\n    // collect a blob of stones, so a count test never sees them; per feature\n    // the thinness test is exactly right, and gap closing is read AROUND\n    // (Dorig) because it solidifies a tiny mark into a blob first.\n    var hit = new Uint32Array(nLab || 1);\n    for (si2 = 0; si2 < grid.dots.length; si2++) {\n      var dd2 = grid.dots[si2];\n      var lx = (dd2.cx * cs) | 0, ly = (dd2.cy * cs) | 0;\n      if (lx < 0 || ly < 0 || lx >= m.fw || ly >= m.fh) continue;\n      var ll = lbl[ly * m.fw + lx];\n      if (ll >= 0) hit[ll]++;\n    }\n    var artArea = 0, vanished = 0, zeroFeatures = 0, smallFeatures = 0, smallArea = 0, minFeature = 8;\n    var smallFlag = new Uint8Array(nLab || 1);\n    for (si2 = 0; si2 < nLab; si2++) {\n      artArea += areas[si2];\n      if (areas[si2] < minFeature) continue;\n      if (hit[si2] < 2) { vanished += areas[si2]; if (!hit[si2]) zeroFeatures++; }\n      // a LONG thin feature is a line or an outline (FOOTBALL's hollow letters,\n      // a keyline) \u2014 the vendor traces those with a single row whatever their\n      // thinness; only a short thin speck is small detail\n      var diagF = Math.sqrt(Math.pow(bx1[si2] - bx0[si2], 2) + Math.pow(by1[si2] - by0[si2], 2));\n      var isLine = diagF >= 4 * pitch3 && thin[si2] / areas[si2] >= FEATURE_THIN_MAX;\n      if (!isLine && (thin[si2] / areas[si2] >= FEATURE_THIN_MAX || filled[si2] / areas[si2] >= FEATURE_FILLED_MAX)) {\n        smallFeatures++; smallArea += areas[si2]; smallFlag[si2] = 1;\n      }\n    }\n    grid.stats.smallFeatures = smallFeatures;\n    grid.stats.smallArea = smallArea;\n    for (si2 = 0; si2 < nLab && grid.stats.feats && si2 < grid.stats.feats.length; si2++) { grid.stats.feats[si2].stones = hit[si2]; grid.stats.feats[si2].runs = featRuns[si2] || null; grid.stats.feats[si2].placed = featPlaced[si2]; }\n\n    // Justin 2026-09-03: \"if 90% or more of the image is spangle-able let it\n    // through but don't include the small stuff in the preview.\" Features\n    // flagged as too small are removed from the render \u2014 the (R) mark on the\n    // Cricut logo, a tiny tagline \u2014 and the standing note under the preview\n    // tells the customer that is what will happen. Only when small detail is\n    // a real share of the design (DETAIL_SMALL_SHARE_MIN) does the dialog block.\n    if (smallFeatures && artArea && smallArea / artArea < DETAIL_SMALL_SHARE_MIN) {\n      var kept = [], dropped = 0;\n      for (si2 = 0; si2 < grid.dots.length; si2++) {\n        var dk = grid.dots[si2];\n        var kx = (dk.cx * cs) | 0, ky = (dk.cy * cs) | 0;\n        var kl = (kx >= 0 && ky >= 0 && kx < m.fw && ky < m.fh) ? lbl[ky * m.fw + kx] : -1;\n        if (kl >= 0 && smallFlag[kl]) { dropped++; continue; }\n        kept.push(dk);\n      }\n      if (dropped) {\n        grid.dots = kept;\n        grid.stats.byMm = { 1: 0, 2: 0, 3: 0, 4: 0 };\n        for (si2 = 0; si2 < kept.length; si2++) grid.stats.byMm[kept[si2].mm]++;\n      }\n      grid.stats.droppedStones = dropped;\n    }\n\n    grid.stats.artArea = artArea;\n    grid.stats.vanished = vanished;\n    grid.stats.features = nLab;\n    grid.stats.zeroFeatures = zeroFeatures;\n\n    latticeCache[key] = grid;\n    return grid;\n  }\n\n  /* ---------------- drawing ------------------------------------------------ */\n\n  function paintDots(ctx, dots, picks, ox, oy, cell) {\n    for (var i = 0; i < dots.length; i++) {\n      var d = dots[i];\n      var rgb = picks[d.c] || DEFAULT_RGBS[d.c] || DEFAULT_RGB;\n      if (rgb.mode === 'rainbow' || rgb.mode === 'lt_rainbow') {\n        // rainbow spangles: each stone a different hue, stable per stone\n        var hue = (i * 47 + (d.cx * 13 | 0) * 29) % 360;\n        ctx.fillStyle = rgb.mode === 'rainbow' ? 'hsl(' + hue + ',90%,50%)' : 'hsl(' + hue + ',70%,80%)';\n      } else {\n        ctx.fillStyle = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';\n      }\n      ctx.beginPath();\n      ctx.arc(ox + d.cx * cell, oy + d.cy * cell, d.r * cell, 0, 6.2832);\n      ctx.fill();\n    }\n  }\n\n  function fitGrid(grid, w, h, pad) {\n    var cell = Math.min(w * pad / grid.gw, h * pad / grid.gh);\n    return { ox: (w - cell * grid.gw) / 2, oy: (h - cell * grid.gh) / 2, cell: cell };\n  }\n\n  function positionOverlay() {\n    if (!wrap || !stage) return;\n    var host = stage.parentElement;\n    if (!host) return;\n    host.classList.add('nt-spg-host');\n    if (wrap.parentElement !== host) host.appendChild(wrap);\n    /* The design-notes button belongs in the window's corner, not under it: the\n       engine docks it to the stage wrapper, which on phones also holds the note\n       paragraph (Justin 2026-09-15). The overlay IS the window's box, so moving\n       the button in here puts it where it was asked for \u2014 and nothing about the\n       button itself changes, so its own handler keeps working. */\n    try {\n      var fab = host.querySelector('.bsv4-notes-fab') ||\n        (host.ownerDocument && host.ownerDocument.querySelector('.bsv4-preview .bsv4-notes-fab'));\n      if (fab && fab.parentElement !== wrap) wrap.appendChild(fab);\n    } catch (e) {}\n    var hr = host.getBoundingClientRect();\n    var sr = stage.getBoundingClientRect();\n    wrap.style.left = Math.max(0, sr.left - hr.left) + 'px';\n    wrap.style.top = Math.max(0, sr.top - hr.top) + 'px';\n    wrap.style.width = Math.min(sr.width, hr.width) + 'px';\n    wrap.style.height = sr.height + 'px';\n  }\n\n  // Where the engine's own artwork image sits inside the overlay. The dots\n  // must land in exactly that box: the engine's size rulers bracket the image,\n  // so fitting the grid to the whole stage instead (with its own padding) drew\n  // the design bigger than the rulers and the width rule crossed the letters\n  // (Justin 2026-09-03).\n  function artBox() {\n    if (!wrap || !stage) return null;\n    var img = stage.querySelector('.bsv4-preview__art img') || stage.querySelector('img');\n    if (!img || !img.getBoundingClientRect) return null;\n    var ir = img.getBoundingClientRect(), wr = wrap.getBoundingClientRect();\n    if (ir.width < 8 || ir.height < 8) return null;\n    return { x: ir.left - wr.left, y: ir.top - wr.top, w: ir.width, h: ir.height };\n  }\n\n  function drawStage(picks, grid) {\n    if (!canvas || !stage) return;\n    positionOverlay();\n    var w = stage.offsetWidth, h = stage.offsetHeight;\n    if (w < 40 || h < 40) return;\n    var dpr = Math.min(window.devicePixelRatio || 1, 2);\n    canvas.width = Math.round(w * dpr);\n    canvas.height = Math.round(h * dpr);\n    var x = canvas.getContext('2d');\n    x.clearRect(0, 0, canvas.width, canvas.height);\n    var box = artBox();\n    if (box) {\n      // same box as the uploaded image, so the rulers frame the dots too\n      var fb = fitGrid(grid, box.w * dpr, box.h * dpr, 1);\n      paintDots(x, grid.dots, picks, box.x * dpr + fb.ox, box.y * dpr + fb.oy, fb.cell);\n      return;\n    }\n    var f = fitGrid(grid, canvas.width, canvas.height, 0.9);\n    paintDots(x, grid.dots, picks, f.ox, f.oy, f.cell);\n  }\n\n  function tightDataUrl(picks, grid) {\n    var c = document.createElement('canvas');\n    c.width = Math.ceil(grid.gw * EXPORT_CELL_PX);\n    c.height = Math.ceil(grid.gh * EXPORT_CELL_PX);\n    paintDots(c.getContext('2d'), grid.dots, picks, 0, 0, EXPORT_CELL_PX);\n    return c.toDataURL('image/png');\n  }\n\n  function sizeGuideImgs() {\n    return [].slice.call(document.querySelectorAll('[data-bsv4-sg-design]'));\n  }\n\n  function applySizeGuide() {\n    if (!currentDataUrl) return;\n    sizeGuideImgs().forEach(function (img) {\n      if (img.getAttribute('src') !== currentDataUrl) img.setAttribute('src', currentDataUrl);\n    });\n  }\n\n  function watchSizeGuide() {\n    if (sgObserver) return;\n    var imgs = sizeGuideImgs();\n    if (!imgs.length) return;\n    sgObserver = new MutationObserver(function () {\n      if (!currentDataUrl || !(stage && stage.querySelector('img'))) return;\n      applySizeGuide();\n    });\n    imgs.forEach(function (img) {\n      sgObserver.observe(img, { attributes: true, attributeFilter: ['src'] });\n    });\n  }\n\n  function drawThumbs(picks, across) {\n    if (!layoutEl || !mask) return;\n    var tAcross = Math.min(THUMB_DOTS_MAX, across);\n    var tiles = layoutTiles();\n    var dpr = Math.min(window.devicePixelRatio || 1, 2);\n    thumbStats = { tiles: tiles.length, across: tAcross, per: [] };\n    tiles.forEach(function (tile) {\n      var cv = tile.querySelector('canvas');\n      if (!cv) return;\n      var rect = cv.getBoundingClientRect();\n      if (rect.width >= 40 && rect.height >= 20) {\n        var bw = Math.round(rect.width * dpr), bh = Math.round(rect.height * dpr);\n        if (cv.width !== bw) cv.width = bw;\n        if (cv.height !== bh) cv.height = bh;\n      }\n      var pat = parseInt(tile.getAttribute('data-spg-pattern'), 10);\n      var grid = lattice(pat, tAcross);\n      var x = cv.getContext('2d');\n      x.clearRect(0, 0, cv.width, cv.height);\n      var f = fitGrid(grid, cv.width, cv.height, 0.86);\n      paintDots(x, grid.dots, picks, f.ox, f.oy, f.cell);\n      thumbStats.per.push({ pat: pat, w: cv.width, h: cv.height, cell: +f.cell.toFixed(2), dots: grid.dots.length });\n    });\n  }\n\n  function renderAll(picks) {\n    lastPicks = picks;\n    var across = dotsAcross();\n    var grid = lattice(pattern, across);\n    drawStage(picks, grid);\n    drawThumbs(picks, across);\n    currentDataUrl = tightDataUrl(picks, grid);\n    watchSizeGuide();\n    applySizeGuide();\n  }\n\n  function rerender() {\n    if (renderTimer) clearTimeout(renderTimer);\n    renderTimer = setTimeout(function () {\n      renderTimer = null;\n      if (!mask) return;\n      try { resolvePalette(function (p) { try { renderAll(p); scheduleMockup(); } catch (e) { renderFailed(e); } }); } catch (e) { renderFailed(e); }\n    }, 150);\n  }\n\n  // Spangle mockup for the cart / order (Justin 2026-09-03): the settled\n  // render is uploaded through the engine's own presign path and carried\n  // on the line item as _Spangle Mockup (the cart snippets prefer it for the\n  // thumbnail). Re-uploaded whenever the render changes; debounced.\n  var mockupUrl = '', mockupFor = '', mockupTimer = null, mockupBusy = false;\n  function scheduleMockup() {\n    if (mockupTimer) clearTimeout(mockupTimer);\n    mockupTimer = setTimeout(uploadMockup, 1500);\n  }\n  function uploadMockup() {\n    mockupTimer = null;\n    try {\n      var bridge = window.__bsv4Bridge;\n      if (!bridge || typeof bridge.uploadBlob !== 'function' || !currentDataUrl) return;\n      var key = currentDataUrl.length + ':' + currentDataUrl.slice(-64);\n      if (key === mockupFor || mockupBusy) { if (mockupBusy && key !== mockupFor) scheduleMockup(); return; }\n      mockupBusy = true;\n      fetch(currentDataUrl).then(function (r) { return r.blob(); }).then(function (blob) {\n        var file = new File([blob], 'spangle-mockup-' + Date.now() + '.png', { type: 'image/png' });\n        return bridge.uploadBlob(file);\n      }).then(function (res) {\n        mockupBusy = false;\n        if (res && res.imgixUrl) { mockupUrl = res.imgixUrl; mockupFor = key; }\n      }).catch(function () { mockupBusy = false; });\n    } catch (e) { mockupBusy = false; }\n  }\n  /* The mockup on the cart line must be the CURRENT colours (Justin 2026-10-13, NT-2709302:\n     Aqua, Navy, Royal ordered, mockup still showed Aqua with greys \u2014 the render from before\n     Navy and Royal were picked, because the add ran inside the 1.5s debounce / upload). */\n  function mockupKey() { return currentDataUrl ? currentDataUrl.length + ':' + currentDataUrl.slice(-64) : ''; }\n  function mockupFresh() { return !currentDataUrl || mockupKey() === mockupFor; }\n  /* Checkout waits (up to 10s) for the latest render to finish and upload; it never blocks\n     the sale \u2014 past the deadline the line goes without a mockup (see __bsv4ItemProps). */\n  function mockupSettled() {\n    if (!renderTimer && !mockupTimer && !mockupBusy && mockupFresh()) return true;\n    return new Promise(function (resolve) {\n      var deadline = Date.now() + 10000;\n      (function tick() {\n        if (!renderTimer && mockupTimer) { clearTimeout(mockupTimer); uploadMockup(); }\n        else if (!renderTimer && !mockupTimer && !mockupBusy && !mockupFresh()) uploadMockup();\n        if ((!renderTimer && !mockupTimer && !mockupBusy && mockupFresh()) || Date.now() > deadline) { resolve(true); return; }\n        setTimeout(tick, 150);\n      })();\n    });\n  }\n\n  /* ---------------- overlay lifecycle ------------------------------------- */\n\n  function mount() {\n    if (wrap) return;\n    wrap = document.createElement('div');\n    wrap.className = 'nt-spg-overlay';\n    canvas = document.createElement('canvas');\n    canvas.className = 'nt-spg-canvas';\n    chip = document.createElement('button');\n    chip.type = 'button';\n    chip.className = 'nt-spg-chip';\n    chip.textContent = 'Show original';\n    chip.addEventListener('click', function () {\n      showingDots = !showingDots;\n      wrap.classList.toggle('nt-spg-overlay--off', !showingDots);\n      chip.textContent = showingDots ? 'Show original' : 'Show spangle preview';\n    });\n    wrap.appendChild(canvas);\n    wrap.appendChild(chip);\n    positionOverlay();\n  }\n\n  function unmount() {\n    if (wrap) { try { wrap.remove(); } catch (e) {} }\n    wrap = canvas = chip = null;\n    mask = null;\n    maskSrc = '';\n    latticeCache = {};\n    currentDataUrl = '';\n    applyDetectedMax(3);\n    setColorsPending(true);          // no design -> nothing to pick yet\n    // the design is gone \u2014 so are the reasons it wouldn't work\n    showNote('detail', false);\n    if (modalEl) modalEl.hidden = true;\n  }\n\n  /* ---------------- desktop: colors live inside the preview card ---------- */\n\n  // Justin 2026-09-02: on desktop the color pickers belong in the preview box\n  // with the design, not in their own card down the rail. Same approach the\n  // engine already uses to move the size_guide block into the preview on\n  // mobile \u2014 relocate the element and put it back when the layout flattens,\n  // so the mobile card order (order:8) still applies there.\n  var colorsCard = null, colorsHome = null, colorsHomeNext = null;\n\n  function placeColors() {\n    if (!colorsCard) {\n      colorsCard = root && root.closest ? root.closest('[data-bsv4-block=\"spangle_colors\"]') : null;\n      if (!colorsCard) return;\n      colorsHome = colorsCard.parentElement;\n      colorsHomeNext = colorsCard.nextSibling;\n    }\n    var body = document.querySelector('.bsv4-preview__body');\n    var desktop = window.matchMedia('(min-width: 1000px)').matches;\n    if (desktop && body) {\n      // Into the AI-tools rail, taking the space the Spangle Layout tiles\n      // used to occupy (Justin 2026-09-03: layout choice removed, pattern 1 is\n      // the only one). The rail widens for this template so the pickers are\n      // usable, and they stack down the column.\n      var rail = body.querySelector('.bsv4-preview__tools-col') || body;\n      if (colorsCard.parentElement !== rail || colorsCard.nextSibling !== null) {\n        rail.appendChild(colorsCard);\n      }\n      colorsCard.classList.add('nt-spg-card--inpreview');\n    } else if (body) {\n      // Mobile (Justin 2026-09-03): the colors scroll UNDER the frozen preview\n      // and the freeze ends at Step 2. Both fall out of one move \u2014 put the\n      // card inside the preview card after the stage. The sticky stagewrap's\n      // containing block is that card, so it pins while the colors (and notes)\n      // scroll beneath it and releases exactly where the card ends, which is\n      // where the size step begins.\n      if (colorsCard.parentElement !== body || colorsCard.nextSibling !== null) body.appendChild(colorsCard);\n      colorsCard.classList.add('nt-spg-card--inpreview');\n    } else {\n      if (colorsHome && colorsCard.parentElement !== colorsHome) {\n        colorsHome.insertBefore(colorsCard, colorsHomeNext);\n      }\n      colorsCard.classList.remove('nt-spg-card--inpreview');\n    }\n  }\n\n  /* ---------------- zoom lightbox ---------------------------------------- */\n\n  // The engine's zoom (magnifier, top-right of the stage) fills its dialog\n  // <img> from previewUrl(file) \u2014 the uploaded artwork. Justin 2026-09-02: it\n  // should show whatever the preview window is showing, so while the dot\n  // overlay is on we substitute the tight dot render, and when the customer\n  // has toggled \"Show original\" we leave the engine's image alone. Same\n  // write-only-if-different attribute observer as the size-guide swap, so the\n  // engine's own src writes (async swapImage) can't win a race and nothing loops.\n  function applyZoomSrc() {\n    var dlg = document.querySelector('dialog[data-bsv4-zoom]');\n    var img = dlg ? dlg.querySelector('img') : null;\n    if (!img) return;\n    if (!showingDots || !currentDataUrl) return;   // showing the original\n    if (img.getAttribute('src') === currentDataUrl) return;\n    img.setAttribute('src', currentDataUrl);\n  }\n\n  function watchZoom() {\n    var dlg = document.querySelector('dialog[data-bsv4-zoom]');\n    var img = dlg ? dlg.querySelector('img') : null;\n    if (!img || img.__ntSpgZoomWatched) return;\n    img.__ntSpgZoomWatched = true;\n    new MutationObserver(applyZoomSrc).observe(img, { attributes: true, attributeFilter: ['src'] });\n  }\n\n  function stageImgSrc() {\n    var img = stage ? stage.querySelector('img') : null;\n    return img ? (img.currentSrc || img.src || '') : '';\n  }\n\n  function adoptMask(m) {\n    // Re-deriving after an AI edit / upscale / bg-remove must not yank the\n    // customer back to the dot view if they were looking at the original.\n    var keepOriginal = !!wrap && !showingDots;\n    mask = m;\n    latticeCache = {};\n    applyDetectedMax(m.colors);\n    setColorsPending(false);         // colours known: show the pickers, already sized to the design\n    mount();\n    showingDots = !keepOriginal;\n    wrap.classList.toggle('nt-spg-overlay--off', !showingDots);\n    chip.textContent = showingDots ? 'Show original' : 'Show spangle preview';\n    rerender();\n    prep(false);                     // dots are on screen \u2014 drop the veil\n    watchZoom();\n    placeColors();\n    syncBusy();\n    evaluateWarnings(); // after rerender: the lattice the audit reads is built\n  }\n\n  var testPinned = false; // __ntSpgTest: ignore late engine re-renders until the next real intake\n  var stageTimer = null;\n\n  // The engine paints its own loader (ninja GIF + %) into [data-bsv4-canvas]\n  // for every stage change \u2014 upload, AI edit, upscale, bg-remove. While it is\n  // up the box belongs to the engine, so hide the dot overlay: the customer\n  // sees that loader whichever view they were on, instead of stale dots.\n  function stageBusy() {\n    return !!(stage && stage.querySelector('.bsv4-preview__loading'));\n  }\n\n  function syncBusy() {\n    if (!wrap) return;\n    wrap.classList.toggle('nt-spg-overlay--busy', stageBusy());\n  }\n\n  // Hold a veil over the stage from the moment a new image lands until the\n  // dots for it are painted, so the customer never sees the digital image\n  // first and then a swap (Justin 2026-09-03: keep the loading state going\n  // until the spangle preview is ready).\n  var prepTimer = null;\n  function prep(on) {\n    if (on && wrap && wrap.classList.contains('nt-spg-overlay--prep')) return; // already up; keep its watchdog\n    clearTimeout(prepTimer);\n    if (on) {\n      mount();                       // no-op if already mounted\n      if (wrap) wrap.classList.add('nt-spg-overlay--prep');\n      // Watchdog (Justin 2026-09-03, \"endless load\"): the veil must never\n      // outlive the work it hides. If the dots are not painted 15s after a\n      // new image landed, drop it and show whatever the stage has.\n      prepTimer = setTimeout(function () {\n        if (wrap && wrap.classList.contains('nt-spg-overlay--prep')) {\n          try { console.warn('[spangle] preview did not settle in 15s - releasing the loading veil'); } catch (e) {}\n          prep(false);\n        }\n      }, 15000);\n    } else if (wrap) {\n      wrap.classList.remove('nt-spg-overlay--prep');\n    }\n  }\n\n  // A lattice/paint exception used to be swallowed and left the veil up for\n  // good (spinner forever). Log it where a screenshot of the console shows\n  // it, release the veil, and fall back to the engine's own image so the\n  // customer can keep going (colors still pick, the line just has no mockup).\n  function renderFailed(e) {\n    try { console.error('[spangle] render failed', e && (e.stack || e.message || e)); } catch (e2) {}\n    prep(false);\n    if (wrap) { try { wrap.classList.add('nt-spg-overlay--busy'); } catch (e3) {} }\n    window.__ntSpgLastError = String(e && (e.stack || e.message || e));\n  }\n\n  // Driven by a MutationObserver on the stage rather than a delay after\n  // bsv4:preview-ready. That event fires while the LOADER is still in the box\n  // \u2014 the <img> lands a fade later \u2014 so a fixed 350ms guess read the old\n  // image, or none at all, and the preview went stale (or unmounted) after an\n  // AI edit. Watching src/childList catches every path the engine can take.\n  // The stage <img> src the current mask was derived FOR. Distinct from\n  // maskSrc (what we sampled \u2014 the original upload when it has alpha, see\n  // pickSampleSrc): comparing the stage against maskSrc re-raised the veil on\n  // every mutation once the two stopped matching, and each raise restarted\n  // the watchdog \u2014 the \"endless load\" Justin hit 2026-09-03.\n  var stageSrcSeen = '';\n\n  function onStageChanged(muts) {\n    // Our own overlay lives inside the stage; its class toggles are not a\n    // stage change (they fed the loop above).\n    if (muts && wrap && muts.length && muts.every(function (m) { return m.target === wrap || wrap.contains(m.target); })) return;\n    // SYNCHRONOUS part. A MutationObserver callback runs before the browser\n    // paints the mutation, so this is the one moment the veil can go up before\n    // the engine's new image is ever visible. Doing it after the debounce\n    // below flashed the original for ~140ms on every upload (Justin\n    // 2026-09-03). While the engine's own loader is in the box we leave it\n    // alone \u2014 that is the loading circle the customer should keep seeing \u2014\n    // and veil the instant it is swapped for the image.\n    syncBusy();\n    if (!testPinned && !stageBusy()) {\n      var srcNow = stageImgSrc();\n      if (srcNow && srcNow !== stageSrcSeen) prep(true);\n    }\n    // the heavy work still waits for the DOM to settle\n    clearTimeout(stageTimer);\n    stageTimer = setTimeout(function () {\n      syncBusy();\n      if (testPinned) return;\n      if (stageBusy()) return; // mid-render; the next mutation brings the art\n      onPreviewReady();\n    }, 140);\n  }\n\n  function watchStage() {\n    if (!stage || stage.__ntSpgWatched) return;\n    stage.__ntSpgWatched = true;\n    new MutationObserver(onStageChanged).observe(stage, {\n      childList: true, subtree: true, attributes: true, attributeFilter: ['src', 'class']\n    });\n  }\n\n  // Prefer the original upload over the engine's bg-removed derivative when\n  // the original already has transparency: the AI background removal treats\n  // a white keyline as background and deletes it. Probed once per file.\n  var alphaProbe = {};\n  function pickSampleSrc(stageSrc, cb) {\n    try {\n      var st = window.__bsv4 && window.__bsv4.getState ? window.__bsv4.getState() : null;\n      var file = st && st.files && st.files[0];\n      var orig = file && file.imgixUrl;\n      if (!orig) return cb(stageSrc);\n      if (alphaProbe[orig] === true) return cb(orig + '?fm=png&w=1600');\n      if (alphaProbe[orig] === false) return cb(stageSrc);\n      var im = new Image();\n      im.crossOrigin = 'anonymous';\n      im.onload = function () {\n        try {\n          var c = document.createElement('canvas'); c.width = 64; c.height = 64;\n          var x = c.getContext('2d'); x.drawImage(im, 0, 0, 64, 64);\n          var d = x.getImageData(0, 0, 64, 64).data, t = 0, i;\n          for (i = 3; i < d.length; i += 4) if (d[i] < ALPHA_MIN) t++;\n          alphaProbe[orig] = t > 64 * 64 * 0.02;\n        } catch (e) { alphaProbe[orig] = false; }\n        cb(alphaProbe[orig] ? orig + '?fm=png&w=1600' : stageSrc);\n      };\n      im.onerror = function () { alphaProbe[orig] = false; cb(stageSrc); };\n      im.src = orig + '?fm=png&w=64';\n    } catch (e) { cb(stageSrc); }\n  }\n\n  function onPreviewReady() {\n    if (testPinned) return;\n    var stageSrc = stageImgSrc();\n    if (!stageSrc) { if (!stageBusy()) unmount(); return; }\n    if (stageSrc === stageSrcSeen && wrap && mask) { rerender(); return; }\n    stageSrcSeen = stageSrc;\n    pickSampleSrc(stageSrc, function (src) {\n    if (src === maskSrc && wrap && mask) { rerender(); return; }\n    maskSrc = src;\n    setColorsPending(true);          // a new design: hide the pickers until its colours are known\n    sampleDesign(src, function (m) {\n      if (!m) { prep(false); unmount(); setColorsPending(false); return; }   // could not sample: let the customer pick anyway\n      try { adoptMask(m); } catch (e) { renderFailed(e); setColorsPending(false); }\n    });\n    });\n  }\n\n  /* ---------------- engine adapter seam (cart + pricing) -------------------- */\n\n  function selectedNames() {\n    return (window.__ntSpangleColors || []).map(function (c) { return c && c.name; }).filter(Boolean);\n  }\n\n  function showColorsError(show) {\n    if (!root) return;\n    var el = root.querySelector('.nt-spg__error');\n    if (!el) {\n      el = document.createElement('p');\n      el.className = 'nt-spg__error';\n      el.setAttribute('role', 'alert');\n      el.textContent = 'Please pick at least 1 color.';\n      root.appendChild(el);\n    }\n    el.hidden = !show;\n  }\n\n  function installCartAdapter() {\n    // Tier prices in exact cents (2.99 -10% = 2.69), matching the legacy\n    // spangle table; the engine's default floors the discount (-> 2.70).\n    window.__bsv4TierExactCents = true;\n    // \"A, B\" value format as the legacy spangle page; the KEY is underscore-\n    // prefixed ('_Spangle Colors') so Shopify hides it at checkout / order\n    // status \u2014 staff read it from the order's line item properties in admin.\n    // (Legacy pdp_transferBySize*.js still writes the visible 'Spangle Colors'.)\n    // test hook only: force one size (1-4) or 0 for the engine's own choice\n    function setStoneMode(mm) {\n      stoneMode = mm >= 1 && mm <= 4 ? mm : 0;\n      latticeCache = {};\n      rerender();\n    }\n    window.__ntSpgSetStone = setStoneMode;\n    // Seam fallback (2026-09-03): the shared v4 bundle is rebuilt from several\n    // branches and a build without the family seams silently drops the spangle\n    // props and the colour gate (seen twice on the shared sandbox). Carry both\n    // from this asset too: wrap the engine's cart/add.js post to merge\n    // __bsv4ItemProps into each design line (skipped when the seam already\n    // ran \u2014 '_Spangle Colors' present), and veto the checkout click in the\n    // capture phase before cart.js sees it. Pure no-ops on a seam-aware build.\n    (function installSeamFallback() {\n      if (window.__ntSpgSeamFallback) return;\n      window.__ntSpgSeamFallback = true;\n      function gateBlocked() {\n        if (!window.__bsv4CartGate) return false;\n        var st = null;\n        try { st = window.__bsv4 && window.__bsv4.getState ? window.__bsv4.getState() : null; } catch (e2) {}\n        return window.__bsv4CartGate(st) === false;\n      }\n      var origFetch = window.fetch;\n      if (typeof origFetch === 'function') {\n        window.fetch = function (input, init) {\n          try {\n            var url = typeof input === 'string' ? input : (input && input.url) || '';\n            if (/\\/cart\\/add(\\.js)?(\\?|$)/.test(url) && init && typeof init.body === 'string' && window.__bsv4ItemProps) {\n              var body = JSON.parse(init.body);\n              if (body && Array.isArray(body.items)) {\n                var extra = null, touched = false;\n                body.items.forEach(function (it) {\n                  var pr = it && it.properties;\n                  if (!pr || typeof pr !== 'object') return;\n                  if (pr['_Spangle Colors'] || pr['Spangle Colors']) return; // seam already applied\n                  var isDesign = Object.keys(pr).some(function (k) { return k === '_cartImg' || /^_Upload/.test(k); });\n                  if (!isDesign) return;\n                  if (!extra) extra = window.__bsv4ItemProps() || {};\n                  Object.keys(extra).forEach(function (k) { pr[k] = extra[k]; });\n                  touched = true;\n                });\n                // backstop: a commit that reached the network with no color\n                // (a path the click guards above did not see) is refused\n                if (touched && extra && !extra['_Spangle Colors'] && gateBlocked()) {\n                  return Promise.reject(new Error('Please pick at least 1 color.'));\n                }\n                if (touched) init = Object.assign({}, init, { body: JSON.stringify(body) });\n              }\n            }\n          } catch (e) { /* leave the request untouched */ }\n          return origFetch.call(this, input, init);\n        };\n      }\n      // Every entry that commits the current design to the cart is gated:\n      // the checkout button, the \"add another design\" zone (click, keyboard,\n      // drop, its own file input) and the \"previous design\" / \"Create with\n      // AI\" links inside it (Justin 2026-09-03: gate those like add-to-cart).\n      var COMMIT_SEL = '[data-bsv4-checkout],[data-bsv4-add-another],[data-bsv4-addlink]';\n      function veto(e) { e.preventDefault(); e.stopImmediatePropagation(); }\n      window.addEventListener('click', function (e) {\n        var hit = e.target && e.target.closest && e.target.closest(COMMIT_SEL);\n        if (hit && gateBlocked()) veto(e);\n      }, true);\n      window.addEventListener('keydown', function (e) {\n        if (e.key !== 'Enter' && e.key !== ' ') return;\n        var hit = e.target && e.target.closest && e.target.closest('[data-bsv4-add-another]');\n        if (hit && gateBlocked()) veto(e);\n      }, true);\n      window.addEventListener('drop', function (e) {\n        var hit = e.target && e.target.closest && e.target.closest('[data-bsv4-add-another]');\n        if (hit && gateBlocked()) veto(e);\n      }, true);\n      window.addEventListener('change', function (e) {\n        var t = e.target;\n        if (!t || !t.matches || !t.matches('[data-bsv4-add-input]')) return;\n        if (gateBlocked()) { veto(e); try { t.value = ''; } catch (e3) {} }\n      }, true);\n    })();\n\n    window.__bsv4ItemProps = function () {\n      var names = selectedNames();\n      var props = {};\n      // Underscore-prefixed (Justin 2026-09-03): the colours must not show\n      // in the cart / checkout - staff read them from the order's line item\n      // properties in admin. Same \"A, B\" value format as the legacy page.\n      if (names.length) props['_Spangle Colors'] = names.join(', ');\n      /* only a mockup of THESE colours; a stale one is worse than none (the cart then\n         shows the upload) */\n      if (mockupUrl && mockupFresh()) {\n        props['_Spangle Mockup'] = mockupUrl;\n        // Every cart renderer (page item, drawer item, design-group header,\n        // added-toast) draws the line thumbnail from _cartImg \u2014 point it at\n        // the spangle preview so the cart shows the mockup, not the raw upload.\n        props['_cartImg'] = mockupUrl;\n      }\n      return props;\n    };\n    // Legacy spangle required >= 1 color before add-to-cart.\n    window.__bsv4CartGate = function () {\n      if (selectedNames().length) { showColorsError(false); return mockupSettled(); }\n      showColorsError(true);\n      try { root.scrollIntoView({ block: 'center', behavior: 'smooth' }); } catch (e) {}\n      return false;\n    };\n  }\n\n  /* ---------------- boot --------------------------------------------------- */\n\n  function boot() {\n    root = document.querySelector('[data-nt-spg]');\n    if (!root) return; // not the spangle template \u2014 do nothing\n    stage = document.querySelector('[data-bsv4-canvas]');\n    initChooser();\n    initLayout();\n    window.__ntSpangleColors = [];\n    installCartAdapter();\n\n    if (stage) {\n      watchStage();\n      document.addEventListener('bsv4:preview-ready', onStageChanged);\n      // print size changes (rows) move the physical pitch\n      document.addEventListener('bsv4:rows-changed', function () { latticeCache = {}; rerender(); });\n      // Default print size after upload (Justin 2026-09-03): open the preview at\n      // a realistic width \u2014 the colors block's default_width_in, 9in \u2014 with\n      // proportional height, clamped to the size limits. The engine's own\n      // default is the 3in minimum height, which made every element \"small\"\n      // and pushed the stone sizing toward 2mm. Applied once per new file.\n      var defaultedFile = null;\n      function applyDefaultWidth() {\n        try {\n          var want = parseFloat(root.getAttribute('data-default-w'));\n          if (!(want > 0)) return;\n          var st = window.__bsv4 && window.__bsv4.getState ? window.__bsv4.getState() : null;\n          var file = st && st.files && st.files[0];\n          if (!file || !file.rows || !file.rows[0]) return;\n          if (defaultedFile === (file.id || file.name)) return;\n          var row = file.rows[0], aspect = row.w > 0 && row.h > 0 ? row.w / row.h : 0;\n          if (!aspect) return;\n          var inputs = document.querySelectorAll('.bsv4-row input[type=\"number\"]');\n          var wIn = inputs[0], hIn = inputs[1];\n          if (!wIn) return;\n          var maxW = parseFloat(wIn.max) || 15, minW = parseFloat(wIn.min) || 0;\n          var maxH = hIn ? (parseFloat(hIn.max) || 11) : 11;\n          var target = Math.min(want, maxW, maxH * aspect);\n          if (target < minW) target = minW;\n          target = Math.round(target * 100) / 100;\n          defaultedFile = file.id || file.name;\n          if (Math.abs(target - row.w) < 0.01) return;\n          wIn.value = String(target);\n          wIn.dispatchEvent(new Event('input', { bubbles: true }));\n          wIn.dispatchEvent(new Event('change', { bubbles: true }));\n        } catch (e) { /* preview only */ }\n      }\n      document.addEventListener('bsv4:upload-complete', function () { setTimeout(applyDefaultWidth, 60); });\n      // a fresh intake = a new design = the modal may show again\n      document.addEventListener('bsv4:files-received', function () { uploadEpoch++; testPinned = false; });\n      var previewRoot = stage.closest('.bsv4-preview') || document.body;\n      new MutationObserver(function () {\n        var now = document.querySelector('[data-nt-spg-layout]');\n        if (now && now !== layoutEl) {\n          layoutEl = now;\n          if (mask) rerender();\n        }\n      }).observe(previewRoot, { childList: true, subtree: true });\n      window.addEventListener('resize', rerender);\n      window.addEventListener('resize', placeColors);\n      placeColors();\n      // the dialog is built with the preview; nudge after the engine's own\n      // src write so the first zoom of a session is already the dot render\n      document.addEventListener('click', function (e) {\n        if (e.target && e.target.closest && e.target.closest('[data-bsv4-zoom-open]')) {\n          watchZoom();\n          setTimeout(applyZoomSrc, 0);\n          setTimeout(applyZoomSrc, 150);\n        }\n      });\n    }\n\n    window.__ntSpgDebug = {\n      png: function () { return (currentDataUrl || '').split(',')[1] || ''; }, // tight render, base64 body\n      thumbStats: function () { return thumbStats; },\n      detail: detailAudit,           // stone mix + how much art is lost\n      tooFine: detailTooFine,        // what the warning keys off\n      dotsAcross: dotsAcross,\n      // geometry for pixel-level diagnosis: gap-closed mask, its distance\n      // transform, the artwork as uploaded, and the fine-mask dims\n      dots: function () { return mask ? lattice(pattern, dotsAcross()).dots : []; },\n      geom: function () {\n        if (!mask) return null;\n        var g = geomFor(mask, dotsAcross());\n        return { fw: g.fw, fh: g.fh, cov: g.cov, cov0: g.cov0, D: g.__D, Dorig: g.__Dorig, srcScale: g.srcScale };\n      },\n      lattice: function (pat) { return mask ? lattice(pat || pattern, dotsAcross()).dots.length : 0; },\n      stone: function (mm) { if (typeof mm === 'number' && window.__ntSpgSetStone) window.__ntSpgSetStone(mm); return stoneMode; }\n    };\n\n    // headless test hook: run the full pipeline on any image URL\n    window.__ntSpgTest = function (url) {\n      if (!stage) return 'no stage';\n      uploadEpoch++;\n      testPinned = true;\n      maskSrc = '';\n      sampleDesign(url, function (m) { if (m) adoptMask(m); });\n      return 'sampling';\n    };\n  }\n\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', boot);\n  } else {\n    boot();\n  }\n})();\n"],
  "mappings": "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",
  "names": ["mx", "mn", "b", "dr", "dg", "db", "ox", "oy", "sx", "sy", "x1", "y1", "dk", "tq", "hi", "pass", "kk", "dd", "cur", "dd2", "kk2", "key"]
}
