{
  "version": 3,
  "sources": ["/cdn/shop/t/1064/assets/artwork-library-v2.js?auto=format%2Ccompress"],
  "sourcesContent": ["/* Artwork Library v2 content script \u2014 moved out of snippets/artwork-library-v2.liquid\n   (was an inline <script>), loaded with defer. One copy runs per render of the\n   snippet and claims the next un-initialised [data-alv2-root], as before. */\n(function () {\n  'use strict';\n  /* Claim the next un-initialised root. Each render of this snippet emits its\n     own copy of this script, so with a plain querySelector every copy would\n     re-initialise the FIRST instance and later ones would sit on their loading\n     spinner forever. This is the pattern my-designs-panel already uses\n     (`.md-container:not([data-md-init])`) after hitting exactly that bug, and\n     it matters here for the same reason: the plausible rollout has an on-page\n     library in Tab 2 and the modal on the same PDP. */\n  var root = document.querySelector('[data-alv2-root]:not([data-alv2-init])');\n  if (!root) return;\n  root.setAttribute('data-alv2-init', '');\n\n  /* STAFF LOOKUP (Justin 2026-09-30, internal customer-artwork page). When\n     sections/customer-artwork-lookup.liquid is the host it declares\n     window.__ntArtworkLookup = { id: '<customer id>' } from a PARSE-TIME\n     script that runs before this one, and the library then renders THAT\n     customer instead of the signed-in employee. Everywhere else the global is\n     undefined and this line reads exactly as it always did.\n     \u26A0 The data layer refuses WRITES and skips the two VIEWER-SCOPED feeds\n     while this is set (nt-artwork-data.js): the saved-gang-sheets proxy and\n     the Shopify-orders fallback both identify the viewer, so leaving them on\n     would show the employee's own sheets and orders inside a customer's\n     library. Do not \"restore\" them here. */\n  var LOOKUP = window.__ntArtworkLookup || null;\n  var CUSTOMER_ID = LOOKUP ? String(LOOKUP.id || '') : (root.getAttribute('data-customer-id') || '');\n  var FORCED_TYPE = root.getAttribute('data-forced-type') || '';\n  var ALLOW_MULTI = root.hasAttribute('data-allow-multi');\n  /* Archive and Delete are account-surface actions. On a product page the tile\n     offers only the add action (Owen) \u2014 the same rule the live panel follows. */\n  var IS_ACCOUNT  = root.hasAttribute('data-account');\n  /* Recent strip (dashboard): only designs from the last N days, one page,\n     no head/pager \u2014 see the Liquid note on recent_days. */\n  var RECENT_DAYS = parseInt(root.getAttribute('data-recent-days'), 10) || 0;\n  /* KIND \u00D7 STATE library (Owen 2026-09-16, Rev 3): on the full account\n     library the tab row names WHAT a thing is \u2014 Uploads / Gang Sheet / Design\n     Studio (+ Archive) \u2014 and a Saved \u21C4 Purchased swap sits where the type\n     chips were. Saved = never ordered (Use Design / Continue Editing);\n     Purchased = order lines, locked to Reorder. The recent-days strip and the\n     pickers keep the source tabs + type chips; only this mode changes. */\n  var KIND_MODE = IS_ACCOUNT && !RECENT_DAYS;\n  /* PICKERS speak the same vocabulary (Owen 2026-09-17): the product already\n     forces the kind (a by-size PDP never sees gang sheets and vice versa), so\n     the tab row there is just the Saved \u21C4 Purchased swap \u2014 no source tabs. */\n  var PICKER_SWAP = !IS_ACCOUNT && !!FORCED_TYPE && !RECENT_DAYS;\n  /* 24, not 12 (Owen 2026-09-02): halves pager clicks at no load cost \u2014 the\n     feed is fetched whole regardless (pagination is client-side slicing) and\n     tiles are loading=lazy, so a longer page fetches thumbs only as rows\n     scroll in. 24 divides evenly at every grid width (2/3/4 columns), so no\n     ragged last row anywhere. */\n  var PAGE_SIZE = RECENT_DAYS ? 400 : 24;   /* the strip is a single scroller \u2014 no paging */\n\n  var SORTS = [\n    { key: 'newest', label: 'Newest' },\n    { key: 'oldest', label: 'Oldest' },\n    { key: 'name',   label: 'Name A\u2013Z' }\n    /* 'Largest' from the handoff is deliberately absent: it would require\n       measuring the ENTIRE library (a full-res load per design), not just the\n       visible page. Restore it when the API carries dimensions. */\n  ];\n\n  var TABS = [\n    { key: 'all',      label: 'All Images' },\n    { key: 'purchase', label: 'Purchases' },\n    { key: 'upload',   label: 'Uploads' },\n    /* \u26A0 Archive is a BUCKET, not a source. Every other tab shows unarchived\n       designs of that source; this one shows archived designs of any source.\n       It also closes a hole: archiving was a one-way door because nothing in\n       v2 could see an archived design again, let alone restore one. */\n    /* Design Studio saves (2026-09-15) \u2014 both generations: print-safe\n       `design-studio-save-` rows (orderable, re-editable) and legacy\n       `design-studio-state-` rows (600px previews, Continue Editing only \u2014\n       quarantined here by matchesSource so no other tab can order one).\n       Account-only, like Archive: on a picker a state row could only be a\n       dead tile, and save rows already show under Uploads/All there. */\n    { key: 'studio',   label: 'Design Studio' },\n    /* Gang Sheet Builder saves (2026-09-15) \u2014 saved-but-unpurchased sheets\n       from the builder's own backend. Separate tab per Owen (one grouping/\n       navigation design pass to come). Account-only, edit-only cards. */\n    { key: 'gangsave', label: 'Gang Sheets' },\n    { key: 'archive',  label: 'Archive' }\n    /* \"Ninja Library\" slot intentionally unwired \u2014 no theme-accessible\n       content source exists. /pages/design-library 404s; the 2,000+ pre-made\n       designs live inside the third-party gang sheet builder's own gallery. */\n  ];\n\n  /* \u26A0 Hidden entirely when the surface forces a type \u2014 every card is that type\n     already, so the control could only ever filter to \"all\" or \"nothing\". Same\n     rule the card's type pill follows. */\n  /* \u26A0 No \"All Types\" (Owen) \u2014 the two families are different products with\n     different tiles and different order flows, so the group is an either/or,\n     never a merged view. By Size is the default: it is the overwhelming\n     majority of every library (734 of 761 in the reference account). */\n  var TYPES = [\n    { key: 'bysize',    label: 'By Size' },\n    { key: 'gangsheet', label: 'Gang Sheet' }\n  ];\n\n  var state = {\n    designs: [], loaded: false,\n    tab: 'all', type: 'bysize', side: 'all', arch: false, query: '', sort: 'newest', page: 1,\n    checked: [], zoom: null,\n    /* id -> true while a delete is in flight. A delete now round-trips the\n       server more than once (the data layer re-fetches to catch hidden copies),\n       so the card stayed untouched for a second or two and looked like nothing\n       happened (Owen 2026-10-01). The card stays in the grid, veiled with a\n       spinner and inert, until the server confirms; then it is removed. */\n    deleting: {}\n  };\n  function setDeleting(ids, on) {\n    (ids || []).forEach(function (id) {\n      if (on) state.deleting[String(id)] = true; else delete state.deleting[String(id)];\n    });\n    render();\n  }\n  if (KIND_MODE) state.tab = 'uploads';\n\n  /* Kind tabs (KIND_MODE). Uploads = by-size artwork; Gang Sheet = gang\n     purchases + builder saves; Design Studio = studio saves (both\n     generations) + purchases of studio files. Archive keeps its bucket. */\n  var KIND_TABS = [\n    { key: 'uploads', label: 'Uploads' },\n    { key: 'gang',    label: 'Gang Sheets' },\n    { key: 'studio',  label: 'Design Studio' },\n    { key: 'archive', label: 'Archive' }\n  ];\n  /* All = both sides at once (Owen 2026-09-17): two buckets are for browsing,\n     All is for hunting \u2014 a search only looks at the side you stand on, so a\n     customer who can't recall whether they ordered a file needs one view that\n     spans both. Cards stay self-describing (Use / Continue Editing / Reorder)\n     and nothing doubles: an ordered upload is only ever its order line.\n     EVERY surface lands on All (Owen 2026-09-18: \"all panels should default\n     to all\") \u2014 the library and the pickers alike; Saved / Purchased are the\n     narrowing moves. state.side starts as 'all' above. */\n  /* Order (Justin 2026-10-13, every surface): Reorder-Ready Files \u00B7 Saved \u00B7 All. No Purchased:\n     a purchase is Saved, showing the file that went into the cart (our file is Reorder-Ready). */\n  var SIDES = [\n    { key: 'pr',    label: 'Reorder-Ready Files' },\n    { key: 'saved', label: 'Saved' },\n    { key: 'all',   label: 'All' }\n  ];\n  /* Print Ready Files (Justin 2026-10-13): our production files, one card each (d.printReady,\n     nt-artwork-data applyProductionArt) \u2014 Purchased keeps the customer's own image. The pill\n     only shows when there is one (sidesShown). */\n  function sidesShown() { return SIDES.filter(function (t) { return t.key !== 'pr' || sideCount('pr') > 0; }); }\n  var toastTimer = null;\n  var searchTimer = null;\n\n  /* \u2500\u2500 Ninja Labs beacon (feature 'my-designs', Owen 2026-09-17) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     Fire-and-forget usage counts for the rebuilt library: POST /evt on the\n     Labs HTTP API \u2192 ninja-labs-evt \u2192 CloudWatch NinjaLabs/MyDesigns. Same\n     contract every Labs feature uses ({f, e, v?, ver, env}); the registry is\n     the allowlist, so retiring the feature in Ninja Labs drops these at the\n     door with no theme change. sendBeacon so a click that navigates\n     (Continue Editing, Order as \u2026) never waits on us; the Variant (`ver`)\n     carries the surface so one namespace splits library / picker / recent.\n     Never throws. Every call site is `labs(`.\n     REMOVAL: ninja-labs/docs/REMOVAL-my-designs.md. */\n  var LABS_EVT = 'https://uszaouez69.execute-api.us-east-1.amazonaws.com/evt';\n  var LABS_SURFACE = RECENT_DAYS ? 'recent' : (IS_ACCOUNT ? 'library' : 'picker');\n  var labsOpened = false;\n  function labs(e, v) {\n    try {\n      var body = { f: 'my-designs', e: e, ver: 'rev3-' + LABS_SURFACE,\n                   env: (window.Shopify && Shopify.theme && Shopify.theme.role === 'main') ? 'production' : 'staging' };\n      if (typeof v === 'number' && isFinite(v)) body.v = v;\n      var json = JSON.stringify(body);\n      if (navigator.sendBeacon) navigator.sendBeacon(LABS_EVT, json);\n      else fetch(LABS_EVT, { method: 'POST', body: json, keepalive: true }).catch(function () {});\n    } catch (x) { /* counting must never break the library */ }\n  }\n  /* Which lifecycle action a save-document card took (mirrors saveCtaLabel). */\n  function labsSaveAction(d) {\n    labs(saveCtaLabel(d) === 'Reorder' ? 'reorder_save'\n         : (d && d.source === 'gangsave' ? 'continue_gang' : 'continue_studio'));\n  }\n\n  /* --------------------------------------------------------------- refs */\n  var q = function (sel) { return root.querySelector(sel); };\n  var scroller   = q('[data-alv2-scroller]');\n  var gridEl     = q('[data-alv2-grid]');\n  var loadingEl  = q('[data-alv2-loading]');\n  var emptyEl    = q('[data-alv2-empty]');\n  var pagerEl    = q('[data-alv2-pager]');\n  var rangeEl    = q('[data-alv2-range]');\n  var pagesEl    = q('[data-alv2-pages]');\n  var tabsEl     = q('[data-alv2-tabs]');\n  var typesEl    = q('[data-alv2-types]');\n  var searchEl   = q('[data-alv2-search]');\n  var searchClear = q('[data-alv2-search-clear]');\n  var sortBtn    = q('[data-alv2-sort-btn]');\n  var sortLabel  = q('[data-alv2-sort-label]');\n  var sortMenu   = q('[data-alv2-sort-menu]');\n  var selbar     = q('[data-alv2-selbar]');\n  var selThumbs  = q('[data-alv2-selthumbs]');\n  var selTitle   = q('[data-alv2-seltitle]');\n  var useManyBtn = q('[data-alv2-use-many]');\n  var useManyLbl = q('[data-alv2-usemany-label]');\n  var selNote    = q('[data-alv2-selnote]');\n  var selDelBtn  = q('[data-alv2-selbar-delete]');\n  function selDelLabelEl() {\n    var spans = root.querySelectorAll('[data-alv2-selbar-delete-label]');\n    for (var i = 0; i < spans.length; i++) if (spans[i].offsetParent) return spans[i];\n    return spans[0] || null;\n  }\n  var selMenu    = q('[data-alv2-selmenu]');\n  function closeSelMenu() {\n    if (!selMenu || selMenu.hidden) return;\n    selMenu.hidden = true;\n    var b = q('[data-alv2-selmenu-btn]');\n    if (b) b.setAttribute('aria-expanded', 'false');\n  }\n  var selDelLbl  = q('[data-alv2-selbar-delete-label]');\n  var toastEl    = q('[data-alv2-toast]');\n  var toastMsg   = q('[data-alv2-toast-msg]');\n  var toastAction = q('[data-alv2-toast-action]');\n  var zoomEl     = q('[data-alv2-zoom]');\n  var zoomImg    = q('[data-alv2-zoom-img]');\n  var zoomName   = q('[data-alv2-zoom-name]');\n  var zoomOrders = q('[data-alv2-zoom-orders]');\n  var zoomUse    = q('[data-alv2-zoom-use]');\n  var zoomUv     = q('[data-alv2-zoom-uv]');\n  var zoomRestore = q('[data-alv2-zoom-restore]');\n  var zoomDelete  = q('[data-alv2-zoom-delete]');\n  var zoomRows   = q('[data-alv2-zoom-rows]');\n  var zoomToggle = q('[data-alv2-zoom-toggle]');\n\n  /* --------------------------------------------------------------- utils */\n  function esc(s) {\n    return String(s == null ? '' : s).replace(/[&<>\"']/g, function (c) {\n      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\n    });\n  }\n  function byId(id) {\n    for (var i = 0; i < state.designs.length; i++) {\n      if (String(state.designs[i].id) === String(id)) return state.designs[i];\n    }\n    return null;\n  }\n  function isChecked(id) { return state.checked.indexOf(String(id)) > -1; }\n\n  /* EDIT-ONLY rows: cards whose file must never enter a selection or an order\n     flow \u2014 their single forward action is Continue Editing in the tool that\n     made them. Two kinds: legacy studio 'state' saves (600px previews \u2014 the\n     9-14 sales-audit trap) and Gang Sheet Builder saves (the file is just the\n     builder's preview PNG; the sheet itself lives in the builder's backend). */\n  function editOnly(d) {\n    /* On ACCOUNT surfaces print-safe studio saves join the save-document\n       family too (Owen 2026-09-16): their card is a design with a lifecycle\n       (edit until ordered, reorder after), not selectable artwork. In PICKERS\n       they stay ordinary orderable files \u2014 that is the studio contract. */\n    return !!d && (d.studio === 'state' || d.source === 'gangsave' ||\n                   (IS_ACCOUNT && d.studio === 'save'));\n  }\n  function continueEditUrl(d) {\n    if (d && d.source === 'gangsave') return window.NTArtworkData.gangSaveEditUrl(d, window.location.pathname);\n    return window.NTArtworkData.studioEditUrl(d);\n  }\n  /* ORDERED saves are LOCKED (Owen 2026-09-16): the design is final once it\n     has been purchased, so the card's action flips Continue Editing \u2192 Reorder.\n     Gang saves carry the builder's own purchasedAt flag; a studio save is\n     ordered when its file has a purchase twin in the feed (the same dateIx\n     lookup the card dates use). Legacy -state- rows are deliberately EXEMPT \u2014\n     their file is a 600px preview and reordering it is the 60 dpi trap, so\n     they stay on Continue Editing forever. */\n  function savedOrdered(d) {\n    if (!d) return false;\n    if (d.source === 'gangsave') return !!d.ordered;\n    if (d.studio === 'save' && dateIx) {\n      var slot = dateIx[window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet)];\n      return !!(slot && slot.purchase);\n    }\n    return false;\n  }\n  function saveCtaLabel(d) {\n    /* filter bar v2 (Justin 2026-10-13): Open in Builder / Open in Editor on the account library */\n    if (KIND_MODE && d.source === 'gangsave') return 'Open in Builder';\n    if (KIND_MODE && d.studio && !(d.studio === 'save' && savedOrdered(d))) return 'Open in Editor';\n    return savedOrdered(d) && d.studio !== 'state' ? 'Reorder' : 'Continue Editing';\n  }\n\n  function isVectorDesign(d) { return window.NTArtworkData.isVectorFile(d.file || ''); }\n\n  /* ------------------------------------------------------------ deriving */\n  /* The two filter bars are INDEPENDENT axes \u2014 you can be on Uploads and By\n     Size at once \u2014 so each is applied separately and each counts against the\n     other's current state. That cross-filtering is deliberate: the number on a\n     pill should be what you get if you press it, not a global total that turns\n     out to be wrong the moment another filter is on. */\n  function matchesType(d, key) {\n    /* Builder saves are type-INDEPENDENT: they are sheets by nature, but\n       their tab must not vanish while the By Size chip is active (tabCount\n       cross-filters through here \u2014 the archive-count precedent in reverse).\n       They can't leak into the type counts of other tabs: matchesSource\n       quarantines them to their own tab first. */\n    if (d && d.source === 'gangsave') return true;\n    if (FORCED_TYPE === 'gangsheet') return !!d.gangsheet;\n    if (FORCED_TYPE === 'bysize') return !d.gangsheet;\n    if (key === 'gangsheet') return !!d.gangsheet;\n    if (key === 'bysize') return !d.gangsheet;\n    return true;\n  }\n  /* \u26A0 Archive inverts the archived test rather than adding to it. Every other\n     bucket hides archived designs; this one shows nothing else. */\n  /* --- KIND \u00D7 STATE helpers --- */\n  function kindOf(d) {\n    if (d.studio) return 'studio';\n    if (d.source === 'gangsave' || d.gangsheet) return 'gang';\n    return 'uploads';\n  }\n  /* An ORDERED design. Order lines are the record of a purchase; a builder\n     save the builder marks purchased counts too. */\n  function isPurchasedRow(d) {\n    return d.source === 'purchase' || (d.source === 'gangsave' && !!d.ordered);\n  }\n  /* Artwork MOVES on purchase: an upload (plain or studio save) whose file has\n     a purchase twin is represented by that order line on the Purchased side\n     and leaves Saved \u2014 the buckets stay disjoint. Same dateIx the card dates\n     read; built lazily here because the filter runs before the grid paints. */\n  function hasPurchaseTwin(d) {\n    if (!dateIx) buildDateIndex();\n    var slot = dateIx[window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet)];\n    return !!(slot && slot.purchase);\n  }\n  function matchesSide(d, side) {\n    if (side === 'all') return matchesSide(d, 'saved') || !!d.printReady || (KIND_MODE && d.source === 'gangsave');\n    /* account library: builder saves live in their own Gang Sheet Builder tab (filter bar v2) */\n    if (side === 'builder') return d.source === 'gangsave';\n    if (KIND_MODE && d.source === 'gangsave') return false;\n    if (side === 'pr') return !!d.printReady;\n    if (d.printReady || d.prTwin) return false;\n    if (side === 'purch') {\n      /* Order lines, plus builder saves the builder marks purchased \u2014 the\n         gang order feed does NOT carry builder orders (Owen's 8 builder\n         purchases: 1 order line in orderDataNew?gangsheet=true), so the save\n         is the only record of them. Reorder on those opens the builder with\n         the sheet loaded. */\n      return isPurchasedRow(d);\n    }\n    /* Saved = uploads + purchases (the cart file); an upload that was bought shows once, as its order line */\n    return isPurchasedRow(d) || !hasPurchaseTwin(d);\n  }\n  function inWindow(d) {\n    var ts = d.timestamp || 0;\n    if (ts && ts < 1e11) ts *= 1000;   /* seconds \u2192 ms, should a feed ever hand us seconds */\n    return ts >= Date.now() - RECENT_DAYS * 864e5;\n  }\n  /* Recent strip = My Designs' Single Images (Justin 2026-10-14): no gang sheets / builder saves;\n     studio saves only under their Design Studio tab */\n  function stripMatch(d, side) {\n    if (d.gangsheet || d.source === 'gangsave') return false;\n    if (side === 'studio') return !!d.studio;\n    return !d.studio && matchesSide(d, side);\n  }\n  function archOfKind(d, kind) {\n    return !!d.archived && (kindOf(d) === kind || (kind === 'uploads' && kindOf(d) === 'studio'));\n  }\n  function sideCount(side) {\n    return state.designs.filter(function (d) {\n      return matchesSource(d, state.tab) &&\n             (RECENT_DAYS ? inWindow(d) : KIND_MODE ? true : matchesType(d, state.type)) &&   /* pickers: the forced kind */\n             (RECENT_DAYS ? stripMatch(d, side) : matchesSide(d, side));\n    }).length;\n  }\n  /* Every surface opens on Print Ready Files when there are any (Justin 2026-10-13: our files\n     are the most reliable images); once, so the customer's own pick sticks. */\n  var sideInit = false;\n  function initSide() {\n    if (sideInit || !state.designs.length) return;\n    sideInit = true;\n    if (sideCount('pr') > 0) state.side = 'pr';\n  }\n\n  function matchesSource(d, key) {\n    if (key === 'archive') return !!d.archived;\n    if (d.archived) return false;\n    /* KIND keys (account library, Rev 3) */\n    if (key === 'uploads' || key === 'gang' || key === 'studio') return kindOf(d) === key;\n    /* Studio tab: both generations, any source (a purchase of a save PNG is\n       still studio art). Legacy 'state' rows live ONLY here \u2014 every other\n       bucket refuses them so a 600px preview can never reach an order flow\n       (the 9-14 sales-audit trap). Print-safe 'save' rows stay ordinary\n       everywhere AND collect here. */\n    if (key === 'studio') return !!d.studio;\n    if (d.studio === 'state') return false;\n    /* Builder saves live ONLY in their tab \u2014 the preview PNG behind the card\n       must never surface as orderable artwork anywhere else. */\n    if (key === 'gangsave') return d.source === 'gangsave';\n    if (d.source === 'gangsave') return false;\n    if (key === 'all') return true;\n    return d.source === key;\n  }\n  function libraryForType() {\n    return state.designs.filter(function (d) {\n      return !d.archived && matchesType(d, state.type);\n    });\n  }\n  function tabCount(key) {\n    return state.designs.filter(function (d) {\n      if (!matchesSource(d, key)) return false;\n      /* Kind tabs count what the two sides will show \u2014 a row on neither side\n         (an ordered save represented by its order line) is not counted. */\n      if (KIND_MODE) return key === 'archive' || matchesSide(d, 'all');\n      return matchesType(d, state.type);\n    }).length;\n  }\n  function typeCount(key) {\n    return state.designs.filter(function (d) {\n      return matchesSource(d, state.tab) && matchesType(d, key);\n    }).length;\n  }\n  function visibleDesigns() {\n    var list = state.designs.filter(function (d) {\n      /* Kind \u00D7 state: the tab picks the kind, the swap picks the side\n         (Archive has no side). No type axis \u2014 the kind IS the type. */\n      if (KIND_MODE) {\n        /* Archived is a toggle ON TOP of the kind (Justin 2026-10-13): archived designs of the chosen kind */\n        if (state.arch) return archOfKind(d, state.tab);\n        return matchesSource(d, state.tab) && (state.tab === 'archive' || matchesSide(d, state.side));\n      }\n      /* Picker: forced kind \u00D7 side. 'all' still applies the quarantines\n         (legacy previews, builder saves, archived never reach a picker). */\n      if (PICKER_SWAP) {\n        return matchesSource(d, 'all') && matchesType(d, state.type) && matchesSide(d, state.side);\n      }\n      /* the strip shows BOTH families (the removed carousel did) \u2014 its type\n         segment is hidden with the head, so the type axis is skipped. It does\n         take the side rule the library uses ('all' = saved \u222A purchased, the\n         buckets disjoint): an upload whose file was bought is represented by\n         its order line, so the strip no longer shows it twice (2026-09-29). */\n      return matchesSource(d, state.tab) && (RECENT_DAYS ? stripMatch(d, state.side) : matchesType(d, state.type));\n    });\n    if (RECENT_DAYS) {\n      list = list.filter(function (d) {\n        /* Design Studio state saves are tagged by basename prefix (contract:\n           dev/studio-v2/src/persistence.js) \u2014 the old dashboard carousel hid\n           them (Owen 9-09 rdNotStudioSave); the strip keeps that until the\n           library grows its studio card. */\n        var base = String(d.fileName || d.file || '').split('?')[0].split('/').pop();\n        if (base.indexOf('design-studio-state-') === 0) return false;\n        return inWindow(d);\n      });\n    }\n    var query = state.query.trim().toLowerCase();\n    if (query) {\n      /* Studio saves answer to their design name too \u2014 the card shows it. */\n      list = list.filter(function (d) {\n        return (d.fileName || '').toLowerCase().indexOf(query) > -1 ||\n               (d.studioName || '').toLowerCase().indexOf(query) > -1 ||\n               ((d.builderSave && d.builderSave.name) || '').toLowerCase().indexOf(query) > -1;\n      });\n    }\n    list = list.slice();\n    if (state.sort === 'name') {\n      list.sort(function (a, b) { return (a.fileName || '').localeCompare(b.fileName || ''); });\n    } else {\n      /* Newest/Oldest key on LAST USED, not the record's own date (Owen\n         2026-09-04: \"sort the order of uploaded to last used\"). Last used =\n         the later of the design's own timestamp and its purchase twin's\n         newest order \u2014 the same fact the card's date line shows (\"Ordered:\"\n         wins there too), so a design uploaded last year but reordered\n         yesterday now sorts like yesterday instead of sinking to the bottom.\n         Computed once per item (not per comparison): makeUploadMatchKey\n         normalizes a key per call, and n\u00B7log n of those on a 750-design\n         library is real work; n of them is the same cost class as the\n         filters above. */\n      list.forEach(function (d) { d.__usedTs = lastUsedTs(d); });\n      if (state.sort === 'oldest') {\n        list.sort(function (a, b) { return (a.__usedTs || 0) - (b.__usedTs || 0); });\n      } else {\n        list.sort(function (a, b) { return (b.__usedTs || 0) - (a.__usedTs || 0); });\n      }\n    }\n    return list;\n  }\n\n  /* Applying a design \u2014 Use Design, Order as DTF/UV, send to the builder \u2014 is a\n     \"use\": it moves the design to the front of the last-used sort even before\n     any order exists (Owen 2026-09-28: \"applying it to a pdp counts\"; the PDP\n     reuse path never re-registers the design, so its timestamp never bumped and\n     it sat where it was). Recorded per-device in localStorage under the SAME\n     makeUploadMatchKey the sort keys on; a later order still bumps it\n     cross-device through the order timestamp. Every access is wrapped so a\n     blocked or absent store never breaks an apply. The grid already collapses\n     same-file rows to the newest timestamp, so this only ever reorders \u2014 it\n     never shows a duplicate. */\n  var USED_KEY = 'nt-md-used-v1';\n  var usedCache = null;\n  function usedStore() {\n    if (usedCache) return usedCache;\n    try { usedCache = JSON.parse(localStorage.getItem(USED_KEY) || '{}') || {}; } catch (e) { usedCache = {}; }\n    return usedCache;\n  }\n  function markUsed(items) {\n    try {\n      var store = usedStore(), now = Date.now(), touched = false;\n      (items || []).forEach(function (d) {\n        if (!d) return;\n        var k = window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet);\n        if (k) { store[k] = now; touched = true; }\n      });\n      if (!touched) return;\n      var keys = Object.keys(store);\n      if (keys.length > 400) {   /* keep the map bounded \u2014 newest 400 keys */\n        keys.sort(function (a, b) { return store[b] - store[a]; }).slice(400).forEach(function (k) { delete store[k]; });\n      }\n      localStorage.setItem(USED_KEY, JSON.stringify(store));\n    } catch (e) {}\n  }\n  function usedTsFor(d) {\n    var store = usedStore();\n    var k = window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet);\n    return (k && store[k]) || 0;\n  }\n\n  /* The later of \"when this record happened\", \"when this design was last\n     ordered\" (its purchase twin's newest order), and \"when it was last applied\"\n     (markUsed, above). Max, not cardWhen's purchase-first pick: a design\n     re-uploaded after an old order was last used at the re-upload, not at the\n     stale order. */\n  function lastUsedTs(d) {\n    if (!dateIx) buildDateIndex();\n    var slot = dateIx[window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet)];\n    /* \u26A0 ONE unit (ms). Feed timestamps are SECONDS, markUsed stores\n       Date.now() MILLISECONDS \u2014 compared raw, anything used in this browser\n       outranked every upload, even one made a minute ago (Justin 2026-09-29:\n       Sep 28 studio files above his Sep 29 upload on Newest). */\n    var ms = function (t) { t = t || 0; return t && t < 1e11 ? t * 1000 : t; };\n    var own = ms(d.timestamp);\n    var bought = slot && slot.purchase ? ms(slot.purchase.timestamp) : 0;\n    /* and its newest UPLOAD: a purchased design re-uploaded later (same file \u2014\n       aliasSameFileUploads) moves to the top while its order line keeps\n       representing it (Justin 2026-09-29). */\n    var uploaded = slot && slot.upload ? ms(slot.upload.timestamp) : 0;\n    return Math.max(own, bought, uploaded, ms(usedTsFor(d)));\n  }\n\n  /* ------------------------------------------------------------ rendering */\n\n  /* Newest purchase + newest upload for every file in the feed, built ONCE per\n     render.\n\n     \u26A0 Do not call newestRecordOf() from cardHtml. It walks all of\n     state.designs and normalizes a match key for every record; twice per card\n     across a 12-card page at 756 designs is ~18,000 key computations per\n     render. This produces the same answer in one O(n) pass.\n\n     Same keying as the dedupe (source + file), which is why an upload and a\n     purchase of one file stay separate records \u2014 the tabs filter by source. */\n  var dateIx = null;\n  function buildDateIndex() {\n    var ix = Object.create(null);\n    for (var i = 0; i < state.designs.length; i++) {\n      var x = state.designs[i];\n      var k = window.NTArtworkData.makeUploadMatchKey(x, !!x.gangsheet);\n      var slot = ix[k] || (ix[k] = { purchase: null, upload: null });\n      var cur = slot[x.source];\n      if (cur === undefined) continue;   /* a source we do not label */\n      if (!cur || (x.timestamp || 0) > (cur.timestamp || 0)) slot[x.source] = x;\n    }\n    dateIx = ix;\n  }\n\n  /* \"Purchased: Feb 29, 2024\" \u2014 or \"Uploaded: ...\" when the feed shows no\n     purchase (wording: Justin 2026-09-29, was \"Ordered:\"). Purchased wins: for\n     something you have actually bought, when you last bought it is the more\n     useful fact.\n\n     Returns null when the feed has neither, and the line is then omitted\n     rather than rendered empty \u2014 the same rule the zoom panel follows, since a\n     gap in the feed is not evidence that a thing never happened. */\n  function cardWhen(d) {\n    if (!dateIx) return null;\n    var slot = dateIx[window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet)];\n    if (!slot) return null;\n    var rec = slot.purchase || slot.upload;\n    if (!rec) return null;\n    var when = fmtOrderDate(rec.timestamp, rec.date);\n    if (!when) return null;\n    return (slot.purchase ? 'Purchased: ' : 'Uploaded: ') + when;\n  }\n\n  function cardHtml(d) {\n    var checked = isChecked(d.id);\n    /* Studio saves show the design's name (\"Test 2\"), not the hashed\n       filename; the hover title keeps the real file for anyone who needs it. */\n    var shownName = d.studioName || (d.builderSave && d.builderSave.name) || d.fileName;\n    var deleting = !!state.deleting[String(d.id)];\n    var html = '<article class=\"alv2-card' + (deleting ? ' alv2-card--deleting' : '') + '\" data-alv2-card data-id=\"' + esc(d.id) + '\"' +\n               (checked ? ' data-selected' : '') + (deleting ? ' aria-busy=\"true\"' : '') +\n               /* staff lookup: the file the page's download button fetches (print-ready first) */\n               (LOOKUP ? ' data-dl=\"' + esc((d.prod && d.prod.url) || d.file || '') + '\" data-dl-name=\"' + esc(d.fileName || '') + '\"' : '') + '>';\n    html += '<div class=\"alv2-card__frame nt-checker-bg w3_bg\">';\n    html +=   '<img class=\"alv2-card__img\" src=\"' + esc(d.thumb) + '\" alt=\"' + esc(d.fileName) + '\" loading=\"lazy\" decoding=\"async\">';\n    /* Delete in flight: veil the thumbnail with the shared spinner so the\n       wait reads as progress, not as a click that did nothing. */\n    if (deleting) html += '<span class=\"alv2-card__veil\" aria-hidden=\"true\"><span class=\"alv2-spinner\"></span></span>';\n    /* Edit-only rows never select \u2014 the card's file is a preview and\n       selection is the road to ordering it (toggleCheck guards the same\n       rule). No checkbox, no half-promise. */\n    if (ALLOW_MULTI && !editOnly(d)) {\n      html += '<button type=\"button\" class=\"alv2-card__check\" data-alv2-check role=\"checkbox\" aria-checked=\"' +\n              (checked ? 'true' : 'false') + '\" aria-label=\"Select ' + esc(shownName) + '\">' +\n              '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"m5 13 4 4L19 7\"/></svg></button>';\n    }\n    /* Builder saves wear \"Built\" where the checkbox would be \u2014 the one honest\n       differentiator from uploaded gang files (the order feed has no signal). */\n    /* \u2026and so does a gang ORDER LINE the data layer joined to an ordered save\n       (orderName) \u2014 the Purchased side's only build signal. */\n    if (d.source === 'gangsave' || d.builderSave) html += '<span class=\"alv2-card__tag\" aria-label=\"Made in the Gang Sheet Builder\">Builder</span>';\n    /* Print Ready Files card: our production file (Justin 2026-10-13). */\n    if (d.printReady && !KIND_MODE) html += '<span class=\"alv2-card__tag alv2-card__tag--pr\" aria-label=\"Has a print-ready production file\">Print Ready</span>';\n    /* \u26A0 Both this and the \"View details\" link below open the SAME panel, and\n       both names say so. They are not duplicates to be deduped: the magnifier\n       is for the moment you are looking at the artwork and want it bigger, the\n       link is for the moment you are reading the name and want the specifics.\n       One destination, two reasons to go there (Owen).\n       Whichever you change, change the other \u2014 a control that promises only\n       half of what the panel does is what made this feel like two actions. */\n    html +=   '<button type=\"button\" class=\"alv2-card__zoom\" data-alv2-zoom-open ' +\n              'title=\"View larger and details\" aria-label=\"View larger and details\">' +\n              '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.35-4.35M11 8v6M8 11h6\"/></svg></button>';\n    /* Type pills removed from tiles (Owen 2026-09-02) \u2014 the By Size /\n       Gang Sheet segment above the grid already answers \"which kind\", and on\n       forced-type surfaces the question doesn't exist. d.gangsheet still\n       drives filters, details and reorder routing. */\n    html += '</div>';\n    var when = d.whenLabel || cardWhen(d);\n    html += '<div class=\"alv2-card__meta\">' +\n              '<p class=\"alv2-card__name\" title=\"' + esc(d.fileName) + '\">' + esc(shownName) + '</p>' +\n              (when ? '<p class=\"alv2-card__when\">' + esc(when) + '</p>' : '') +\n            '</div>';\n    /* Archived cards mirror the archived selection bar (Owen 2026-09-03):\n       the ONLY two things you can do to something in the Archive are restore\n       it or delete it for good, so those ARE the links \u2014 no Use Design, no\n       View details, no dots. Archived designs render only on the account\n       Archive tab (matchesTab hides them everywhere else), so this branch\n       never reaches a picker. */\n    if (d.archived) {\n      html += '<div class=\"alv2-card__actions\">' +\n                '<button type=\"button\" class=\"alv2-card__link\" data-alv2-restore-one>Restore</button>' +\n                '<span class=\"alv2-card__sep\" aria-hidden=\"true\"></span>' +\n                '<button type=\"button\" class=\"alv2-card__link alv2-card__link--danger\" data-alv2-delete-one><span>Delete</span></button>' +\n              '</div>';\n    } else {\n      /* An edit-only row's single forward action is re-opening the design in\n         its tool (studio for legacy state saves, the builder for saved gang\n         sheets) \u2014 the preview file itself must never be \"used\". Print-safe\n         studio save rows keep the standard pair. */\n      /* Order lines on the Purchased side are ordinary artwork cards \u2014 Use\n         Design, same control as every upload (Owen 2026-09-17: \"reorder\n         should be use design\"); the side says it was ordered, the bar orders. */\n      html += '<div class=\"alv2-card__actions\">' +\n                (editOnly(d)\n                  ? '<button type=\"button\" class=\"alv2-card__link\" data-alv2-studio-edit>' + saveCtaLabel(d) + '</button>'\n                  : '<button type=\"button\" class=\"alv2-card__link\" data-alv2-use-one>Use Design</button>') +\n                '<span class=\"alv2-card__sep\" aria-hidden=\"true\"></span>' +\n                '<button type=\"button\" class=\"alv2-card__link\" data-alv2-zoom-open>Details</button>' +\n                (IS_ACCOUNT && !d.printReady && (d.source !== 'gangsave' || !d.ordered)\n                  ? '<button type=\"button\" class=\"alv2-card__more\" data-alv2-more ' +\n                    'aria-haspopup=\"menu\" aria-expanded=\"false\" ' +\n                    'aria-label=\"More actions for ' + esc(shownName) + '\">' +\n                    '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">' +\n                    '<circle cx=\"12\" cy=\"5\" r=\"1.6\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\"/>' +\n                    '<circle cx=\"12\" cy=\"19\" r=\"1.6\"/></svg></button>'\n                  : '') +\n              '</div>';\n    }\n    html += '</article>';\n    return html;\n  }\n\n  /* No count badges (Owen 2026-09-17: \"do you think we need the counts?\" \u2014\n     no). A pill's job is to say what is behind it and whether that is empty;\n     the pager says how many once you are there. countFn is still consulted\n     for the EMPTY state (dead-grey, inert pill) \u2014 it just never renders a\n     number, so nothing in the row can ever change width or bounce. */\n  /* rail tab: title + one-line description (My Designs + Previous Designs, Justin 2026-10-13) */\n  function rtab(attr, key, title, sub, on) {\n    return '<button type=\"button\" class=\"alv2-seg__btn alv2-rtab\" role=\"tab\" ' + attr + '=\"' + key + '\" aria-selected=\"' + on + '\">' +\n      '<span class=\"alv2-rtab__t\">' + title + '</span><span class=\"alv2-rtab__s\">' + sub + '</span></button>';\n  }\n  function segHtml(items, activeKey, attr, countFn) {\n    return items.map(function (t) {\n      var empty = !!countFn && countFn(t.key) === 0;\n      return '<button type=\"button\" class=\"alv2-seg__btn\" role=\"tab\" ' + attr + '=\"' + t.key + '\" ' +\n             (empty ? 'data-empty aria-disabled=\"true\" ' : '') +\n             'aria-selected=\"' + (activeKey === t.key ? 'true' : 'false') + '\">' + esc(t.label) +\n             '</button>';\n    }).join('');\n  }\n\n  function renderTabs() {\n    /* \u26A0 Archive is account-only, like the actions that fill it. On a picker\n       there is no way to archive or restore, so the tab could only ever be a\n       read-only cul-de-sac of designs the customer has already put away \u2014 and\n       offering them for use on a product page is the opposite of what\n       archiving meant. */\n    /* Archive only exists while something is in it (Owen). An empty Archive\n       tab is a door to a blank room. Count is the same cross-filtered number\n       the pill would show, so with only gang-sheet designs archived the tab\n       appears under Gang Sheet and not under By Size \u2014 consistent with every\n       other count on the bar. */\n    /* The archive rule, generalized to every tab (Owen 2026-09-01): a tab\n       with 0 returns is a door to a blank room, so it hides. 'All Images'\n       stays as the anchor while anything exists at all. A COMPLETELY empty\n       library shows ONLY the Uploads tab with the get-started message \u2014\n       that tab names where new artwork will land. */\n    var totallyEmpty = state.loaded && state.designs.length === 0;\n    var tabs;\n    initSide();\n    if (RECENT_DAYS) {\n      /* Print Ready / Uploads rail like My Designs, no All (Justin 2026-10-13) */\n      if (typesEl) typesEl.hidden = true;\n      var rPr = sideCount('pr'), rUp = sideCount('saved'), rSt = sideCount('studio');\n      /* until the customer picks a tab, re-pick on every render (data arrives in waves) */\n      if (!state.sidePicked || state.side === 'all' || sideCount(state.side) === 0) state.side = rPr ? 'pr' : rUp ? 'saved' : 'studio';\n      tabsEl.classList.add('alv2-rail-host');\n      tabsEl.setAttribute('aria-label', 'Filter designs');\n      tabsEl.innerHTML = totallyEmpty || (!rPr && !rUp && !rSt) ? '' : '<span class=\"alv2-sides\">' +\n        (rPr ? rtab('data-alv2-side', 'pr', 'Print Ready', 'Exact images we printed, ready to reorder', state.side === 'pr') : '') +\n        (rUp ? rtab('data-alv2-side', 'saved', 'Uploads', \"Your images, ready to use. We'll optimize before printing\", state.side === 'saved') : '') +\n        (rSt ? rtab('data-alv2-side', 'studio', 'Design Studio', 'Saved Designs from our Studio', state.side === 'studio') : '') + '</span>';\n      return;\n    }\n    if (KIND_MODE) {\n      /* Kind tabs: Uploads is the anchor (it names where new artwork lands);\n         the others show only while they hold something. The swap renders in\n         the type-chip slot \u2014 same pill component \u2014 and hides on Archive,\n         which has no lifecycle. */\n      /* Filter bar v2 (Claude Design handoff, Justin 2026-10-13) \u2014 same kinds and sides, new\n         controls: kind pills (Uploads reads \"Single Images\"; Gang Sheets always shown; Design\n         Studio while it holds something), side tabs on a rail, Archive = \"Archived (N)\" toggle. */\n      var nArch = tabCount('archive');\n      if (totallyEmpty) {\n        tabs = KIND_TABS.filter(function (t) { return t.key === 'uploads'; });\n        state.tab = 'uploads';\n      } else {\n        /* empty filters are hidden, not greyed (Justin 2026-10-13) \u2014 Single Images stays as the anchor */\n        if (state.arch && !nArch) state.arch = false;\n        var gangHere = function () { return tabCount('gang') > 0 || (state.arch && state.designs.some(function (d) { return archOfKind(d, 'gang'); })); };\n        tabs = KIND_TABS.filter(function (t) { return t.key === 'uploads' || (t.key === 'gang' && gangHere()); });\n        if (state.tab === 'archive' || (state.tab === 'gang' && !gangHere())) state.tab = 'uploads';\n      }\n      /* Design Studio is a Row B tab under Single Images; its pill reads Single Images */\n      tabsEl.innerHTML = segHtml(tabs.map(function (t) { return t.key === 'uploads' ? { key: t.key, label: 'Single Images' } : t; }),\n        state.tab === 'studio' ? 'uploads' : state.tab, 'data-alv2-tab',\n        function (k) { return state.arch ? state.designs.filter(function (d) { return archOfKind(d, k); }).length : tabCount(k); });\n      if (!typesEl) return;\n      if (totallyEmpty) { typesEl.hidden = true; return; }\n      var arch = !nArch ? '' : '<button type=\"button\" class=\"alv2-arch\" data-alv2-arch aria-label=\"Archived (' + nArch + ')\" aria-pressed=\"' + state.arch + '\">' +\n        '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"4\" rx=\"1\"/><path d=\"M5 8v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8M10 12h4\"/></svg>' +\n        '<span class=\"alv2-arch__l\">Archived</span><span class=\"alv2-arch__n\">' + nArch + '</span></button>';\n      typesEl.hidden = false;\n      typesEl.removeAttribute('data-ghost');\n      if (state.arch) {\n        /* No lifecycle on Archive \u2014 ghost the side tabs so the row keeps its shape. */\n        typesEl.innerHTML = '<span class=\"alv2-sides\" data-ghost>' + segHtml(SIDES.slice(1), state.side, 'data-alv2-side', null) + '</span>' + arch;\n        return;\n      }\n      /* Open on a side that has something: a tab whose Saved side is empty\n         lands on Purchased rather than on a blank room (All is never emptier\n         than either side, so it only needs the both-empty case). */\n      if (state.tab !== 'studio' && sideCount(state.side) === 0) {\n        state.side = sideCount('pr') > 0 ? 'pr' : sideCount('saved') > 0 ? 'saved' : sideCount('builder') > 0 && state.tab === 'gang' ? 'builder' : 'saved';\n      }\n      var studioOn = state.tab === 'studio';\n      /* side counts for the kind the row belongs to (Design Studio sits under Single Images) */\n      var baseCount = function (k) { var keep = state.tab; state.tab = studioOn ? 'uploads' : keep; var n = sideCount(k); state.tab = keep; return n; };\n      /* no All on the account library (Justin 2026-10-13) \u2014 land on a real side instead */\n      if (!studioOn && state.side === 'all') state.side = sideCount('pr') ? 'pr' : 'saved';\n      /* rail tabs: title + one-line description (Justin 2026-10-13 mock) */\n      var gangOn = state.tab === 'gang';\n      var rail = (baseCount('pr') ? rtab('data-alv2-side', 'pr', 'Print Ready', gangOn ? 'Exact gang sheets we printed, ready to reorder' : 'Exact images we printed, ready to reorder', !studioOn && state.side === 'pr') : '') +\n        (baseCount('saved') ? rtab('data-alv2-side', 'saved', 'Uploads', gangOn ? \"Your files, ready to use. We'll optimize before printing\" : \"Your images, ready to use. We'll optimize before printing\", !studioOn && state.side === 'saved') : '') +\n        (gangOn\n          ? (sideCount('builder') ? rtab('data-alv2-side', 'builder', 'Gang Sheet Builder', 'Sheets saved in the Gang Sheet Builder', state.side === 'builder') : '')\n          : (tabCount('studio') ? rtab('data-alv2-tab', 'studio', 'Design Studio', 'Saved Designs from our Studio', studioOn) : ''));\n      typesEl.setAttribute('aria-label', 'Filter designs');\n      typesEl.innerHTML = '<span class=\"alv2-sides\">' + rail + '</span>' + arch;\n      return;\n    }\n    if (PICKER_SWAP) {\n      /* The swap IS the tab row here; the kind is the product's. An empty\n         side flips to the other; both empty \u2192 the swap hides and the grid's\n         own empty copy speaks. */\n      state.tab = 'all';\n      if (typesEl) typesEl.hidden = true;\n      var sSaved = sideCount('saved'), sPr = sideCount('pr');\n      if (!sSaved && !sPr) { tabsEl.innerHTML = ''; return; }\n      /* Print Ready / Uploads rail like My Designs, no All (Justin 2026-10-13) */\n      if (state.side === 'all' || sideCount(state.side) === 0) state.side = sPr ? 'pr' : 'saved';\n      var gangP = FORCED_TYPE === 'gangsheet';\n      tabsEl.classList.add('alv2-rail-host');\n      tabsEl.setAttribute('aria-label', 'Filter designs');\n      tabsEl.innerHTML = '<span class=\"alv2-sides\">' +\n        (sPr ? rtab('data-alv2-side', 'pr', 'Print Ready', gangP ? 'Exact gang sheets we printed, ready to reorder' : 'Exact images we printed, ready to reorder', state.side === 'pr') : '') +\n        (sSaved ? rtab('data-alv2-side', 'saved', 'Uploads', gangP ? \"Your files, ready to use. We'll optimize before printing\" : \"Your images, ready to use. We'll optimize before printing\", state.side === 'saved') : '') + '</span>';\n      return;\n    }\n    if (totallyEmpty) {\n      tabs = TABS.filter(function (t) { return t.key === 'upload'; });\n      state.tab = 'upload';\n    } else {\n      tabs = TABS.filter(function (t) {\n        if (t.key === 'all') return true;\n        if (t.key === 'archive') return IS_ACCOUNT && tabCount('archive') > 0;\n        if (t.key === 'studio')  return IS_ACCOUNT && tabCount('studio') > 0;\n        if (t.key === 'gangsave') return IS_ACCOUNT && tabCount('gangsave') > 0;\n        return tabCount(t.key) > 0;\n      });\n      /* Deleting/restoring the last design of the active tab would otherwise\n         leave the view pointed at a filter that no longer exists. */\n      if (state.tab !== 'all' && tabCount(state.tab) === 0) state.tab = 'all';\n    }\n    tabsEl.innerHTML = segHtml(tabs, state.tab, 'data-alv2-tab', tabCount);\n    if (!typesEl) return;\n    /* Nothing to choose between on a forced-type surface \u2014 or when only one\n       type (or none) has designs: a single chip is not a choice. */\n    /* No type axis inside the Gang Sheets tab \u2014 every card there is a sheet. */\n    typesEl.hidden = !!FORCED_TYPE || totallyEmpty || state.tab === 'gangsave';\n    if (!typesEl.hidden) {\n      var types = TYPES.filter(function (t) { return typeCount(t.key) > 0; });\n      if (types.length && !types.some(function (t) { return t.key === state.type; })) {\n        state.type = types[0].key;\n      }\n      typesEl.hidden = types.length < 2;\n      if (!typesEl.hidden) {\n        typesEl.innerHTML = segHtml(types, state.type, 'data-alv2-type', typeCount);\n      }\n    }\n  }\n\n  /* Which page numbers to show.\n\n     Every page used to be rendered. At a real library size that is unusable:\n     650 designs / 12 = 55 pages, measured at 57 buttons and 2644px of pager in\n     a 926px row. The 30-design mock (3 pages) hid it completely.\n\n     Below the threshold nothing changes \u2014 all pages still show, exactly as the\n     handoff draws them. Above it, first and last are pinned and a window of one\n     page either side of the current follows, with gaps between: 1 \u2026 4 5 6 \u2026 55.\n     Worst case is 7 cells plus the two arrows, which is what makes it fit. */\n  var GAP = '\\u2026';\n  var PAGER_SHOW_ALL_UPTO = 7;\n  var PAGER_WINDOW = 1;\n  function pageList(current, total) {\n    var out = [], last = 0;\n    if (total <= PAGER_SHOW_ALL_UPTO) {\n      for (var i = 1; i <= total; i++) out.push(i);\n      return out;\n    }\n    for (var p = 1; p <= total; p++) {\n      if (p !== 1 && p !== total && Math.abs(p - current) > PAGER_WINDOW) continue;\n      if (last && p - last > 1) out.push(GAP);\n      out.push(p);\n      last = p;\n    }\n    return out;\n  }\n\n  function renderPager(total, totalPages) {\n    if (totalPages <= 1) { pagerEl.hidden = true; return; }\n    pagerEl.hidden = false;\n    var pmr = pageMath(total);\n    var start = pmr.start + 1;\n    var end = Math.min(pmr.start + pmr.size, total);\n    rangeEl.textContent = start + '\u2013' + end + ' of ' + total;\n\n    var html = '<button type=\"button\" class=\"alv2-pager__btn alv2-pager__btn--arrow\" data-alv2-page=\"prev\"' +\n               (state.page === 1 ? ' disabled' : '') + ' aria-label=\"Previous page\">\u2039</button>';\n    pageList(state.page, totalPages).forEach(function (p) {\n      if (p === GAP) { html += '<span class=\"alv2-pager__gap\" aria-hidden=\"true\">\u2026</span>'; return; }\n      html += '<button type=\"button\" class=\"alv2-pager__btn\" data-alv2-page=\"' + p + '\"' +\n              (p === state.page ? ' aria-current=\"page\"' : '') + '>' + p + '</button>';\n    });\n    html += '<button type=\"button\" class=\"alv2-pager__btn alv2-pager__btn--arrow\" data-alv2-page=\"next\"' +\n            (state.page === totalPages ? ' disabled' : '') + ' aria-label=\"Next page\">\u203A</button>';\n    pagesEl.innerHTML = html;\n  }\n\n  /* Page surfaces pin the bar with position:fixed (see the page snippet for\n     why sticky is impossible there); fixed knows nothing about the column, so\n     the box is synced to the root's rect here. No-op wherever the CSS does\n     not make the bar fixed (the picker modal keeps its absolute bar). */\n  function syncSelbarBox() {\n    if (getComputedStyle(selbar).position !== 'fixed') return;\n    var r = root.getBoundingClientRect();\n    selbar.style.left = r.left + 'px';\n    selbar.style.width = r.width + 'px';\n    /* Dock at the component's end: while the root's bottom is below the fold\n       the bar pins to the viewport bottom, and once the footer scrolls into\n       view the bar rides up with the last row instead of hovering over the\n       footer (Owen 2026-09-02). This is the sticky behavior, reimplemented\n       for fixed because the portal's overflow ancestors break sticky. */\n    selbar.style.bottom = Math.max(0, window.innerHeight - r.bottom) + 'px';\n  }\n  window.addEventListener('resize', syncSelbarBox);\n  /* Per-scroll cost is one rect read, and only while a selection is active \u2014\n     the bar is display:none otherwise and the guard exits on hidden. */\n  window.addEventListener('scroll', function () {\n    if (!root.hasAttribute('data-has-selection')) return;\n    syncSelbarBox();\n  }, { passive: true });\n  if ('ResizeObserver' in window) new ResizeObserver(syncSelbarBox).observe(root);\n\n  function renderSelectionBar() {\n    syncSelbarBox();\n    var n = state.checked.length;\n    root.toggleAttribute('data-has-selection', n > 0);\n    if (n === 0) { selbar.hidden = true; return; }\n    selbar.hidden = false;\n\n    var picked = state.checked.map(byId).filter(Boolean);\n    var shown = picked.slice(0, 3);\n    var overflow = picked.length - shown.length;\n    selThumbs.innerHTML = shown.map(function (d) {\n      return '<img class=\"alv2-selthumb\" src=\"' + esc(d.thumb) + '\" alt=\"\">';\n    }).join('') + (overflow > 0 ? '<span class=\"alv2-selmore\">+' + overflow + '</span>' : '');\n    selThumbs.classList.toggle('alv2-selbar__thumbs--overflow', overflow > 0);\n\n    selTitle.textContent = n === 1 ? '1 item selected' : n + ' items selected';\n\n    /* Owen 2026-09-18 (supersedes 09-03): the ACCOUNT bar is three things \u2014\n       \"Order as DTF\" (gang single: \"Order as DTF Gang Sheet\", matching the\n       details panel; no count in the label, the title already says how many),\n       \"Ordering Options\" (one design \u2192 the ?file= modal; several by-size\n       designs \u2192 the same modal carrying the whole selection on the by-size\n       cards, which is where the old \"Order as UV DTF\" button went; the modal's\n       \"Gang sheets\" category is the builder deep link per film, which is where\n       \"Order as Gang Sheet\" went), and the dots menu (Archive, Delete).\n       Pickers keep \"Use Design(s)\" \u2014 there the design goes into the PDP, not\n       an order. */\n    var moreWrap = q('[data-alv2-selmore-wrap]');\n    var ooBtn = q('[data-alv2-selbar-oo]');\n    if (IS_ACCOUNT) {\n      var hasGang   = picked.some(function (d) { return !!d.gangsheet; });\n      var hasBySize = picked.some(function (d) { return !d.gangsheet; });\n      var mixed     = hasGang && hasBySize;\n      var multiGang = !mixed && hasGang && n > 1;\n\n      useManyBtn.hidden = mixed || multiGang;\n      /* Gang sheets can't go by-size, so gang-containing multis hide the\n         modal button (the note below explains); a single gang sheet still\n         gets it \u2014 the modal shows the film catalogue for those. */\n      if (ooBtn) ooBtn.hidden = mixed || multiGang || (n > 1 && hasGang);\n      if (selNote) {\n        selNote.hidden = !(mixed || multiGang);\n        selNote.textContent = mixed\n          ? 'By Size and Gang Sheet are ordered from different products \u2014 order them separately.'\n          : (multiGang ? 'Gang sheets are set up one at a time \u2014 order them separately.' : '');\n      }\n      if (!mixed && !multiGang) {\n        useManyLbl.textContent = primaryLabel(picked);\n      }\n      /* Archive-tab selections (selection clears on tab switch, so a checked\n         set is homogeneous): the ordering pair stands down and the bar shows\n         Restore + Delete permanently as the buttons; the dots menu hides \u2014\n         both its actions ARE the buttons here (Owen 2026-09-03). */\n      var allArchived = picked.every(function (d) { return !!d.archived; });\n      var restoreBtn = q('[data-alv2-selbar-restore]');\n      var delPermBtn = root.querySelector('.alv2-selbar__ctas [data-alv2-selbar-delete]');\n      if (allArchived) {\n        useManyBtn.hidden = true;\n        if (ooBtn) ooBtn.hidden = true;\n        if (selNote) selNote.hidden = true;\n        if (restoreBtn) restoreBtn.hidden = false;\n        if (delPermBtn) delPermBtn.hidden = false;\n        if (moreWrap) moreWrap.hidden = true;\n      } else {\n        if (restoreBtn) restoreBtn.hidden = true;\n        if (delPermBtn) delPermBtn.hidden = true;\n        if (moreWrap) moreWrap.hidden = false;\n      }\n    } else {\n      useManyBtn.hidden = false;\n      useManyLbl.textContent = n === 1 ? 'Use this Design' : 'Use ' + n + ' Designs';\n      if (ooBtn) ooBtn.hidden = true;\n      if (selNote) selNote.hidden = true;\n      if (moreWrap) moreWrap.hidden = true;\n      var rB = q('[data-alv2-selbar-restore]'); if (rB) rB.hidden = true;\n      var dB = root.querySelector('.alv2-selbar__ctas [data-alv2-selbar-delete]'); if (dB) dB.hidden = true;\n    }\n    /* Reorder-Ready files (ours) can't be archived or deleted \u2014 Justin 2026-10-13 */\n    if (moreWrap && picked.every(function (d) { return d.printReady; })) moreWrap.hidden = true;\n    if (selMenu && !selMenu.hidden) closeSelMenu();\n    /* Arming resets whenever the selection changes \u2014 a confirm that survived a\n       different set of designs would delete something else. */\n    disarmSelDelete();\n  }\n\n  function render() {\n    /* Locked until the library is on screen \u2014 see the load/render split. State\n       still advances; only the DOM build waits. */\n    if (!renderUnlocked) return;\n    /* Labs: one `open_<surface>` per mount, on the first render that has data\n       (v = library size). Hidden instances never render, so this is \"seen\". */\n    if (state.loaded && !labsOpened) { labsOpened = true; labs('open_' + LABS_SURFACE, state.designs.length); }\n    /* Fresh before any filter runs: the Saved/Purchased split reads purchase\n       twins from this index (matchesSide), not just the card dates. */\n    buildDateIndex();\n    renderTabs();\n    var list = visibleDesigns();\n    var total = list.length;\n    var pm = pageMath(total);\n    var totalPages = pm.totalPages;\n    if (state.page > totalPages) { state.page = totalPages; pm = pageMath(total); }\n\n    var pageItems = list.slice(pm.start, pm.start + pm.size);\n\n    var upTile = showUploadTile();\n    if (!state.loaded) {\n      loadingEl.hidden = false; gridEl.hidden = true; emptyEl.hidden = true; pagerEl.hidden = true;\n    } else if (total === 0) {\n      /* Two different empties: a filter/search with no hits keeps the\n         'No matches' copy; a library with nothing in it AT ALL gets the\n         get-started message (Owen 2026-09-01), paired with renderTabs'\n         uploads-only tab row. */\n      var noneAtAll = state.designs.length === 0;\n      var etitle = emptyEl.querySelector('.alv2-empty__title');\n      var esub = emptyEl.querySelector('.alv2-empty__sub');\n      /* STAFF LOOKUP gets a statement, not a call to action: the viewer is not\n         the owner and has no upload tile to act on, so \"Upload your first\n         design\" invited something the page will not accept (Justin 2026-09-30).\n         Customers keep the call to action \u2014 their empty library renders the\n         upload tile right beside it, which is how a first design gets added. */\n      if (etitle) etitle.textContent = noneAtAll\n        ? (LOOKUP ? 'This customer has no uploaded images yet' : 'Upload your first design to get started')\n        : 'No matches';\n      if (esub) {\n        esub.textContent = 'Try a different name, or upload new artwork.';\n        esub.hidden = noneAtAll;\n      }\n      if (RECENT_DAYS && !noneAtAll) {\n        /* the strip has no search box \u2014 \"No matches\" reads wrong; the host's copy wins */\n        if (etitle) etitle.textContent = root.getAttribute('data-empty-text') || ('No designs in the last ' + RECENT_DAYS + ' days.');\n        if (esub) esub.hidden = true;\n      }\n      /* The upload tile still shows on an empty view \u2014 on the true-empty\n         library it IS the get-started action the message points at. */\n      loadingEl.hidden = true; gridEl.hidden = upTile ? false : true; emptyEl.hidden = false; pagerEl.hidden = true;\n      if (upTile) gridEl.innerHTML = uploadTileHtml();\n    } else {\n      loadingEl.hidden = true; emptyEl.hidden = true;\n      gridEl.hidden = false;\n      buildDateIndex();\n      gridEl.innerHTML = (upTile ? uploadTileHtml() : '') + pageItems.map(cardHtml).join('');\n      if (RECENT_DAYS) pagerEl.hidden = true; else renderPager(total, totalPages);\n    }\n    renderSelectionBar();\n  }\n\n  /* \u2500\u2500 upload-into-library tile (Owen 2026-09-02) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     ACCOUNT surfaces only, By Size view, page 1 (an upload prepends under\n     Newest, so page 1 is where the result lands). Hidden on Purchases and\n     Archive \u2014 uploads do not belong to either. The actual transfer is the\n     data layer's uploadToLibrary \u2014 the SAME presign/PUT/saveData contract the\n     legacy panel uses. */\n  var uploadInput = q('[data-alv2-upload-input]');\n  var uploadBusy = 0;\n  function tileView() {\n    if (RECENT_DAYS) return IS_ACCOUNT;   /* the strip always leads with the upload tile */\n    /* Kind \u00D7 state: new artwork lands in Uploads \u2192 Saved; All includes Saved,\n       so the tile leads there too. Never on Purchased. */\n    if (KIND_MODE) return state.tab === 'uploads' && state.side !== 'purch' && !state.arch;\n    return IS_ACCOUNT && !FORCED_TYPE && state.type === 'bysize' &&\n      (state.tab === 'all' || state.tab === 'upload');\n  }\n  /* STAFF LOOKUP shows the upload tile again (Justin 2026-10-12; hidden 9-30):\n     staff upload ON BEHALF of the customer \u2014 the call passes CUSTOMER_ID, which\n     in lookup mode is the LOOKED-UP customer, so files land in their library.\n     The tile says so (\"this customer's library\"); delete/archive stay refused. */\n  function showUploadTile() { return tileView() && state.page === 1; }\n  /* \u26A0 Tile views hold PAGE_SIZE\u22121 designs on page 1 (Owen 2026-09-03: \"add or\n     subtract thumbnails to prevent orphans\"). The tile is a 25th grid item on\n     a 24-design page, so the last row always carried one orphan. Tile + 23 =\n     24 items, and 24 divides evenly by every column count this grid can\n     produce (2, 3 and 4 \u2014 auto-fill at minmax 22cqw caps at 4-up, the narrow\n     bands are explicit 2-up), so every row is full at every width. Later\n     pages have no tile and keep 24. All paging math (slice, pager range,\n     click clamp) MUST go through pageMath \u2014 a raw PAGE_SIZE multiply is off\n     by one page everywhere a tile view is involved. */\n  function pageMath(total) {\n    var cap1 = tileView() ? PAGE_SIZE - 1 : PAGE_SIZE;\n    var totalPages = Math.max(1, total <= cap1 ? 1 : 1 + Math.ceil((total - cap1) / PAGE_SIZE));\n    var start = state.page === 1 ? 0 : cap1 + (state.page - 2) * PAGE_SIZE;\n    var size = state.page === 1 ? cap1 : PAGE_SIZE;\n    return { cap1: cap1, totalPages: totalPages, start: start, size: size };\n  }\n  function uploadTileHtml() {\n    if (uploadBusy > 0) {\n      return '<div class=\"alv2-upcard\"><div class=\"alv2-upcard__box\" data-alv2-upload-tile>' +\n        '<span class=\"alv2-upcard__spin\" aria-hidden=\"true\"></span>' +\n        '<p class=\"alv2-upcard__title\">Uploading ' + (uploadBusy === 1 ? 'your design' : uploadBusy + ' designs') + '\u2026</p>' +\n        '</div></div>';\n    }\n    return '<div class=\"alv2-upcard\"><div class=\"alv2-upcard__box\" data-alv2-upload-tile role=\"button\" tabindex=\"0\" aria-label=\"Upload artwork to ' + (LOOKUP ? 'this customer\\'s' : 'your') + ' library\">' +\n      '<span class=\"alv2-upcard__icon\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 16V4\"/><path d=\"m6 10 6-6 6 6\"/><path d=\"M4 20h16\"/></svg></span>' +\n      '<p class=\"alv2-upcard__title\">Upload artwork</p>' +\n      '<p class=\"alv2-upcard__sub\">PNG, JPG, PDF, AI, EPS\u2026<br>Saved to ' + (LOOKUP ? 'this customer\\'s' : 'your') + ' library</p>' +\n      '</div></div>';\n  }\n  var UPLOAD_EXTS = ['png','jpg','jpeg','jfif','webp','heic','heif','avif','gif','bmp','svg','pdf','ai','eps','psd','tif','tiff'];\n  function startLibraryUploads(fileList) {\n    var files = [].slice.call(fileList || []).filter(function (f) {\n      var ext = (f.name.split('.').pop() || '').toLowerCase();\n      return UPLOAD_EXTS.indexOf(ext) > -1;\n    });\n    if (!files.length || uploadBusy) return;\n    uploadBusy = files.length;\n    state.page = 1;\n    render();\n    var failed = [];\n    Promise.all(files.map(function (f) {\n      return window.NTArtworkData.uploadToLibrary(CUSTOMER_ID, f, false)\n        ['catch'](function () { failed.push(f.name); });\n    })).then(function () {\n      uploadBusy = 0;\n      var ok = files.length - failed.length;\n      if (ok > 0) showToast(ok === 1 ? (window.NTArtworkData.smartFileName(files[0].name, 34) + ' added to your library') : (ok + ' designs added to your library'));\n      if (failed.length) showToast(failed.length + ' upload' + (failed.length > 1 ? 's' : '') + ' failed \u2014 try again');\n      /* nothing uploads INTO Reorder-Ready (or any other section): land on Single Images \u203A Uploads,\n         where the new file is (Justin 2026-10-21) */\n      if (ok > 0 && KIND_MODE) { state.tab = 'uploads'; state.side = 'saved'; state.sidePicked = true; state.arch = false; state.page = 1; }\n      /* Fresh fetch (uploadToLibrary cleared the cache) so the new records\n         render; sort Newest puts them right beside the tile. */\n      loadDesigns();\n      broadcastChange();\n    });\n  }\n  root.addEventListener('change', function (e) {\n    if (e.target !== uploadInput) return;\n    startLibraryUploads(uploadInput.files);\n    uploadInput.value = '';\n  });\n  root.addEventListener('dragover', function (e) {\n    var tile = e.target.closest && e.target.closest('[data-alv2-upload-tile]');\n    if (!tile) return;\n    e.preventDefault();\n    tile.classList.add('alv2-upcard__box--drag');\n  });\n  root.addEventListener('dragleave', function (e) {\n    var tile = e.target.closest && e.target.closest('[data-alv2-upload-tile]');\n    if (tile) tile.classList.remove('alv2-upcard__box--drag');\n  });\n  root.addEventListener('drop', function (e) {\n    var tile = e.target.closest && e.target.closest('[data-alv2-upload-tile]');\n    if (!tile) return;\n    e.preventDefault();\n    tile.classList.remove('alv2-upcard__box--drag');\n    if (e.dataTransfer && e.dataTransfer.files) startLibraryUploads(e.dataTransfer.files);\n  });\n\n  /* \u2500\u2500 FULL-PAGE drag-and-drop (Owen 2026-09-03) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     Wherever the upload box exists, dragging a file anywhere over the window\n     raises the dark \"Drop your file(s)\" screen and releasing ANYWHERE feeds\n     the same startLibraryUploads intake as the tile. Same pattern as the\n     PDP's initPageDrop (dev/bysize-v4/src/uploader.js) \u2014 preventDefault on\n     every dragover so an off-tile release can't navigate to the file.\n     Document listeners per root, but each bails unless THIS root is visible\n     AND currently showing the tile (showUploadTile) \u2014 so pickers, forced-type\n     surfaces, Purchases/Archive tabs and hidden pane copies never react, and\n     only one root can ever act on a given drop. */\n  var pageDropActive = false;\n  function pageDropEligible() {\n    if (RECENT_DAYS) return false;   /* dashboard strip: the upload card (dash-home-upload.js) owns page-wide drops */\n    return root.offsetParent !== null && showUploadTile() && !uploadBusy;\n  }\n  function isFileDrag(e) {\n    var types = e.dataTransfer && e.dataTransfer.types;\n    if (!types) return false;\n    for (var i = 0; i < types.length; i++) if (types[i] === 'Files') return true;\n    return false;\n  }\n  function showDropScreen() {\n    if (document.querySelector('.alv2-dropscreen')) return;\n    var el = document.createElement('div');\n    el.className = 'alv2-dropscreen';\n    el.innerHTML = '<div class=\"alv2-dropscreen__inner\">' +\n      '<div class=\"alv2-dropscreen__glyph\" aria-hidden=\"true\"></div>' +\n      '<div class=\"alv2-dropscreen__title\">Drop your file(s)</div>' +\n      '<div class=\"alv2-dropscreen__sub\">anywhere to add to your library</div>' +\n      '</div>';\n    document.body.appendChild(el);\n  }\n  function clearDropScreen() {\n    var el = document.querySelector('.alv2-dropscreen');\n    if (el) el.remove();\n    pageDropActive = false;\n  }\n  /* \u26A0 WINDOW capture, not document. PROVEN NECESSARY (dash-home-upload.js\n     found it first): a site-wide script calls stopPropagation() on the drop\n     at the window\u2192document boundary, so a document-level listener never sees\n     the release \u2014 the overlay raised but dropping did nothing (Owen 2026-09-03).\n     Window-capture fires alongside that script regardless. */\n  window.addEventListener('dragover', function (e) {\n    if (!pageDropEligible() || !isFileDrag(e)) return;\n    e.preventDefault();\n    if (!pageDropActive) { pageDropActive = true; showDropScreen(); }\n  }, true);\n  window.addEventListener('dragleave', function (e) {\n    if (pageDropActive && !e.relatedTarget) clearDropScreen();\n  }, true);\n  window.addEventListener('dragend', function () { if (pageDropActive) clearDropScreen(); }, true);\n  window.addEventListener('drop', function (e) {\n    if (!pageDropActive) return;\n    /* One intake for the whole page: swallow before the tile's own drop\n       handler so an on-tile release can't double-intake. */\n    e.preventDefault();\n    e.stopImmediatePropagation();\n    var files = e.dataTransfer && e.dataTransfer.files;\n    clearDropScreen();\n    if (files && files.length) startLibraryUploads(files);\n  }, true);\n\n  function resetToPageOne() { state.page = 1; }\n\n  /* ------------------------------------------------------------ actions */\n  /* Selection changes must NOT rebuild the grid. Everything the two-path rule\n     switches (card CTA visibility, frame corner radius + bottom border) is CSS\n     driven by [data-has-selection] on the root, so only the toggled card's\n     checkbox + ring actually change in the DOM. Re-rendering here would\n     re-create all 12 <img> elements on every click and flash the artwork. */\n  function syncSelectionDom() {\n    root.toggleAttribute('data-has-selection', state.checked.length > 0);\n    var cards = gridEl.querySelectorAll('[data-alv2-card]');\n    Array.prototype.forEach.call(cards, function (card) {\n      var on = isChecked(card.getAttribute('data-id'));\n      var box = card.querySelector('[data-alv2-check]');\n      if (box) box.setAttribute('aria-checked', on ? 'true' : 'false');\n      card.toggleAttribute('data-selected', on);\n    });\n    renderSelectionBar();\n  }\n\n  /* Shift range-select (Owen 2026-09-10). The ANCHOR is the last card whose\n     checkbox state was plainly toggled; a shift-click then selects every card\n     between anchor and target in the RENDERED page order. File-manager\n     semantics: the range is always SELECTED (never range-unselect), and the\n     anchor stays put so successive shift-clicks re-extend from the same\n     start. The anchor is resolved against the current DOM \u2014 after a page,\n     tab, sort or filter change the old anchor simply isn't in the grid and\n     the shift-click degrades to a plain toggle (which re-anchors). */\n  var selAnchorId = null;\n  function toggleCheck(id) {\n    id = String(id);\n    /* Edit-only rows never enter a selection \u2014 their file is a preview and\n       every selection exit is an order/use flow. The card renders no\n       checkbox; this guards the frame click and shift-range too. */\n    if (editOnly(byId(id))) return;\n    selAnchorId = id;\n    if (!ALLOW_MULTI) { state.checked = [id]; syncSelectionDom(); return; }\n    var i = state.checked.indexOf(id);\n    if (i > -1) state.checked.splice(i, 1); else state.checked.push(id);\n    syncSelectionDom();\n  }\n  function rangeCheck(id) {\n    id = String(id);\n    if (!ALLOW_MULTI || !selAnchorId || selAnchorId === id) return toggleCheck(id);\n    var order = [];\n    Array.prototype.forEach.call(gridEl.querySelectorAll('[data-alv2-card]'), function (c) {\n      order.push(String(c.getAttribute('data-id')));\n    });\n    var a = order.indexOf(selAnchorId), b = order.indexOf(id);\n    if (a < 0 || b < 0) return toggleCheck(id);\n    var lo = Math.min(a, b), hi = Math.max(a, b);\n    for (var i = lo; i <= hi; i++) {\n      /* Ranges skip edit-only rows for the same reason toggleCheck refuses\n         them \u2014 a swept-in preview would ride the selection into an order. */\n      if (editOnly(byId(order[i]))) continue;\n      if (state.checked.indexOf(order[i]) < 0) state.checked.push(order[i]);\n    }\n    syncSelectionDom();\n  }\n  function clearSelection() { state.checked = []; selAnchorId = null; syncSelectionDom(); }\n  /* Shift-click extends the browser's TEXT selection by default, which paints\n     a blue smear across the card names mid-range-select. Blocking mousedown\n     only while shift is held kills the artifact without touching normal\n     clicks, drags or copy behavior. */\n  gridEl.addEventListener('mousedown', function (e) { if (e.shiftKey) e.preventDefault(); });\n\n  /* Archive the checked designs.\n\n     Archived designs drop out of every tab (libraryForType filters them), and\n     v2 has no Archive tab to restore from \u2014 the handoff dropped it \u2014 so this\n     would be a one-way door without the Undo below. The endpoint is reversible\n     (restore=1), so Undo is a real restore rather than a local trick.\n\n     Not everything can be archived: the endpoint needs a photo_id, which\n     uploads carry and purchases substitute with the file's basename. Anything\n     with neither is skipped rather than silently appearing to succeed. */\n  /* Bulk delete, with the same arm-then-confirm the card menu uses. One click\n     never deletes: the label becomes \"Click again\", and it disarms itself after\n     4s so it cannot sit primed while the customer does something else. */\n  var selDelArmed = false, selDelTimer = 0;\n  function disarmSelDelete() {\n    if (selDelTimer) { clearTimeout(selDelTimer); selDelTimer = 0; }\n    if (!selDelArmed) return;\n    selDelArmed = false;\n    var dl0 = selDelLabelEl(); if (dl0) dl0.textContent = 'Delete permanently';\n  }\n  function deleteSelected() {\n    var picked = state.checked.map(byId).filter(Boolean);\n    if (!picked.length) return;\n    if (!selDelArmed) {\n      selDelArmed = true;\n      var dl1 = selDelLabelEl(); if (dl1) dl1.textContent = 'Click again to confirm';\n      selDelTimer = setTimeout(disarmSelDelete, 4000);\n      return;\n    }\n    disarmSelDelete();\n    /* Purchases carry no photo_id and cannot be deleted; say so rather than\n       firing requests that cannot work. */\n    var able = picked.filter(function (d) { return !!d.photoId && !state.deleting[String(d.id)]; });\n    if (!able.length) { showToast('Those designs cannot be deleted'); return; }\n    setDeleting(able.map(function (d) { return d.id; }), true);\n    Promise.all(able.map(function (d) {\n      return window.NTArtworkData.deleteDesign(CUSTOMER_ID, d)\n        .then(function () { return d; })\n        .catch(function () { return null; });\n    })).then(function (done) {\n      able.forEach(function (d) { delete state.deleting[String(d.id)]; });\n      var gone = done.filter(Boolean);\n      if (gone.length) labs('delete', gone.length);   /* Labs */\n      var goneIds = gone.map(function (d) { return String(d.id); });\n      state.designs = state.designs.filter(function (x) { return goneIds.indexOf(String(x.id)) === -1; });\n      state.checked = state.checked.filter(function (id) { return goneIds.indexOf(String(id)) === -1; });\n      render();\n      announceCount();\n        if (typeof gone !== 'undefined' && gone.length) broadcastChange();\n      var skipped = picked.length - gone.length;\n      var msg = gone.length === 1 ? '1 design permanently deleted'\n                                  : gone.length + ' designs permanently deleted';\n      if (skipped) msg += ', ' + skipped + ' skipped';\n      showToast(gone.length ? msg : 'Could not delete those designs');\n    });\n  }\n\n  function archiveSelected() { archiveDesigns(state.checked.map(byId).filter(function (d) { return d && !d.printReady; })); }\n\n  /* The other half of the one-way door. Undo on the toast only helps if you\n     are still looking at the toast; this is how something archived last week\n     comes back. */\n  function restoreDesigns(picked) {\n    if (!picked.length) return;\n    labs('restore', picked.length);   /* Labs */\n    var reqs = picked.map(function (d) {\n      d.archived = false;\n      return window.NTArtworkData.setArchived(CUSTOMER_ID, d, true);\n    });\n    render();\n    announceCount();\n    whenSettled(reqs).then(broadcastChange);\n    showToast(picked.length === 1 ? 'Design restored' : picked.length + ' designs restored');\n  }\n\n  /* Permanent delete of a single design.\n\n     \u26A0 Waits for the request before removing the row. Archive can drop the row\n     optimistically because it is reversible and has an Undo; delete has\n     neither, so a row that vanished on a request that then failed would read\n     as deleted until the next load and there would be no way back. On failure\n     the row stays and says so.\n\n     Purchases carry no photo_id (the archive endpoint takes a file basename\n     instead, the delete endpoint does not), so they are refused up front with\n     an honest message rather than a request that cannot work. */\n  function deleteDesign(d) {\n    if (!d.photoId) { showToast('That design cannot be deleted'); return; }\n    if (state.deleting[String(d.id)]) return;   /* already in flight */\n    setDeleting([d.id], true);\n    window.NTArtworkData.deleteDesign(CUSTOMER_ID, d)\n      .then(function () {\n        delete state.deleting[String(d.id)];\n        state.designs = state.designs.filter(function (x) { return String(x.id) !== String(d.id); });\n        state.checked = state.checked.filter(function (id) { return String(id) !== String(d.id); });\n        labs('delete', 1);   /* Labs */\n        render();\n        announceCount();\n        broadcastChange();\n        showToast('Design permanently deleted');\n      })\n      .catch(function () {\n        setDeleting([d.id], false);\n        showToast('Could not delete that design');\n      });\n  }\n\n  /* Permanent delete of an UNORDERED builder save (Owen 2026-09-29). Goes to\n     the builder's proxy delete, not /uploads/deleteData \u2014 a builder save has no\n     photoId. Same wait-then-remove discipline as deleteDesign (hard delete, no\n     Undo). A 409 means the server considers it ordered after all (raced an\n     order, or a stale card) \u2014 re-lock it to Reorder and say so rather than\n     leave a dead Delete. */\n  function deleteGangSaveFlow(d) {\n    if (!d || d.ordered) { showToast('Ordered gang sheets cannot be deleted'); return; }\n    if (state.deleting[String(d.id)]) return;   /* already in flight */\n    setDeleting([d.id], true);\n    window.NTArtworkData.deleteGangSave(CUSTOMER_ID, d)\n      .then(function () {\n        delete state.deleting[String(d.id)];\n        state.designs = state.designs.filter(function (x) { return String(x.id) !== String(d.id); });\n        state.checked = state.checked.filter(function (id) { return String(id) !== String(d.id); });\n        labs('delete', 1);   /* Labs */\n        render();\n        announceCount();\n        broadcastChange();\n        showToast('Gang sheet deleted');\n      })\n      .catch(function (err) {\n        delete state.deleting[String(d.id)];\n        if (err && err.code === 'ordered') {\n          d.ordered = true;\n          render();\n          showToast('That gang sheet was ordered and can\u2019t be deleted');\n        } else {\n          render();\n          showToast('Could not delete that gang sheet');\n        }\n      });\n  }\n\n  /* \u2500\u2500 overflow menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     ONE menu, moved to whichever card's dots were clicked. */\n  var menuEl  = q('[data-alv2-menu]');\n  var menuBtn = null;\n  var menuArmed = null;   /* action awaiting a second click to confirm */\n  var menuArmTimer = 0;\n\n  /* Arm state for the archived card's inline Delete link \u2014 one armed button at\n     a time, disarmed by timeout or by arming another card's link. */\n  var cardDelBtn = null, cardDelTimer = 0;\n  function disarmCardDel() {\n    if (cardDelTimer) { clearTimeout(cardDelTimer); cardDelTimer = 0; }\n    if (cardDelBtn) {\n      var s = cardDelBtn.querySelector('span');\n      if (s) s.textContent = 'Delete';\n      cardDelBtn = null;\n    }\n  }\n\n  /* Same again for the details panel's Delete permanently \u2014 its own state\n     because the panel outlives grid re-renders and syncs reset it. */\n  var zoomDelArmed = false, zoomDelTimer = 0;\n  function disarmZoomDel() {\n    if (zoomDelTimer) { clearTimeout(zoomDelTimer); zoomDelTimer = 0; }\n    zoomDelArmed = false;\n    if (zoomDelete) {\n      var s = zoomDelete.querySelector('span');\n      if (s) s.textContent = 'Delete permanently';\n    }\n  }\n\n  function disarmMenu() {\n    if (menuArmTimer) { clearTimeout(menuArmTimer); menuArmTimer = 0; }\n    if (!menuArmed || !menuEl) { menuArmed = null; return; }\n    var el = menuEl.querySelector('[data-alv2-menu-action=\"' + menuArmed + '\"] span');\n    if (el) el.textContent = 'Delete permanently';\n    menuArmed = null;\n  }\n\n  function closeMenu() {\n    if (!menuEl || menuEl.hidden) return;\n    disarmMenu();\n    menuEl.hidden = true;\n    if (menuBtn) { menuBtn.setAttribute('aria-expanded', 'false'); menuBtn = null; }\n  }\n\n  function openMenuFor(btn) {\n    var card = btn.closest('[data-alv2-card]');\n    if (!card || !menuEl) return;\n    closeMenu();\n    menuBtn = btn;\n    menuEl.setAttribute('data-for-id', card.getAttribute('data-id'));\n\n    /* \u26A0 Unhide BEFORE measuring. A hidden element has no box, so measuring\n       first puts the menu at 0x0 and it lands in the wrong place. */\n    /* \u26A0 One menu serves every card, so its labels are per-OPEN state, not\n       markup. On an archived design the same action restores rather than\n       archives \u2014 without this the Archive tab offers a button that re-archives\n       something already archived, which silently does nothing. */\n    var d = byId(card.getAttribute('data-id'));\n    var archiveSpan = menuEl.querySelector('[data-alv2-menu-action=\"archive\"] span');\n    if (archiveSpan) archiveSpan.textContent = (d && d.archived) ? 'Restore' : 'Archive';\n    /* Builder saves have no Archive (that lives on our uploads DB; builder saves\n       live in the builder's system) \u2014 an unordered save gets Delete only. */\n    var archiveItem = menuEl.querySelector('[data-alv2-menu-action=\"archive\"]');\n    if (archiveItem) archiveItem.hidden = !!(d && d.source === 'gangsave');\n\n    menuEl.hidden = false;\n    btn.setAttribute('aria-expanded', 'true');\n\n    var rr = root.getBoundingClientRect();\n    var br = btn.getBoundingClientRect();\n    var mr = menuEl.getBoundingClientRect();\n    /* Right-aligned to the button and opening UPWARD: the dots sit at the\n       bottom of a card, so downward would drop the menu off the last row of\n       every page. Flip down only when there is genuinely no room above. */\n    var top  = br.top - rr.top - mr.height - 6;\n    if (top < 0) top = br.bottom - rr.top + 6;\n    var left = br.right - rr.left - mr.width;\n    if (left < 0) left = 0;\n    menuEl.style.top  = top + 'px';\n    menuEl.style.left = left + 'px';\n\n    var first = menuEl.querySelector('.alv2-menu__item');\n    if (first) first.focus();\n  }\n\n  function runMenuAction(action) {\n    var d = byId(menuEl.getAttribute('data-for-id'));\n    if (!d) { closeMenu(); return; }\n\n    if (action === 'archive') {\n      closeMenu();\n      if (d.archived) { restoreDesigns([d]); } else { archiveDesigns([d]); }\n      return;\n    }\n\n    if (action === 'delete') {\n      /* Two-step inline confirm rather than a native confirm() or a new modal.\n         Delete is the only irreversible action here and it must not be one\n         click away \u2014 but a browser confirm is jarring inside a themed panel,\n         and a bespoke dialog is a lot of surface for one item. Arm, then\n         confirm, and disarm itself after 4s so it cannot sit primed. */\n      if (menuArmed !== 'delete') {\n        menuArmed = 'delete';\n        var span = menuEl.querySelector('[data-alv2-menu-action=\"delete\"] span');\n        if (span) span.textContent = 'Click again to confirm';\n        menuArmTimer = setTimeout(disarmMenu, 4000);\n        return;\n      }\n      closeMenu();\n      if (d.source === 'gangsave') { deleteGangSaveFlow(d); return; }\n      deleteDesign(d);\n    }\n  }\n\n  /* Capture phase. The card's own click handler treats a click anywhere on the\n     tile as \"use this design\", and it is bound on the same root \u2014 so this has\n     to win before the click reaches it, not merely stop it bubbling further. */\n  root.addEventListener('click', function (e) {\n    var more = e.target.closest && e.target.closest('[data-alv2-more]');\n    if (more) {\n      e.preventDefault(); e.stopPropagation();\n      if (menuBtn === more) closeMenu(); else openMenuFor(more);\n      return;\n    }\n    var item = e.target.closest && e.target.closest('[data-alv2-menu-action]');\n    if (item) {\n      e.preventDefault(); e.stopPropagation();\n      runMenuAction(item.getAttribute('data-alv2-menu-action'));\n    }\n  }, true);\n\n  document.addEventListener('click', function (e) {\n    if (!menuEl || menuEl.hidden) return;\n    if (menuEl.contains(e.target)) return;\n    if (menuBtn && menuBtn.contains(e.target)) return;\n    closeMenu();\n  });\n\n  /* \u26A0 stopImmediatePropagation, not stopPropagation. A shell's Escape handler\n     is bound on `document` too, and stopPropagation does not stop listeners on\n     the SAME node \u2014 so Escape would close the menu and the whole modal in one\n     press. Only fires while the menu is open, so nothing else is affected. */\n  document.addEventListener('keydown', function (e) {\n    if (e.key !== 'Escape' || !menuEl || menuEl.hidden) return;\n    e.stopImmediatePropagation();\n    var returnTo = menuBtn;\n    closeMenu();\n    if (returnTo) returnTo.focus();\n  });\n\n  /* Position is absolute against the root and goes stale the moment anything\n     scrolls under it. Closing beats trying to track it. */\n  window.addEventListener('scroll', closeMenu, true);\n  window.addEventListener('resize', closeMenu);\n\n\n  /* Takes a list so the selection bar and the per-card menu share ONE\n     implementation \u2014 including the skip rule, the Undo and the toast copy.\n     A second copy for the single-card case is how the two would drift. */\n  function archiveDesigns(picked) {\n    if (!picked.length) return;\n    var done = [];\n    var reqs = [];\n    picked.forEach(function (d) {\n      if (d.source !== 'purchase' && !d.photoId) return;\n      reqs.push(window.NTArtworkData.setArchived(CUSTOMER_ID, d, false));\n      d.archived = true;\n      done.push(d);\n    });\n    if (!done.length) {\n      showToast(picked.length === 1 ? 'That design cannot be archived' : 'Those designs cannot be archived');\n      return;\n    }\n    labs('archive', done.length);   /* Labs */\n    /* Drop only what was archived. The bulk path used to clear the whole\n       selection, which is right when it IS the selection but wrong when one\n       card is archived from its own menu mid-selection. */\n    state.checked = state.checked.filter(function (id) {\n      return !done.some(function (d) { return String(d.id) === String(id); });\n    });\n    render();\n    announceCount();\n    whenSettled(reqs).then(broadcastChange);   /* the other instance refetches AFTER the server has the change */\n    var skipped = picked.length - done.length;\n    var msg = (done.length === 1 ? '1 design archived' : done.length + ' designs archived');\n    if (skipped) msg += ', ' + skipped + ' skipped';\n    showToast(msg, 'Undo', function () {\n      var undo = done.map(function (d) {\n        d.archived = false;\n        return window.NTArtworkData.setArchived(CUSTOMER_ID, d, true);\n      });\n      hideToast();\n      labs('restore', done.length);   /* Labs: the toast's Undo is a restore too */\n      render();\n      announceCount();\n      whenSettled(undo).then(broadcastChange);\n      showToast(done.length === 1 ? 'Design restored' : 'Designs restored');\n    });\n  }\n\n  /* actionLabel/onAction are optional. An actionable toast lives longer than a\n     plain confirmation \u2014 2.2s is not enough time to read a message AND decide\n     to undo. */\n  var toastActionFn = null;\n  function showToast(msg, actionLabel, onAction) {\n    toastMsg.textContent = msg;\n    toastActionFn = onAction || null;\n    if (actionLabel) {\n      toastAction.textContent = actionLabel;\n      toastAction.hidden = false;\n    } else {\n      toastAction.hidden = true;\n    }\n    toastEl.hidden = false;\n    if (toastTimer) clearTimeout(toastTimer);\n    toastTimer = setTimeout(function () {\n      toastEl.hidden = true;\n      toastActionFn = null;\n    }, actionLabel ? 6000 : 2200);\n  }\n  function hideToast() {\n    if (toastTimer) { clearTimeout(toastTimer); toastTimer = null; }\n    toastEl.hidden = true;\n    toastActionFn = null;\n  }\n\n  /* Labs: an order flow left the library. `reorder` = how many of those\n     designs were PURCHASED rows (order lines) \u2014 the true re-orders. */\n  function labsOrder(items, evName) {\n    labs(evName, items.length);\n    var purch = items.filter(function (d) { return d && d.source === 'purchase'; }).length;\n    if (purch) labs('reorder', purch);\n  }\n\n  /* \u2500\u2500 reorder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     On the ACCOUNT surface there is no upload pipeline to hand a design to \u2014\n     md-picker:use-designs would fire into a page with no listener. What the\n     account offers instead is a reorder: same art, same size, already\n     approved, and only the quantity left to choose.\n\n     \u26A0 This NAVIGATES rather than adding to cart, which is what live does and\n     is deliberate. A by-size line needs about a dozen properties -- the imgix\n     URL with transform params baked in, _Original Image, _cartImg, _width /\n     _height, background / super-res flags, precut -- plus variant resolution\n     and tier pricing. The builder on the destination page owns that contract;\n     reproducing it here would be a second copy of it, free to drift.\n\n     \u26A0 orderName is what makes it a REORDER rather than a fresh add. The\n     destination reads it into window.__designReUsedByUrl / __designReUsedByName\n     and the cart-serialize code stamps\n         properties['design re-used'] = 'previously on order # NT-\u2026'\n     Uploads have no orderName and simply arrive as a normal pick. */\n  var REORDER_DTF  = '/products/dtf-transfers';\n  var REORDER_GANG = '/products/premium-dtf-gang-sheets';\n  var REORDER_UV   = '/products/uv-dtf-stickers-decals-by-size';\n  var REORDER_STICKER  = '/products/custom-stickers';\n  var REORDER_UV_GANG  = '/products/uv-dtf-gang-sheets';\n\n  /* Which product each past order line was bought from \u2014 every id here serves my_designs_selection\n     (verified on the live storefront). 7546683752531 = live DTF by-size v2, not stale; Custom Stickers\n     reuses the by-size template (no sticker JS, still live). \u26A0 Store-specific: the UK ids differ. */\n  /* multi   = the product page takes a whole selection (my_designs_selection).\n     gang    = a gang sheet product (one sheet at a time, ?file=).\n     handoff = the per-line Add CANNOT build this product's cart line \u2014 Spangle\n               needs its colour key, stickers their shape options, Puff /\n               Glitter Puff variants are Size \u00D7 Ink Color (no area bands), the\n               floor graphics' bands use an en dash \u2014 so that row, and the\n               primary, open the product page with the design loaded (?file=,\n               the same link the Ordering Options cards use) instead.\n     cta     = the \"Order as \u2026\" wording when it differs from the label.\n     Ids for the handoff rows verified against the live product pages\n     2026-09-29 (Justin: orders must tell DTF / UV DTF / Spangle / Stickers /\n     3D Puff / 3D Glitter Puff apart). */\n  var PRODUCT_BY_ID = {\n    '6969285312595': { path: REORDER_DTF,     label: 'DTF', multi: true },\n    '7546683752531': { path: REORDER_DTF,     label: 'DTF', multi: true },\n    '7000403607635': { path: REORDER_UV,      label: 'UV DTF', multi: true },\n    '7133807116371': { path: REORDER_STICKER, label: 'Stickers', multi: true },\n    '6932460994643': { path: REORDER_GANG,    label: 'Gang Sheet', cta: 'DTF Gang Sheet', gang: true },\n    '6995572850771': { path: REORDER_UV_GANG, label: 'UV Gang Sheet', cta: 'UV DTF Gang Sheet', gang: true },\n    '7548193177683': { path: '/products/spangle-transfers',           label: 'Spangle', handoff: true },\n    '7411038879827': { path: '/products/3d-puff-transfers',           label: '3D Puff', handoff: true },\n    '7735614013523': { path: '/products/3d-glitter-puff-transfers',   label: '3D Glitter Puff', handoff: true },\n    '7563553898579': { path: '/products/vinyl-stickers',              label: 'Vinyl Stickers', handoff: true },\n    '7563601444947': { path: '/products/bumper-stickers',             label: 'Bumper Stickers', handoff: true },\n    '7563619795027': { path: '/products/truck-stickers',              label: 'Truck Stickers', handoff: true },\n    '7697756356691': { path: '/products/custom-magnets',              label: 'Magnets', handoff: true },\n    '7747591372883': { path: '/products/custom-soft-vinyl-keychains', label: 'Keychains', handoff: true },\n    '7778296954963': { path: '/products/indoor-floor-graphics',       label: 'Indoor Floor Graphics', handoff: true },\n    '7778243969107': { path: '/products/outdoor-floor-graphics',      label: 'Outdoor Floor Graphics', handoff: true },\n    '7778300690515': { path: '/products/window-clings',               label: 'Window Clings', handoff: true },\n    '7778306392147': { path: '/products/low-tac-wall-graphics',       label: 'Wall Graphics', handoff: true }\n  };\n  var DTF_PRODUCT  = PRODUCT_BY_ID['6969285312595'];\n  var UV_PRODUCT   = PRODUCT_BY_ID['7000403607635'];\n  var GANG_PRODUCT = PRODUCT_BY_ID['6932460994643'];\n\n  /* \u26A0 A design is EITHER by-size OR gang sheet, never both (Owen). Every order\n     line on one design therefore comes from the same family, so the fallback\n     below can trust design.gangsheet even when a line's product_id is unknown \u2014\n     an unmapped id on a gang sheet design is still a gang sheet.\n\n     It also means the two families never mix WITHIN a design. They can still\n     mix across a multi-select, which is why the selection bar checks every\n     picked design rather than just the first. */\n  function productOfLine(line, design) {\n    var hit = line && line.productId && PRODUCT_BY_ID[line.productId];\n    if (hit) return hit;\n    /* Unmapped id: a product added since, or one retired. Fall back on the one\n       thing the feed always knows rather than guessing a product, and render no\n       method chip \u2014 saying nothing beats saying \"DTF\" about a sticker. */\n    return design && design.gangsheet\n      ? { path: REORDER_GANG, label: '' }\n      : { path: REORDER_DTF,  label: '' };\n  }\n\n  /* Which product leads? (Justin 2026-09-29) The account CTAs \u2014 the details\n     primary and the selection bar \u2014 lead with the product the design was LAST\n     bought as: its newest order line. Never ordered, or an unmapped product,\n     leads with DTF (DTF Gang Sheet for a gang design). Several designs lead\n     with a product only when every one was last bought as it AND its page\n     takes a selection (multi); otherwise DTF. The Ordering Options modal then\n     leaves out the product the primary already orders, so \"other\" means the\n     others \u2014 a UV design's modal offers DTF, a DTF design's offers UV. */\n  function lastBoughtAs(d) {\n    if (!d) return null;\n    var twin = lastOrderOf(d);\n    var line = twin && ((twin.history && twin.history[0]) || twin);\n    return (line && line.productId && PRODUCT_BY_ID[line.productId]) || null;\n  }\n  function primaryProduct(items) {\n    var gang = !!(items[0] && items[0].gangsheet);\n    var fallback = gang ? GANG_PRODUCT : DTF_PRODUCT;\n    var p = lastBoughtAs(items[0]);\n    if (!p || !!p.gang !== gang) return fallback;\n    for (var i = 1; i < items.length; i++) {\n      if ((lastBoughtAs(items[i]) || {}).path !== p.path) return fallback;\n    }\n    if (items.length > 1 && !p.multi) return fallback;\n    return p;\n  }\n  function primaryLabel(items) {\n    var p = primaryProduct(items);\n    return 'Order as ' + (p.cta || p.label);\n  }\n  function primaryExclude(items) {\n    var p = primaryProduct(items);\n    /* DTF gang sheets have no single card (the DTF films are variants). */\n    return p === GANG_PRODUCT ? [] : [p.path.split('/').pop()];\n  }\n  /* One design into a page that takes ?file= (gang sheets, and every product\n     the Ordering Options modal links one design at a time): the order file \u2014\n     the LINE's own artwork when a history row asks \u2014 plus the ordered size\n     for vector files and the preview passthrough. */\n  /* The past order a re-bought design comes from (Justin 2026-09-30): every\n     cart line gets \"_reorder: Design previously used on #NT-\u2026\" \u2014 straight\n     from addLineToCart, and on the product pages from ?ordertype=reorder&\n     order_name= (the ?file= engines' existing reorder params) or the\n     my_designs_selection payload's orderName. '' = never bought. */\n  /* Only OUR print-ready file is a reorder (Justin 2026-10-13): the customer's own image from\n     Purchased is a fresh order \u2014 no _reorder / design re-used / reorder params. */\n  function isPR(x) { var u = x && (x.artUrl || (x.file && window.NTArtworkData.orderFileUrl(x))); return !!(x && (x.printReady || (window.ntPrintReady && window.ntPrintReady.isPrintReady(u || '')))); }\n  function reorderRef(line) { return isPR(line) ? String(line.orderName || '').replace(/^#/, '').trim() : ''; }\n  function newestLine(d) { var t = d && lastOrderOf(d); return t && ((t.history && t.history[0]) || t); }\n  function reorderParams(line) {\n    var rr = reorderRef(line);\n    return rr ? '&ordertype=reorder&order_name=' + encodeURIComponent(rr) : '';\n  }\n  function fileHref(path, d, line) {\n    var src = line && line.artUrl ? { file: cleanArtUrl(line.artUrl) } : d;\n    var url = path + '?file=' + encodeURIComponent(window.NTArtworkData.orderFileUrl(src)) + reorderParams(line || newestLine(d));\n    if (window.NTArtworkData.isVectorFile(src.file || '')) {\n      var dims = window.NTArtworkData.parseOrderedSize((line || lastOrderOf(d) || d).variantTitle);\n      if (dims) url += '&orderFileWidth=' + dims.width + '&orderFileHeight=' + dims.height;\n    }\n    var cur = new URLSearchParams(window.location.search);\n    if (cur.has('preview_theme_id')) url += '&preview_theme_id=' + encodeURIComponent(cur.get('preview_theme_id'));\n    return url;\n  }\n\n  function reorderPayload(items) {\n    return items.map(function (d) {\n      var p = { id: String(d.id), name: d.fileName, fileURL: window.NTArtworkData.orderFileUrl(d) };\n\n      /* \u26A0 Order facts come from the PURCHASE TWIN, not from `d`.\n\n         The dedupe keys on source + file, so a design you both uploaded and\n         later bought exists as TWO records. The grid shows the upload one, and\n         its card says \"Ordered\" because the date is already read from the twin\n         \u2014 but the twin is where orderName and variantTitle live. Reading them\n         off `d` gave a payload with neither, so a design the customer sees as\n         ordered would arrive untagged and be treated as a fresh upload:\n         no \"design re-used\" property, and the size not pre-filled.\n\n         lastOrderOf() is the same lookup the details panel uses. */\n      var order = lastOrderOf(d) || d;\n      var dims = window.NTArtworkData.parseOrderedSize(order.variantTitle);\n      if (dims) { p.designWidth = String(dims.width); p.designHeight = String(dims.height); }\n      if (order.orderName && isPR(d)) p.orderName = String(order.orderName);\n      return p;\n    });\n  }\n\n  /* Carries preview_theme_id through, or a reorder from a theme preview lands\n     on the live product page and silently tests the wrong theme. */\n  function reorderHref(path, items) {\n    var url = path + '?my_designs_selection=' + encodeURIComponent(JSON.stringify(reorderPayload(items)));\n    var cur = new URLSearchParams(window.location.search);\n    if (cur.has('preview_theme_id')) {\n      url += '&preview_theme_id=' + encodeURIComponent(cur.get('preview_theme_id'));\n    }\n    return url;\n  }\n\n  /* Reorder ONE historical line: that line's size AND that line's product.\n\n     Both come off the order row, so a design bought at 3x3 as UV and at 4x6 as\n     DTF reorders correctly from either row \u2014 which is the whole point of\n     hanging this off the line rather than the design. */\n  /* Resolve an order line's variant_title to a Shopify variant id.\n\n     \u26A0 The products do NOT share a variant model, which is why this matches on\n     the title rather than assuming a shape:\n       DTF by-size   50 variants, \"Style #1-9\" \u2014 PRICE TIERS. The real size is\n                     never a variant; it travels as _width/_height properties,\n                     which is what designWidth/designHeight already feeds.\n                     A feed title like \"22.00 X 22\" matches nothing here, so\n                     this returns null and the size params do the work. Correct.\n       UV by-size    48 variants, `3\" x 3\"` \u2014 size IS the variant.\n       Stickers      22 variants, same shape as UV.\n       DTF gang      40 variants, \"5 Feet / Glitter\" \u2014 length x film style.\n       UV gang       8 variants, \"5 Feet\" \u2014 length only, no film style.\n\n     So gang sheets and stickers cannot be reordered by width and height at all;\n     they need the variant. Matching the exact title covers every case without\n     encoding five different rules.\n\n     Cached per product: a customer reordering three lines from one product\n     should not fetch the same variant list three times. */\n  var VARIANT_CACHE = {};\n  function variantIdFor(path, variantTitle) {\n    if (!variantTitle) return Promise.resolve(null);\n    return productVariants(path).then(function (variants) {\n      var want = String(variantTitle).trim().toLowerCase();\n      for (var i = 0; i < variants.length; i++) {\n        if (String(variants[i].title).trim().toLowerCase() === want) return variants[i].id;\n      }\n      return null;\n    });\n  }\n\n  /* \u2500\u2500 direct cart add for a reorder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     A reorder does not need the builder: the art is already in the system.\n     Purchase records store the ORDER'S artwork URL with its transforms baked\n     in \u2014 verified against live, where 7 of 13 carry trim=colorUnlessAlpha and\n     2 also carry bg-remove=true. So the artwork property is the stored URL\n     VERBATIM, not something reconstructed from theme config, and the flags are\n     read back off that URL rather than guessed.\n\n     \u26A0 Unescape &amp; first. One of the 13 live records stores\n     \"trim=colorUnlessAlpha&amp;bg-remove=true\". Proven consequential: the\n     escaped URL serves image/jpeg at 1.57MB (no alpha \u2014 background BACK), the\n     corrected one image/png at 5.76MB. Passing it verbatim would reorder the\n     wrong artwork.\n\n     \u26A0 NO price is computed here. By-size tiers are cumulative across the whole\n     cart, so any number shown next to a qty stepper would disagree with\n     checkout the moment anything else is in the basket. The variant sets the\n     base rate and the cart applies the tier. */\n  function cleanArtUrl(u) { return String(u || '').replace(/&amp;/g, '&'); }\n\n  /* By-size variants are AREA BANDS, titled \"Style #1-9\". The order line's\n     variant_title is the SIZE (\"22.00 X 22\"), which matches no variant title,\n     so a title lookup cannot work here \u2014 the band has to be computed, exactly\n     as the builder's matchCustomVariant does: ceil(w*h), then the band holding\n     it, clamped to the largest. Verified against live: 3x3 -> Style #1-9,\n     12x12 -> #140-149, 22x22 -> #470-509, bands contiguous with no gaps.\n     \u26A0 The product also carries 16 exact-size \"popular\" variants; those are a\n     different pricing path and are deliberately not matched here. */\n  function bandVariantFor(path, w, h) {\n    return productVariants(path).then(function (variants) {\n      var area = Math.ceil((parseFloat(w) || 0) * (parseFloat(h) || 0)) || 1;\n      var bands = [];\n      variants.forEach(function (v) {\n        var m = /#\\s*([\\d.]+)\\s*-\\s*([\\d.]+)/.exec(v.title || '');\n        if (m) bands.push({ id: v.id, min: +m[1], max: +m[2] });\n      });\n      if (!bands.length) return null;\n      bands.sort(function (a, b) { return a.min - b.min; });\n      var top = bands[bands.length - 1];\n      if (area > top.max) return top.id;\n      for (var i = bands.length - 1; i >= 0; i--) {\n        if (area >= bands[i].min && area <= bands[i].max) return bands[i].id;\n      }\n      return null;\n    });\n  }\n\n  function productJson(path) {\n    if (!VARIANT_CACHE[path]) {\n      VARIANT_CACHE[path] = fetch(path + '.js')\n        .then(function (r) { return r.ok ? r.json() : null; })\n        .catch(function () { return null; });\n    }\n    return VARIANT_CACHE[path];\n  }\n  function productVariants(path) { return productJson(path).then(function (p) { return (p && p.variants) || []; }); }\n  /* The product's quantity-break rules, keyed by product TYPE in the shop's\n     combine_group_split_config (the table the cart uses). */\n  function tierRules(type) { return window.NTQtyTiers ? window.NTQtyTiers.rulesFor(type) : null; }   /* one copy: assets/nt-qty-tiers.js */\n\n  /* After a successful add, make the ADD visible outside this panel. Without\n     this the only evidence was our own toast \u2014 the header badge kept its old\n     count and Owen had to fetch /cart.js to know it worked. Same recipe the\n     by-size builder uses after its adds (bysize-v4 showCartConfirm): repaint\n     [data-header-cart-count] / [data-header-cart-total] from a no-store\n     /cart.js, then fire the theme's own 'cart-updated' so every listener\n     (upsell popups, drawer) reacts exactly as it would to a builder add. */\n  /* Ported from bysize-v4's showCartConfirm: same structure, same 4s dismiss,\n     same hover-pause (mouseenter clears the timer, mouseleave re-arms at 1.5s),\n     same manual close. Portals to <body> because the account page scrolls \u2014\n     position:fixed inside a transformed ancestor would pin to the wrong box. */\n  function showCartToast(c) {\n    var old = document.querySelector('.alv2-cartok');\n    if (old) old.remove();\n    var el = document.createElement('div');\n    el.className = 'alv2-cartok';\n    el.setAttribute('role', 'status');\n    var price = (typeof c.total === 'number' && c.total > 0) ? '$' + c.total.toFixed(2) : '';\n    var K = 'alv2-cartok__';\n    el.innerHTML =\n      '<div class=\"' + K + 'head\"><span class=\"' + K + 'check\" aria-hidden=\"true\">' +\n      '<svg viewBox=\"0 0 24 24\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 12.5l5.5 5.5L20 6.5\"/></svg>' +\n      '</span><strong>Added to cart</strong>' +\n      '<button type=\"button\" class=\"' + K + 'x\" aria-label=\"Close\">&times;</button></div>' +\n      (c.name\n        ? '<div class=\"' + K + 'body\">' +\n          (c.thumb ? '<img class=\"' + K + 'thumb\" src=\"' + esc(c.thumb) + '\" alt=\"\">' : '') +\n          '<span class=\"' + K + 'meta\"><strong class=\"' + K + 'name\"></strong>' +\n          '<span class=\"' + K + 'qty\">Qty ' + (c.qty || 1) + '</span></span>' +\n          (price ? '<strong class=\"' + K + 'price\">' + price + '</strong>' : '') + '</div>'\n        : '');\n    el.querySelector('.' + K + 'name') && (el.querySelector('.' + K + 'name').textContent = c.name || '');\n    document.body.appendChild(el);\n    /* \u26A0 setTimeout, not requestAnimationFrame. rAF is suspended in background\n       tabs, so a toast triggered while the tab was not front never got its\n       is-in class and sat at opacity:0 \u2014 an invisible confirmation. Found\n       driving the sandbox via CDP; a customer switching tabs mid-add hits the\n       same thing. */\n    setTimeout(function () { el.classList.add('is-in'); }, 20);\n    var dismiss = function () { el.classList.remove('is-in'); setTimeout(function () { el.remove(); }, 300); };\n    var timer = setTimeout(dismiss, 4000);\n    el.addEventListener('mouseenter', function () { clearTimeout(timer); });\n    el.addEventListener('mouseleave', function () { clearTimeout(timer); timer = setTimeout(dismiss, 1500); });\n    el.querySelector('.' + K + 'x').addEventListener('click', function () { clearTimeout(timer); dismiss(); });\n  }\n\n  /* Rebuild the slide-out cart after an add, the way every other add flow on\n     this theme does it (component-product-form, component-quick-buy,\n     component-cart all carry this same block \u2014 there is no shared helper to\n     call): fetch ?section_id=helper-cart, swap #AjaxCartForm's contents,\n     re-ajaxify, swap #AjaxCartSubtotal, badges from the section's own\n     [data-cart-count]/[data-cart-total], then the theme's cart-updated event.\n\n     \u26A0 Without the swap the drawer keeps its server-rendered contents from page\n     load: the badge ticked but opening the cart showed the OLD lines until a\n     refresh (Owen). The badge event alone never touched the drawer.\n\n     Falls back to the /cart.js badge repaint on any surface without the drawer\n     markup, so the account page cannot break if the sidebar section moves. */\n  function syncCartUi() {\n    var drawer = document.getElementById('AjaxCartForm');\n    if (drawer) {\n      return fetch('?section_id=helper-cart', { cache: 'no-store' })\n        .then(function (r) { return r.text(); })\n        .then(function (text) {\n          var doc = new DOMParser().parseFromString(text, 'text/html');\n          var form = doc.getElementById('AjaxCartForm');\n          var sub = doc.getElementById('AjaxCartSubtotal');\n          if (!form) return;\n          window.__ntCartCache = null;\n          drawer.innerHTML = form.innerHTML;\n          if (typeof drawer.ajaxifyCartItems === 'function') drawer.ajaxifyCartItems();\n          var subEl = document.getElementById('AjaxCartSubtotal');\n          if (sub && subEl) subEl.innerHTML = sub.innerHTML;\n          var n = (drawer.querySelector('[data-cart-count]') || {}).textContent || '';\n          if (n) {\n            document.querySelectorAll('[data-header-cart-count]').forEach(function (el) {\n              el.textContent = n; el.setAttribute('data-count', n);\n            });\n          }\n          var tot = (drawer.querySelector('[data-cart-total]') || {}).textContent || '';\n          if (tot) {\n            document.querySelectorAll('[data-header-cart-total]').forEach(function (el) { el.textContent = tot; });\n          }\n          try { document.dispatchEvent(new CustomEvent('cart-updated', { bubbles: true })); } catch (e) {}\n        }).catch(function () {});\n    }\n    /* No drawer on this surface \u2014 badge-only repaint. */\n    return fetch('/cart.js', { cache: 'no-store' })\n      .then(function (r) { return r.json(); })\n      .then(function (c) {\n        var n = c && Number(c.item_count);\n        if (isFinite(n) && n > 0) {\n          document.querySelectorAll('[data-header-cart-count]').forEach(function (el) {\n            el.textContent = String(n); el.setAttribute('data-count', String(n));\n          });\n          if (typeof c.total_price === 'number') {\n            var money = '$' + (c.total_price / 100).toFixed(2);\n            document.querySelectorAll('[data-header-cart-total]').forEach(function (el) { el.textContent = money; });\n          }\n        }\n        try { document.dispatchEvent(new CustomEvent('cart-updated', { bubbles: true })); } catch (e) {}\n      }).catch(function () {});\n  }\n\n  function addLineToCart(d, line, qty) {\n    var art = cleanArtUrl(line.artUrl || d.file);\n    var dims = window.NTArtworkData.parseOrderedSize(line.variantTitle);\n    var target = productOfLine(line, d).path;\n\n    var resolve = dims\n      ? bandVariantFor(target, dims.width, dims.height)\n      : variantIdFor(target, line.variantTitle);\n\n    return resolve.then(function (vid) {\n      if (!vid) throw new Error('no variant');\n      var props = {};\n      /* The stored URL IS the approved artwork. */\n      props['Upload (Vector Files Preferred)'] = art;\n      props['_cartImg'] = art;\n      /* Read the treatments back off the art rather than assuming: this is a\n         reorder of what was printed, so it must not silently drop a background\n         removal the customer paid for. */\n      props['Remove Background'] = /bg-remove=true/.test(art) ? 'Yes' : 'No';\n      props['Super Resolution']  = /upscale=true/.test(art) ? 'Yes' : 'No';\n      if (dims) { props['_width'] = String(dims.width); props['_height'] = String(dims.height); }\n      if (reorderRef(line)) props['design re-used'] = 'previously on order # ' + line.orderName;\n      if (reorderRef(line)) props['_reorder'] = 'Design previously used on #' + reorderRef(line);\n      /* print-ready file (production-art-sync): its own reorder note (EXACT at the size as ordered,\n         SIMILAR at a size edited in the panel), preview, no BG/SR */\n      if (window.ntPrintReady) props = window.ntPrintReady.lineProps(props, reorderRef(line), { resized: !!line.resized });\n\n      return fetch('/cart/add.js', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ items: [{ id: vid, quantity: qty, properties: props }] })\n      }).then(function (r) {\n        if (!r.ok) return r.text().then(function (t) { throw new Error(t.slice(0, 120)); });\n        return r.json();\n      });\n    });\n  }\n\n  function reorderLine(d, idx) {\n    if (!d) return;\n    var order = lastOrderOf(d) || d;\n    var line = (order.history || [])[idx];\n    if (!line) return;\n    var dims = window.NTArtworkData.parseOrderedSize(line.variantTitle);\n    var p = { id: String(d.id), name: d.fileName, fileURL: window.NTArtworkData.orderFileUrl(d) };\n    if (dims) { p.designWidth = String(dims.width); p.designHeight = String(dims.height); }\n    /* THIS line's order number, so the cart is tagged with the order they\n       actually chose rather than the most recent one. */\n    if (isPR(d)) p.orderName = String(line.orderName || order.orderName || '');\n    var target = productOfLine(line, d).path;\n    /* \u26A0 Await the variant BEFORE navigating. Firing the navigation and\n       resolving after would drop the variant every time. A gang sheet without\n       it lands on the default length and film style \u2014 the wrong reorder,\n       wearing the right label. */\n    variantIdFor(target, line.variantTitle).then(function (vid) {\n      var url = target + '?my_designs_selection=' + encodeURIComponent(JSON.stringify([p]));\n      if (vid) url += '&variant=' + encodeURIComponent(vid);\n      var cur = new URLSearchParams(window.location.search);\n      if (cur.has('preview_theme_id')) url += '&preview_theme_id=' + encodeURIComponent(cur.get('preview_theme_id'));\n      window.location.href = url;\n    });\n  }\n\n  /* One navigation at a time. The busy class is cosmetic; this flag is the\n     actual double-click guard \u2014 a second click during the variant lookup would\n     otherwise fire a second navigation. */\n  var navPending = false;\n  /* \u26A0 Browser Back restores this page from bfcache EXACTLY as it left:\n     navPending true, spinner class on the button, pointer-events off \u2014 every\n     order CTA permanently dead until a hard reload. pageshow with .persisted\n     is the restore signal; reset the lock and strip the busy state. */\n  window.addEventListener('pageshow', function (e) {\n    if (!e.persisted) return;\n    navPending = false;\n    root.querySelectorAll('.alv2-busy').forEach(function (b) {\n      b.classList.remove('alv2-busy');\n      b.disabled = false;\n    });\n  });\n  function navBusy(btn) {\n    if (navPending) return false;\n    navPending = true;\n    if (btn) { btn.classList.add('alv2-busy'); btn.disabled = true; }\n    return true;\n  }\n\n  /* \"Other Ordering Options\": live's modal, armed the same way \u2014 every card\n     href becomes /products/<handle>?file=<the design's order file> plus vector\n     dimensions when the design is a vector. Gang sheet designs get the gang\n     grid, whose cards carry pinned variants. preview_theme_id is carried so a\n     sandbox click stays on the sandbox (live's panel omits this; its links\n     landing on the published theme is why testing it there is confusing). */\n  /* \"Other Ordering Options\" \u2192 the shared modal (assets/nt-oo-modal.js). The\n     href builder keeps this surface's rules: ordered-size params for vector\n     files and the preview_theme_id passthrough. */\n  function openOrderingOptions(d, excl) {\n    if (!d || !window.NTOO) return;\n    if (Array.isArray(d)) {\n      if (d.length !== 1) { openOrderingOptionsMulti(d); return; }\n      d = d[0];\n    }\n    labs('oo_open');   /* Labs */\n    var file = window.NTArtworkData.orderFileUrl(d);\n    var vp = '';\n    if (window.NTArtworkData.isVectorFile(d.file || '')) {\n      var line = lastOrderOf(d) || d;\n      var dims = window.NTArtworkData.parseOrderedSize(line.variantTitle);\n      if (dims) vp = '&orderFileWidth=' + dims.width + '&orderFileHeight=' + dims.height;\n    }\n    var cur = new URLSearchParams(window.location.search);\n    var pv = cur.has('preview_theme_id') ? '&preview_theme_id=' + encodeURIComponent(cur.get('preview_theme_id')) : '';\n    window.NTOO.open({\n      title: d.fileName || '',\n      thumb: d.thumb || '',\n      file: file,\n      catalog: d.gangsheet ? 'gangsheet' : 'bysize',\n      exclude: excl || primaryExclude([d]),\n      gsb: d.gangsheet ? null : gsbOptions([d]),\n      __alv2Root: root,\n      hrefFor: function (handle, variant) {\n        var url = '/products/' + handle + '?';\n        if (variant) url += 'variant=' + variant + '&';\n        return url + 'file=' + encodeURIComponent(file) + vp + pv + reorderParams(newestLine(d));\n      }\n    });\n  }\n  /* Several by-size designs at once (Owen 2026-09-18: the bar's \"Order as UV\n     DTF\" folded into this). The modal opens in multi mode \u2014 only cards whose\n     PDP consumes my_designs_selection (the by-size v4 engine: UV, Puff,\n     Glitter Puff, Spangle) stay, marked data-nt-oo-multi in nt-oo-cards \u2014 and\n     every href is the same hand-off the primary uses, just to that product. */\n  function openOrderingOptionsMulti(items) {\n    items = (items || []).filter(function (d) { return d && !d.gangsheet; });\n    if (!items.length || !window.NTOO) return;\n    labs('oo_open', items.length);   /* Labs */\n    window.NTOO.open({\n      title: items.length + ' designs',\n      thumb: items[0].thumb || '',\n      thumbs: items.map(function (d) { return d.thumb || ''; }),\n      file: window.NTArtworkData.orderFileUrl(items[0]),\n      catalog: 'bysize',\n      multi: items.length,\n      exclude: primaryExclude(items),\n      gsb: gsbOptions(items),\n      __alv2Root: root,\n      hrefFor: function (handle) { return reorderHref('/products/' + handle, items); }\n    });\n  }\n  function closeOrderingOptions() { if (window.NTOO) window.NTOO.close(); }\n\n  /* `prod` is a PRODUCT_BY_ID entry (primaryProduct); the studio-save paths\n     still pass 'dtf', which means DTF (a gang design: the DTF gang sheet). */\n  function reorder(items, prod) {\n    if (!items || !items.length) return;\n    markUsed(items);   /* applying to a PDP counts as last-used (Owen 2026-09-28) */\n    if (!prod || typeof prod !== 'object') {\n      prod = prod === 'uv' ? UV_PRODUCT : (items.every(function (d) { return !!d.gangsheet; }) ? GANG_PRODUCT : DTF_PRODUCT);\n    }\n    var uv = prod.path === REORDER_UV || prod.path === REORDER_UV_GANG;\n    labsOrder(items, uv ? 'order_uv' : (prod.gang ? 'order_gang' : (prod.handoff ? 'order_other' : 'order_dtf')));   /* Labs */\n    if (prod.gang || prod.handoff) {\n      /* \u26A0 The gang page does NOT consume my_designs_selection (that is the\n         by-size multiupload contract) \u2014 a gang reorder sent that way lands on\n         a bare product page (Owen 2026-09-02). The gang engine takes ?file=,\n         one sheet at a time \u2014 the same contract the ordering-options gang\n         cards and live's panel use; so do the one-design products (handoff).\n         Multi selections never lead with either (primaryProduct), so items[0]\n         is the whole selection here. */\n      window.location.href = fileHref(prod.path, items[0], null);\n      return;\n    }\n    window.location.href = reorderHref(prod.path, items);\n  }\n\n  /* THE DROP-IN CONTRACT. detail.items must be full design objects in the\n     processItem shape \u2014 four document listeners consume this. */\n  function useDesigns(items, message) {\n    if (!items || !items.length) return;\n    markUsed(items);   /* Use Design \u2192 PDP handoff is a use (Owen 2026-09-28) */\n    /* \u26A0 ACCOUNT surfaces have no md-picker listener \u2014 the four consumers all\n       live on product pages. Dispatching there showed an 'added' toast and\n       did nothing (Owen 2026-09-02: gang Use Design dead on the designs\n       page). Use = the reorder handoff on the account: by-size via\n       my_designs_selection, gang via ?file= \u2014 same routing as the details\n       primary and the selection-bar CTA. */\n    if (IS_ACCOUNT) { reorder(items, primaryProduct(items)); return; }\n    labsOrder(items, 'use_design');   /* Labs: picker hand-off */\n    /* A PURCHASED design keeps its order number even when its card is the\n       upload twin, so the product page stamps _reorder / design re-used\n       (Justin 2026-09-30: only designs that were bought; plain uploads get\n       neither \u2014 their newestLine is null). */\n    items = items.map(function (d) {\n      var o = !d.orderName && newestLine(d);\n      var out = !isPR(d) ? Object.assign({}, d, { orderName: '' }) : o && o.orderName ? Object.assign({}, d, { orderName: o.orderName }) : d;\n      /* Print-ready purchase (production-art-sync): hand the product page the print-ready file,\n         exactly as My Designs does (orderFileUrl), with no bg-remove / upscale params \u2014 the page\n         then treats it as print-ready (assets/nt-print-ready.js hides Remove BG / Upscale and\n         writes the reorder note) instead of re-processing the old upload (Justin 2026-10-13). */\n      if (d.prod && d.prod.url) out = Object.assign({}, out, { file: window.NTArtworkData.orderFileUrl(d) });\n      return out;\n    });\n    try {\n      root.dispatchEvent(new CustomEvent('md-picker:use-designs', {\n        bubbles: true, detail: { items: items }\n      }));\n    } catch (e) {}\n    showToast(message);\n    /* Closing is the SHELL's decision, not ours \u2014 an on-page library has\n       nothing to close. The shell listens for md-picker:use-designs (it\n       bubbles) and dismisses itself after the toast has landed. */\n  }\n  function useOne(d) {\n    if (!d) return;\n    useDesigns([d], window.NTArtworkData.smartFileName(d.fileName, 34) + ' added');\n  }\n  function useChecked() {\n    var picked = state.checked.map(byId).filter(Boolean);\n    if (!picked.length) return;\n    var msg = picked.length === 1\n      ? window.NTArtworkData.smartFileName(picked[0].fileName, 34) + ' added'\n      : picked.length + ' designs added';\n    state.checked = [];\n    useDesigns(picked, msg);\n  }\n\n  /* --------------------- Gang Sheet Builder deep link (Ordering Options) */\n  /* Contract (builder PR #612): /apps/ninja-gang-sheet?add=<JSON [{k,n}]>.\n     k = the imgix OBJECT KEY \u2014 the path after the host, no query. The builder\n     resolves keys against its own imgix host and rejects schemes/authorities/\n     traversal per entry, so keys (not URLs) keep the link short and\n     un-spoofable. `add` is set through searchParams \u2014 encoded exactly ONCE\n     (the my_designs_selection handlers double-encode; do not copy them).\n     The modal's \"Gang sheets\" cards add `type=<film>` (dtf | uv-dtf | glitter\n     | glow-dark | gold-foil | silver-foil \u2014 the builder's transferTypes; the\n     proxy route reads size/type/variant/add/return, verified 2026-09-18) so\n     each card lands on that film. Links are built in nt-oo-modal.js from the\n     `gsb` option below. The cap matches the builder's import limit \u2014 it\n     silently drops extras, so past 12 the category simply does not show. */\n  var GSB_PATH = '/apps/ninja-gang-sheet';\n  var GSB_MAX_IMAGES = 12;\n  var GSB_IMGIX_HOST = 'ninjauploads-production.imgix.net';\n  /* Bucket suffix is NOT stable \u2014 match by shape (see nt-artwork-data.js). */\n  var GSB_S3_RE = /ninja-services-production-ninjauploadss3bucket-[a-z0-9]+\\.s3\\.amazonaws\\.com/;\n  function gsbImgixKey(fileUrl) {\n    if (!fileUrl) return '';\n    try {\n      var u = new URL(String(fileUrl).replace(GSB_S3_RE, GSB_IMGIX_HOST), window.location.origin);\n      /* A handful of very old rows live on other hosts (cloudlift, raw\n         amazonaws paths) \u2014 no imgix key exists, the builder can't import\n         them either; return '' so the caller skips the row. */\n      if (u.host.toLowerCase() !== GSB_IMGIX_HOST) return '';\n      return u.pathname.replace(/^\\//, '');\n    } catch (e) { return ''; }\n  }\n  /* The `gsb` option for NTOO.open: what the builder needs to import this\n     selection, or null when it can't take it (a gang sheet in the set, more\n     than the cap, or no imgix keys) \u2014 null hides the modal's Gang sheets\n     category. `return` is path-only so the builder's Back lands here (their\n     ?add= clean deletes only `add`, so it survives as-is). */\n  function gsbOptions(items) {\n    items = (items || []).filter(Boolean);\n    if (!items.length || items.some(function (d) { return !!d.gangsheet; })) return null;\n    if (items.length > GSB_MAX_IMAGES) { labs('gsb_cap', items.length); return null; }   /* Labs: how often the 12-cap bites */\n    var payload = [];\n    items.forEach(function (d) {\n      var k = gsbImgixKey(d.file);\n      if (k) payload.push(d.fileName ? { k: k, n: d.fileName } : { k: k });\n    });\n    if (!payload.length) return null;\n    return { path: GSB_PATH, add: payload, returnTo: window.location.pathname };\n  }\n  /* Labs: a Gang sheets card in the modal navigates on its own (plain <a>);\n     count the send here. Capture phase so the count lands before unload. */\n  document.addEventListener('click', function (e) {\n    var card = e.target && e.target.closest && e.target.closest('.nt-oo-card[data-gsb-type]');\n    if (!card || !window.NTOO || !window.NTOO.isOpen || !window.NTOO.isOpen()) return;\n    var opts = window.NTOO.current && window.NTOO.current();\n    if (!opts || !opts.gsb || opts.__alv2Root !== root) return;\n    labs('gsb_send', opts.gsb.add.length);   /* Labs: designs per send */\n  }, true);\n\n  /* --------------------------------------------------------------- zoom */\n  function rowHtml(label, value) {\n    return '<div class=\"alv2-row\"><dt class=\"alv2-row__label\">' + esc(label) +\n           '</dt><dd class=\"alv2-row__value\">' + esc(value) + '</dd></div>';\n  }\n\n  /* Most recent ORDER of this artwork.\n\n     Must scan the whole feed rather than read the current record: the dedupe\n     keys on source + file, so an upload and a purchase of the same file stay\n     as two separate records on purpose (the tabs filter by source, and merging\n     them would drop the design from one tab). A design viewed under \"My\n     uploads\" therefore carries no order data of its own \u2014 its order history is\n     on the purchase-source twin. Returns null when the feed shows no purchase\n     of this file. */\n  function newestRecordOf(d, source) {\n    if (d.source === source) return d;\n    var key = window.NTArtworkData.makeUploadMatchKey(d, !!d.gangsheet);\n    var best = null;\n    for (var i = 0; i < state.designs.length; i++) {\n      var x = state.designs[i];\n      if (x.source !== source) continue;\n      if (window.NTArtworkData.makeUploadMatchKey(x, !!x.gangsheet) !== key) continue;\n      if (!best || (x.timestamp || 0) > (best.timestamp || 0)) best = x;\n    }\n    return best;\n  }\n  function lastOrderOf(d) { return newestRecordOf(d, 'purchase'); }\n  function uploadOf(d) { return newestRecordOf(d, 'upload'); }\n\n  /* The feed's `date` strings arrive pre-prefixed (\"Purchased Aug 5, 2026\",\n     \"Uploaded ...\"), which reads wrong under its own label \u2014 so format the timestamp\n     and keep the string only as a fallback, prefix stripped.\n     `formatted_date` is treated as SECONDS everywhere else in the theme (it is\n     only ever used for sorting there, so the unit was never load-bearing);\n     guard against a millisecond value rather than render a date in 1970. */\n  function fmtOrderDate(ts, fallbackStr) {\n    if (ts) {\n      var ms = ts > 1e11 ? ts : ts * 1000;\n      var dt = new Date(ms);\n      if (!isNaN(dt.getTime())) {\n        return dt.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });\n      }\n    }\n    return String(fallbackStr || '').replace(/^(purchased|uploaded|ordered)\\s+/i, '').trim();\n  }\n\n  var zoomOpener = null;\n  function openZoom(id) {\n    var d = byId(id);\n    if (!d) return;\n    /* Remember what opened it so closing can put focus back, instead of\n       dumping the customer at the top of the dialog. */\n    zoomOpener = document.activeElement;\n    state.zoom = String(id);\n    zoomName.textContent = d.studioName || (d.builderSave && d.builderSave.name) || d.fileName || '';\n    /* Full-quality render for inspection, not the grid thumb. */\n    /* lookFile = the cart/order line's URL when the customer last used this design with the\n       background removed (nt-artwork-data applyUsageLooks) \u2014 the zoom follows the tile */\n    zoomImg.src = window.NTArtworkData.zoomUrl(d.lookFile || d.file, d.gangsheet); /* canonical w=2000 (imgix audit 2026-09-11) */\n    zoomImg.alt = d.fileName || '';\n    syncZoomToggle();\n\n    /* A purchased design on the account opens straight into its order panel\n       (Justin 2026-09-29 v2) \u2014 no file facts, so nothing to measure. Uploads\n       keep File Type / Detected Size / Pixels. */\n    var ordered = IS_ACCOUNT && historyOf(d).length > 0;\n    zoomRows.innerHTML = ordered ? '' : rowHtml('File Type', window.NTArtworkData.fileExt(d.file) || '\u2014');\n    if (zoomOrders) zoomOrders.hidden = true;\n    if (ordered) renderOrderHistory(d);\n    zoomEl.hidden = false;\n    pinGridTracks(true);\n    root.setAttribute('data-alv2-zoomed', '');\n    /* Move focus into the overlay so the trap has somewhere to hold it. */\n    setTimeout(function () {\n      var list = focusablesIn(zoomEl);\n      if (list.length) { try { list[0].focus({ preventScroll: true }); } catch (e) {} }\n    }, 0);\n\n    if (!ordered) measureDesign(d).then(function (m) {\n      if (state.zoom !== String(id)) return; /* user moved on */\n      renderZoomDetails(d, m);\n    });\n  }\n\n  /* The ONE sanctioned measurement path. Post-trim by contract. */\n  function measureDesign(d) {\n    if (!window.NTMeasure) return Promise.resolve(null);\n    return window.NTMeasure.measure({\n      imgixUrl: window.NTArtworkData.imgixUrl(d.file),\n      ext: window.NTArtworkData.rawExt(d.file),\n      s3Key: window.NTArtworkData.normalizeFileKey(d.file)\n    });\n  }\n\n  /* One decimal only when it earns one. toFixed(1) forced it always, so a\n     4x6 order read \"4.0\u2033 \u00D7 6.0\u2033\" \u2014 noise on the whole numbers that most\n     ordered sizes are, while 3.9 still needs its decimal. Applies to the print\n     size row too, which had the same problem. */\n  function fmtIn(n) { return String(Math.round(n * 10) / 10) + '\u2033'; }\n\n  /* Neutral facts only. No resolution judgement is rendered anywhere in this\n     picker \u2014 no \"low res\" flag, chip, note or count (Owen 2026-08-24).\n     Do NOT reintroduce one. */\n  function renderZoomDetails(d, m) {\n    var vector = isVectorDesign(d);\n    var rows = '';\n    if (m && m.inW && m.inH) {\n      /* \u26A0 \"Detected size\" for raster AND vector \u2014 the label no longer forks.\n         It was \"Print size\" / \"Artwork size\", and with the order history\n         below it that read as a promise about output: the number is measured\n         off the file, while the sizes underneath are what was actually bought.\n         Detected says where it came from and stops the two competing. */\n      rows += rowHtml('Detected Size', fmtIn(m.inW) + ' \u00D7 ' + fmtIn(m.inH));\n      if (!vector) rows += rowHtml('Pixels', Math.round(m.pxW) + ' \u00D7 ' + Math.round(m.pxH));\n    }\n    /* Source row removed (Owen). The filter bar already says which bucket you\n       are looking at, and the order history below says whether it was ever\n       bought \u2014 the row restated both without adding anything. */\n    rows += rowHtml('File Type', window.NTArtworkData.fileExt(d.file) || '\u2014');\n\n    /* Both rows are OMITTED when no matching record exists, rather than\n       asserting \"never uploaded\" / \"never ordered\" \u2014 the feed is the only\n       evidence available and a gap in it proves nothing. Chronological:\n       uploaded, then last ordered. */\n    var up = uploadOf(d);\n    if (up) {\n      var upWhen = fmtOrderDate(up.timestamp, up.date);\n      if (upWhen) rows += rowHtml('Uploaded', upWhen);\n    }\n    zoomRows.innerHTML = rows;\n    renderOrderHistory(d);\n  }\n\n  /* Every time this artwork was ordered, and at what size (Owen).\n\n     \u26A0 Reads the purchase twin's `history`, not the record itself. The feed\n     emits one row per order, and combineDuplicates collapses them so the GRID\n     shows one card \u2014 it now keeps the collapsed siblings on the survivor\n     instead of discarding them, which is the only reason this list can exist.\n\n     Size comes from each order's own variant_title, so a design ordered at\n     three sizes lists three sizes. It is NOT the file's print size: that is\n     one number for the artwork, this is what was actually bought each time.\n\n     Orders with an unparseable title (gang sheets, \"custom\") show the date\n     alone rather than an invented dimension. */\n  /* Purchased design \u2192 assets/alv2-order-panel.js (NTAlv2Orders, Justin\n     2026-09-29 v2): the viewed order (sizes edit in place, + Add Another\n     Size), Add to Cart as <product>, Order as a Different Product, and the\n     other orders, each with View. This side supplies the data and the cart:\n     addLineToCart per size, then the repaint + toast every add uses.\n     ordering = the account's buy controls; pickers get it read-only. */\n  function historyOf(d) { var t = lastOrderOf(d); return (t && t.history) || []; }\n  function orderPanel(d) { return IS_ACCOUNT && !!d && !d.archived && !editOnly(d); }\n  function renderOrderHistory(d) {\n    if (!zoomOrders) return;\n    var list = historyOf(d);\n    if (!list.length || !window.NTAlv2Orders) { zoomOrders.hidden = true; zoomOrders.innerHTML = ''; return; }\n    window.NTAlv2Orders.render(zoomOrders, {\n      list: list, ordering: orderPanel(d), esc: esc, fmtDate: fmtOrderDate, fmtIn: fmtIn,\n      parseSize: window.NTArtworkData.parseOrderedSize,\n      productOf: function (line) { return productOfLine(line, d); },\n      addLine: function (line, qty) { return addLineToCart(d, line, qty); },\n      added: function (done, all) {\n        markUsed([d]);\n        syncCartUi();\n        var qty = 0, total = 0;\n        done.forEach(function (x) {\n          var it = x.res && x.res.items && x.res.items[0];\n          qty += x.qty;\n          /* unit price \u00D7 this add's qty \u2014 never final_line_price (Shopify merges lines) */\n          if (it && typeof it.price === 'number') total += (it.price * x.qty) / 100;\n        });\n        showCartToast({ name: d.fileName, thumb: d.thumb, qty: qty, total: total });\n        /* in the cart \u2192 back to the library; the toast is the confirmation\n           (Justin 2026-09-29). A partial add stays open to show its error. */\n        if (all) closeZoom();\n      },\n      failed: function (msg) { showToast(msg); },\n      handoff: function (line, btn) {\n        if (!navBusy(btn)) return;\n        markUsed([d]);\n        labsOrder([d], 'order_other');   /* Labs */\n        window.location.href = fileHref(productOfLine(line, d).path, d, line);\n      },\n      /* unit price (cents) of the variant addLineToCart would pick */\n      priceFor: function (line, w, h) {\n        var path = productOfLine(line, d).path;\n        return Promise.all([productVariants(path), w && h ? bandVariantFor(path, w, h) : variantIdFor(path, line.variantTitle)])\n          .then(function (r) { var v = r[0].filter(function (x) { return x.id === r[1]; })[0]; return v ? v.price : null; });\n      },\n      /* the product's own quantity breaks; only DTF + UV DTF by size count\n         every size together (Justin 2026-09-29) */\n      tiers: function (line) {\n        var path = productOfLine(line, d).path;\n        return productJson(path).then(function (p) {\n          var rules = p && tierRules(p.type);\n          return rules ? { rules: rules, cumulative: path === REORDER_DTF || path === REORDER_UV, type: p.type } : null;\n        });\n      },\n      /* \"different\" = not the viewed order's product (DTF gang films are variants, no card) */\n      others: function (line) {\n        var p = productOfLine(line, d);\n        openOrderingOptions(d, p.path === REORDER_GANG ? [] : [p.path.split('/').pop()]);\n      }\n    });\n    zoomOrders.hidden = false;\n  }\n\n  /* The primary here does the same job the selection bar's does, and has to\n     say the same thing: hand off on a picker, reorder on the account. It read\n     \"Use this Design\" on both, which on the account page named an action that\n     could not happen. */\n  function syncZoomActions() {\n    var d = byId(state.zoom);\n    if (!zoomUse) return;\n    disarmZoomDel();\n    /* Archived designs get the archive pair and nothing else \u2014 the panel has\n       to say the same thing as the archived card links and the archived bar:\n       restore it or delete it for good, never order it. */\n    var archived = !!(d && d.archived);\n    if (zoomRestore) zoomRestore.hidden = !archived;\n    if (zoomDelete)  zoomDelete.hidden  = !archived;\n    zoomUse.hidden = archived;\n    if (archived) { if (zoomUv) zoomUv.hidden = true; return; }\n    /* Save-document row: the panel's primary follows the design's lifecycle \u2014\n       Continue Editing until it has been ordered, Reorder after (locked).\n       Ordering CTAs stand down; each tool's own flow orders at real\n       resolution, and Reorder routes through the design's proper path. */\n    if (editOnly(d)) {\n      zoomUse.textContent = saveCtaLabel(d);\n      if (zoomUv) zoomUv.hidden = true;\n      return;\n    }\n    if (IS_ACCOUNT && d) {\n      zoomUse.textContent = primaryLabel([d]);\n      /* a purchased design orders from its panel's own CTAs (NTAlv2Orders) */\n      var inPanel = historyOf(d).length > 0 && !!window.NTAlv2Orders;\n      zoomUse.hidden = inPanel;\n      /* Ordering options exist for BOTH kinds \u2014 the modal itself picks the\n         right grid (shared cards vs the gang-variant cards), like live. */\n      if (zoomUv) zoomUv.hidden = inPanel;\n    } else {\n      zoomUse.textContent = 'Use this Design';\n      if (zoomUv) zoomUv.hidden = true;\n    }\n  }\n\n  function syncZoomToggle() {\n    syncZoomActions();\n    if (!ALLOW_MULTI) { zoomToggle.hidden = true; return; }\n    var zd = byId(state.zoom);\n    if (zd && zd.archived) { zoomToggle.hidden = true; return; }\n    /* a purchased design's panel orders from its own rows \u2014 no Add to selection (Justin 2026-09-29) */\n    if (IS_ACCOUNT && zd && historyOf(zd).length) { zoomToggle.hidden = true; return; }\n    /* Edit-only rows can't join selections (toggleCheck refuses) \u2014 no dead button. */\n    if (editOnly(zd)) { zoomToggle.hidden = true; return; }\n    zoomToggle.hidden = false;\n    var on = state.zoom && isChecked(state.zoom);\n    zoomToggle.textContent = on ? 'Remove from selection' : 'Add to selection';\n    zoomToggle.setAttribute('data-selected', on ? 'true' : 'false');\n  }\n  /* Hold the grid's columns while the zoom is open (Owen 2026-10-16). The\n     page drops the root's container-type for the duration (Safari fix in\n     artwork-library-v2-page.liquid), so the grid's 22cqw track minimum stops\n     measuring the root and re-resolves against the window: the rows behind\n     the dialog reflowed 4-up \u2192 2-up and the page jumped. Snapshot the\n     resolved tracks as an inline style BEFORE the attribute flips, release\n     on close so the container query owns the layout again. */\n  function pinGridTracks(on) {\n    var grids = root.querySelectorAll('.alv2-grid');\n    for (var i = 0; i < grids.length; i++) {\n      var g = grids[i];\n      if (!on) { g.style.gridTemplateColumns = ''; continue; }\n      if (g.offsetParent === null) continue;\n      var cs = getComputedStyle(g);\n      if (cs.display !== 'grid') continue;\n      g.style.gridTemplateColumns = cs.gridTemplateColumns;\n    }\n  }\n  function closeZoom() {\n    var wasOpen = !zoomEl.hidden;\n    disarmZoomDel();\n    state.zoom = null;\n    zoomEl.hidden = true;\n    root.removeAttribute('data-alv2-zoomed');\n    pinGridTracks(false);\n    zoomImg.src = '';\n    if (wasOpen && zoomOpener && root.contains(zoomOpener)) {\n      try { zoomOpener.focus({ preventScroll: true }); } catch (e) {}\n    }\n    zoomOpener = null;\n  }\n\n  /* -------------------------------------------------------- open / close */\n  /* Focus helper. The TRAP itself is the shell's job (a trap only makes sense\n     for a modal \u2014 an on-page library must not hold focus), but the zoom still\n     needs to put focus inside itself, so the query stays here. The shell reads\n     data-alv2-zoomed off the root to know when to scope its trap to the zoom. */\n  var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), ' +\n                  'select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n  function focusablesIn(scope) {\n    return Array.prototype.filter.call(scope.querySelectorAll(FOCUSABLE), function (el) {\n      /* offsetParent is null for display:none subtrees, which is exactly what\n         the [hidden] panels are. Zero-size controls are skipped too. */\n      return el.offsetParent !== null && (el.offsetWidth > 0 || el.offsetHeight > 0);\n    });\n  }\n\n  /* Nothing happens until the library is actioned (Owen 2026-08-25): no fetch and no DOM build on load \u2014\n     the first activation does both (shell activate(), __mdRenderNow() from assets/dtf-upload-tabs.js:237,\n     or visible at init). \u26A0 Don't make the fetch eager again: live's body[data-md-has-designs] gate is\n     inert for v2. __mdRenderNow is idempotent. (Full rationale: git history, 2026-08-25.) */\n  var loadStarted = false, loadedGang = false;\n  function ensureLoaded() {\n    if (loadStarted) return;\n    loadStarted = true;\n    loadDesigns();\n  }\n\n  var renderUnlocked = false;\n  function unlockRender() {\n    if (renderUnlocked) return;\n    renderUnlocked = true;\n    ensureLoaded();   /* first activation is what triggers the fetch */\n    render();\n  }\n  /* Idempotent, matching the live contract. */\n  root.__mdRenderNow = unlockRender;\n\n  /* \u2500\u2500 cross-instance sync (Justin 2026-09-10: \"whenever we make a change on\n     My Designs it updates on Recent \u2014 it's the same element\") \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     The dashboard's Recent strip and the My Designs tab are two instances of\n     THIS component in one document. After a mutation here (archive / restore /\n     delete / upload) every other instance refetches \u2014 the data layer already\n     dropped its cache. Instances that are not rendering yet just mark\n     themselves stale and refetch on activation. */\n  function broadcastChange() {\n    try { window.dispatchEvent(new CustomEvent('alv2:changed', { detail: { root: root } })); } catch (e) {}\n  }\n  /* settle a list of maybe-promises (the data layer's setArchived returns its\n     request since 2026-09-10; older cached copies return undefined) */\n  function whenSettled(list) {\n    return Promise.all((list || []).map(function (p) { return Promise.resolve(p).then(null, function () {}); }));\n  }\n  function onExternalChange() {\n    if (!document.contains(root)) return;   /* an evicted pane's instance stays quiet */\n    if (renderUnlocked) loadDesigns();       /* a not-yet-rendered instance fetches fresh on activation anyway */\n  }\n  window.addEventListener('alv2:changed', function (e) {\n    if (e.detail && e.detail.root === root) return;\n    onExternalChange();\n  });\n  /* the data layer's own event \u2014 archives/deletes made outside any library\n     instance (PDP flows, patch express) should reach the strip too */\n  window.addEventListener('nt-archive-changed', function (e) {\n    if (e.detail && e.detail.source === 'artwork-library-v2') return; /* covered by alv2:changed */\n    onExternalChange();\n  });\n\n  /* One modal shell per page, so a host can re-point it before opening: the portal's\n     \"choose a previous design\" sets data-forced-type / data-allow-multi per link (a gang\n     favorite = gang sheets, one pick). Re-read them here; gang needs the gang feed too. */\n  function syncMode() {\n    var ft = root.getAttribute('data-forced-type') || '', am = root.hasAttribute('data-allow-multi');\n    if (ft === FORCED_TYPE && am === ALLOW_MULTI) return;\n    FORCED_TYPE = ft; ALLOW_MULTI = am;\n    PICKER_SWAP = !IS_ACCOUNT && !!FORCED_TYPE && !RECENT_DAYS;\n    state.checked = [];\n    var sub = root.querySelector('.alv2-sub');\n    if (sub && /^Click a design to use it/.test(sub.textContent)) sub.textContent = am ? 'Click a design to use it, or use checkboxes to select multiple.' : 'Click a design to use it.';\n    if (loadStarted && ft === 'gangsheet' && !loadedGang) loadDesigns();\n  }\n\n  function activate() {\n    syncMode();\n    unlockRender();\n    syncSearchClear();\n    render();\n    /* Auto-focus is a desktop type-to-search convenience. On touch devices it\n       pops the software keyboard over the grid the moment the library opens\n       (portal tab or picker modal), so it is gated to fine-pointer devices. */\n    /* not on the My Designs page itself (Justin 2026-10-13) \u2014 pickers keep type-to-search */\n    if (!KIND_MODE && !window.matchMedia('(hover: none) and (pointer: coarse)').matches) {\n      setTimeout(function () { try { searchEl.focus({ preventScroll: true }); } catch (e) {} }, 0);\n    }\n  }\n  /* Shell calls this when it hides the library. */\n  function deactivate() {\n    closeZoom();\n    hideToast();\n  }\n\n  function announceCount() {\n    try {\n      window.dispatchEvent(new CustomEvent('nt-md-count', { detail: { count: libraryForType().length } }));\n    } catch (e) {}\n  }\n\n  /* \u26A0 nt-artwork-data.js is DEFERRED, and this inline script runs at parse \u2014\n     so on a full-page surface, the visible-at-init activate() fires before\n     window.NTArtworkData exists. The original call threw, ensureLoaded's\n     one-shot flag was already burned, and the page sat on \"Loading your\n     artwork\u2026\" forever with no retry and no visible error.\n\n     The harness never caught it because its data stub is a synchronous inline\n     <script> ABOVE this snippet, so NTArtworkData always existed at parse\n     there. Found on the first real-theme render (sandbox, 2026-08-31).\n\n     Poll rather than assume: cheap (50ms), stops the moment the deferred\n     script lands, and gives up into the error state after 10s instead of\n     spinning forever on a genuinely failed asset. */\n  /* a design archived/deleted elsewhere must not stay 'selected' here */\n  function pruneChecked() {\n    if (!state.checked.length) return;\n    var vis = {};\n    visibleDesigns().forEach(function (d) { vis[String(d.id)] = 1; });\n    state.checked = state.checked.filter(function (id) { return vis[String(id)]; });\n  }\n  function loadDesigns() {\n    /* Staff lookup with no customer chosen yet: there is nothing to fetch, and\n       without this the empty id would still spend three 400s per page view. */\n    if (LOOKUP && !CUSTOMER_ID) { state.designs = []; state.loaded = true; render(); return; }\n    var tries = 0;\n    (function waitForData() {\n      if (window.NTArtworkData) {\n        window.NTArtworkData.load(CUSTOMER_ID, {\n          /* Gang-sheet surfaces fetch the customer's gang UPLOADS too\n             (fetchDataNew?gangsheet=true). So do account surfaces: the base\n             feed carries only SOME gang rows (14 vs 19 on 2026-10-01), so\n             without this My Designs \u2192 Gang Sheets showed fewer sheets than the\n             gang-sheet product page's picker (Owen 2026-10-01). One extra\n             ~20-row request; combineDuplicates dedupes the overlap. */\n          gang: (loadedGang = FORCED_TYPE === 'gangsheet' || IS_ACCOUNT),\n          onCached: function (designs) {\n            state.designs = designs; state.loaded = true; pruneChecked(); render(); announceCount();\n          }\n        }).then(function (designs) {\n          state.designs = designs; state.loaded = true; pruneChecked(); render(); announceCount();\n        }).catch(function () {\n          state.loaded = true; render();\n        });\n        return;\n      }\n      if (++tries > 200) { state.loaded = true; render(); return; }\n      setTimeout(waitForData, 50);\n    })();\n  }\n\n  /* ------------------------------------------------------------- events */\n  root.addEventListener('click', function (e) {\n    var t = e.target;\n\n    if (t.closest('[data-alv2-upload-tile]')) {\n      if (!uploadBusy && uploadInput) uploadInput.click();\n      return;\n    }\n    if (t.closest('[data-alv2-zoom-close]')) { closeZoom(); return; }\n\n    /* Switching tab or type CLEARS the selection (QA 2026-09-03): the checked\n       set used to survive filter changes, so the selection bar followed the\n       user onto tabs where none of the selected tiles were even visible \u2014\n       an \"order bar\" floating over unrelated content. A selection belongs to\n       the view it was made in. */\n    var archBtn = t.closest('[data-alv2-arch]');\n    if (archBtn) {\n      if (archBtn.hasAttribute('data-empty')) return;\n      clearSelection();\n      state.arch = !state.arch;   /* a toggle on top of Single Images / Gang Sheets */\n      if (state.tab === 'studio' || state.tab === 'archive') state.tab = 'uploads';\n      resetToPageOne(); render(); return;\n    }\n    var tabBtn = t.closest('[data-alv2-tab]');\n    if (tabBtn) {\n      if (tabBtn.hasAttribute('data-empty')) return;    /* dead pill: nothing there */\n      var nextTab = tabBtn.getAttribute('data-alv2-tab');\n      if (nextTab !== state.tab) { clearSelection(); if (KIND_MODE) labs('tab_' + nextTab); }   /* Labs */\n      if (KIND_MODE && nextTab === 'studio') state.side = 'all';   /* the Design Studio tab shows every studio row */\n      /* switching Single Images \u21C4 Gang Sheets always opens the first section (Reorder-Ready Files;\n         renderTabs falls through to Uploads when there are none) \u2014 Justin 2026-10-13 */\n      if (KIND_MODE && (nextTab === 'uploads' || nextTab === 'gang') && nextTab !== state.tab) state.side = 'pr';\n      state.tab = nextTab; resetToPageOne(); render(); return;\n    }\n    var sideBtn = t.closest('[data-alv2-side]');\n    if (sideBtn) {\n      if (sideBtn.hasAttribute('data-empty')) return;   /* dead pill: nothing there */\n      var nextSide = sideBtn.getAttribute('data-alv2-side');\n      state.sidePicked = true;\n      if (KIND_MODE && state.tab === 'studio') state.tab = 'uploads';   /* leaving the Design Studio tab */\n      if (nextSide !== state.side) { clearSelection(); labs('side_' + nextSide); }   /* Labs */\n      state.side = nextSide; resetToPageOne(); render(); return;\n    }\n    var typeBtn = t.closest('[data-alv2-type]');\n    if (typeBtn) {\n      var nextType = typeBtn.getAttribute('data-alv2-type');\n      if (nextType !== state.type) clearSelection();\n      state.type = nextType; resetToPageOne(); render(); return;\n    }\n\n    var pageBtn = t.closest('[data-alv2-page]');\n    if (pageBtn && !pageBtn.disabled) {\n      var v = pageBtn.getAttribute('data-alv2-page');\n      var totalPages = pageMath(visibleDesigns().length).totalPages;\n      if (v === 'prev') state.page = Math.max(1, state.page - 1);\n      else if (v === 'next') state.page = Math.min(totalPages, state.page + 1);\n      else state.page = parseInt(v, 10) || 1;\n      render();\n      scroller.scrollTop = 0;\n      return;\n    }\n\n    var zoomBtn = t.closest('[data-alv2-zoom-open]');\n    if (zoomBtn) {\n      e.stopPropagation();\n      openZoom(zoomBtn.closest('[data-alv2-card]').getAttribute('data-id'));\n      return;\n    }\n\n    var useOneBtn = t.closest('[data-alv2-use-one]');\n    if (useOneBtn) {\n      e.stopPropagation();\n      var useOneId = useOneBtn.closest('[data-alv2-card]').getAttribute('data-id');\n      /* NON-PDP surfaces (Owen 2026-09-03): the card's Use Design acts as the\n         checkbox \u2014 it selects, the dark bar owns the actual ordering. Only a\n         picker (PDP) commits a design directly from this link. */\n      if (IS_ACCOUNT) { (e.shiftKey ? rangeCheck : toggleCheck)(useOneId); return; }\n      useOne(byId(useOneId));\n      return;\n    }\n\n    /* Archived-card footer links (the archive mirror of Use Design/Details). */\n    var restoreOneBtn = t.closest('[data-alv2-restore-one]');\n    if (restoreOneBtn) {\n      e.stopPropagation();\n      var rod = byId(restoreOneBtn.closest('[data-alv2-card]').getAttribute('data-id'));\n      if (rod) {\n        /* Restoring un-archives, so a lingering checkbox on this card would\n           flip the bar from Restore/Delete to Use/Order mid-toast. */\n        state.checked = state.checked.filter(function (id) { return String(id) !== String(rod.id); });\n        restoreDesigns([rod]);\n      }\n      return;\n    }\n    var delOneBtn = t.closest('[data-alv2-delete-one]');\n    if (delOneBtn) {\n      e.stopPropagation();\n      /* Same arm-then-confirm as the dots menu's delete \u2014 the card link is the\n         same irreversible action wearing a different control. */\n      if (cardDelBtn !== delOneBtn) {\n        disarmCardDel();\n        cardDelBtn = delOneBtn;\n        var dls = delOneBtn.querySelector('span');\n        if (dls) dls.textContent = 'Click again to confirm';\n        cardDelTimer = setTimeout(disarmCardDel, 4000);\n        return;\n      }\n      var dod = byId(delOneBtn.closest('[data-alv2-card]').getAttribute('data-id'));\n      disarmCardDel();\n      if (dod) deleteDesign(dod);\n      return;\n    }\n\n    var checkBtn = t.closest('[data-alv2-check]');\n    if (checkBtn) {\n      e.stopPropagation();\n      (e.shiftKey ? rangeCheck : toggleCheck)(checkBtn.closest('[data-alv2-card]').getAttribute('data-id'));\n      return;\n    }\n\n    /* A single click on the THUMBNAIL uses that design (Owen) \u2014 same as the\n       card's \"Use Design\" link. Scoped to the frame, not the whole card, so a\n       stray click on blank space in the footer row cannot commit a design.\n\n       The one exception is a batch already in progress: there, a thumbnail\n       click keeps batching instead of using one design and discarding the\n       rest. That follows the same two-path rule as the rest of the tile \u2014 with\n       nothing checked the card owns the primary action, and once anything is\n       checked the dark bar owns it. Starting a batch is the checkbox's job,\n       and it is always visible. */\n    var frame = t.closest('.alv2-card__frame');\n    if (frame) {\n      var frameCard = frame.closest('[data-alv2-card]');\n      var frameId = frameCard && frameCard.getAttribute('data-id');\n      if (!frameId) return;\n      /* An archived thumbnail cannot \"use\" \u2014 the tile's only actions are\n         restore/delete, so its click selects (which surfaces the bar's pair)\n         instead of committing a put-away design to a product. */\n      var frameD = byId(frameId);\n      if (frameD && frameD.archived) { if (ALLOW_MULTI) (e.shiftKey ? rangeCheck : toggleCheck)(frameId); return; }\n      /* An edit-only row cannot select or \"use\" \u2014 its frame opens the details\n         panel, whose primary is Continue Editing. */\n      if (editOnly(frameD)) { openZoom(frameId); return; }\n      /* Account surfaces select on thumbnail click too \u2014 the frame is\n         documented as \"same as the card's Use Design link\", and that link now\n         toggles the checkbox off-PDP (Owen 2026-09-03). */\n      if (IS_ACCOUNT || (ALLOW_MULTI && state.checked.length)) (e.shiftKey ? rangeCheck : toggleCheck)(frameId);\n      else useOne(byId(frameId));\n      return;\n    }\n\n    if (t.closest('[data-alv2-toast-action]')) { if (toastActionFn) toastActionFn(); return; }\n    var selMenuBtn2 = t.closest('[data-alv2-selmenu-btn]');\n    if (selMenuBtn2) {\n      if (selMenu.hidden) { selMenu.hidden = false; selMenuBtn2.setAttribute('aria-expanded', 'true'); }\n      else closeSelMenu();\n      return;\n    }\n    if (selMenu && !selMenu.hidden && !t.closest('[data-alv2-selmenu]')) closeSelMenu();\n    if (t.closest('[data-alv2-selbar-oo]')) {\n      openOrderingOptions(state.checked.map(byId).filter(Boolean));\n      return;\n    }\n    if (t.closest('[data-alv2-studio-edit]')) {\n      var sCard = t.closest('[data-alv2-card]');\n      var sd = sCard && byId(sCard.getAttribute('data-id'));\n      if (sd) {\n        if (!navBusy(t.closest('[data-alv2-studio-edit]'))) return;\n        labsSaveAction(sd);   /* Labs */\n        /* Same lifecycle routing as the panel primary (see zoom-use). */\n        if (sd.studio === 'save' && savedOrdered(sd)) { reorder([sd], 'dtf'); return; }\n        window.location.href = continueEditUrl(sd);\n      }\n      return;\n    }\n    if (t.closest('[data-alv2-selbar-restore]')) {\n      var rSel = state.checked.map(byId).filter(Boolean);\n      if (rSel.length) { restoreDesigns(rSel); state.checked = []; render(); }\n      return;\n    }\n    if (t.closest('[data-alv2-selbar-delete]')) { deleteSelected(); return; }\n    if (t.closest('[data-alv2-archive]')) {\n      closeSelMenu(); disarmSelDelete();\n      var selPicked = state.checked.map(byId).filter(Boolean);\n      if (selPicked.length && selPicked.every(function (d) { return !!d.archived; })) {\n        restoreDesigns(selPicked);\n        state.checked = [];\n        render();\n      } else {\n        archiveSelected();\n      }\n      return;\n    }\n    if (t.closest('[data-alv2-clear]')) { clearSelection(); return; }\n    if (t.closest('[data-alv2-use-many]')) {\n      /* Same button, different job per surface: hand off to the uploader on a\n         picker, start a reorder on the account. */\n      if (IS_ACCOUNT) {\n        if (!navBusy(t.closest('[data-alv2-use-many]'))) return;\n        var umPicked = state.checked.map(byId).filter(Boolean);\n        reorder(umPicked, primaryProduct(umPicked));\n      }\n      else { useChecked(); }\n      return;\n    }\n/* (Order-as-UV multi CTA removed 2026-09-03 \u2014 superseded by the\n       Other Ordering Options button; UV remains reachable per-design via the\n       ordering-options modal.) */\n    if (t.closest('[data-alv2-zoom-uv]')) {\n      /* Opens the modal \u2014 no navigation, so no busy state. The UV product is\n         one of the cards; a dedicated UV reorder button became redundant. */\n      openOrderingOptions(byId(state.zoom));\n      return;\n    }\n    if (t.closest('[data-alv2-zoom-use]')) {\n      var zd = byId(state.zoom);\n      /* Save-document row: unordered goes to its tool (Continue Editing);\n         an ORDERED studio save reorders its print file directly \u2014 the one\n         save kind whose file IS the ordered artwork. Ordered gang saves\n         land in the builder with the sheet loaded (no theme-reachable\n         print file exists for them; Add to Cart there is the reorder). */\n      if (editOnly(zd)) {\n        if (!navBusy(t.closest('[data-alv2-zoom-use]'))) return;\n        labsSaveAction(zd);   /* Labs */\n        if (zd.studio === 'save' && savedOrdered(zd)) { reorder([zd], 'dtf'); return; }\n        window.location.href = continueEditUrl(zd);\n        return;\n      }\n      if (IS_ACCOUNT) {\n        if (zd) { if (!navBusy(t.closest('[data-alv2-zoom-use]'))) return; reorder([zd], primaryProduct([zd])); }\n        return;\n      }\n      closeZoom();\n      useOne(zd);\n      return;\n    }\n    if (t.closest('[data-alv2-zoom-toggle]')) {\n      /* Owen 2026-08-24: this returns to the library rather than staying in\n         the zoom view (the handoff had it stay put). Toggling then closing\n         means the customer lands back on the grid with the box already\n         ticked and the selection bar updated. */\n      toggleCheck(state.zoom);\n      closeZoom();\n      return;\n    }\n    /* Archived pair in the details panel. Both land back on the grid \u2014 one\n       so the restored design is visibly back among the living, the other\n       because the thing the panel was showing no longer exists. */\n    if (t.closest('[data-alv2-zoom-restore]')) {\n      var zrd = byId(state.zoom);\n      closeZoom();\n      if (zrd) {\n        state.checked = state.checked.filter(function (id) { return String(id) !== String(zrd.id); });\n        restoreDesigns([zrd]);\n      }\n      return;\n    }\n    if (t.closest('[data-alv2-zoom-delete]')) {\n      if (!zoomDelArmed) {\n        zoomDelArmed = true;\n        var zds = zoomDelete.querySelector('span');\n        if (zds) zds.textContent = 'Click again to confirm';\n        zoomDelTimer = setTimeout(disarmZoomDel, 4000);\n        return;\n      }\n      var zdd = byId(state.zoom);\n      disarmZoomDel();\n      closeZoom();\n      if (zdd) deleteDesign(zdd);\n      return;\n    }\n\n    /* sort menu */\n    if (t.closest('[data-alv2-sort-btn]')) {\n      var open_ = sortMenu.hidden;\n      sortMenu.hidden = !open_;\n      sortBtn.setAttribute('aria-expanded', open_ ? 'true' : 'false');\n      return;\n    }\n    var opt = t.closest('[data-alv2-sort-opt]');\n    if (opt) {\n      state.sort = opt.getAttribute('data-alv2-sort-opt');\n      /* The menu is built once at boot, so the highlight (keyed on\n         aria-selected) must be re-synced per pick \u2014 without this, Newest\n         stayed marked whatever was chosen (QA 2026-09-03). */\n      sortMenu.querySelectorAll('[data-alv2-sort-opt]').forEach(function (o) {\n        o.setAttribute('aria-selected', o === opt ? 'true' : 'false');\n      });\n      sortLabel.textContent = opt.textContent;\n      sortMenu.hidden = true;\n      sortBtn.setAttribute('aria-expanded', 'false');\n      resetToPageOne(); render();\n      return;\n    }\n    if (!sortMenu.hidden) { sortMenu.hidden = true; sortBtn.setAttribute('aria-expanded', 'false'); }\n  });\n\n  /* Debounced search \u2014 a full filter + 12-card rebuild per keystroke is waste. */\n  /* The button's visibility is NOT debounced \u2014 it has to appear on the first\n     keystroke. Only the filtering waits, since that rebuilds the grid. */\n  function syncSearchClear() {\n    searchClear.hidden = !(searchEl.value || '').length;\n  }\n\n  searchEl.addEventListener('input', function () {\n    syncSearchClear();\n    if (searchTimer) clearTimeout(searchTimer);\n    searchTimer = setTimeout(function () {\n      state.query = searchEl.value || '';\n      resetToPageOne();\n      render();\n    }, 150);\n  });\n\n  /* Clearing is instant: cancel any pending debounce rather than letting it\n     fire afterwards and re-filter against the value we just wiped. */\n  searchClear.addEventListener('click', function () {\n    if (searchTimer) { clearTimeout(searchTimer); searchTimer = null; }\n    searchEl.value = '';\n    state.query = '';\n    syncSearchClear();\n    resetToPageOne();\n    render();\n    try { searchEl.focus({ preventScroll: true }); } catch (e) {}\n  });\n\n  /* Escape. A SHELL owns this outright when present: it needs to close the\n     zoom on the first press and itself on the second, and it cannot do that if\n     we also handle the key \u2014 listener order would have us close the zoom first\n     and the shell would then read \"no zoom\" and close too, dismissing both on\n     one press. A shell announces itself with data-alv2-shelled, so we stand\n     down; shell-less (on-page / full page) renders keep this. */\n  window.addEventListener('keydown', function (e) {\n    if (e.key !== 'Escape' || zoomEl.hidden) return;\n    if (root.hasAttribute('data-alv2-shelled')) return;\n    if (!root.offsetParent) return;\n    closeZoom();\n  });\n\n  /* On page surfaces the zoom is a capped dialog and the page stays visible\n     behind its shadow-backdrop \u2014 a click out there dismisses the dialog and,\n     captured here, never reaches the element underneath. Shelled surfaces\n     skip (the modal owns dismissal), and clicks inside any of the library's\n     own floating layers (ordering-options modal, three-dots menu, selection\n     bar, toast) are theirs, not a dismissal. */\n  document.addEventListener('click', function (e) {\n    if (zoomEl.hidden) return;\n    if (root.hasAttribute('data-alv2-shelled')) return;\n    if (!root.offsetParent) return;\n    if (e.target.closest('[data-alv2-zoom], .nt-oo, .alv2-menu, .alv2-selbar, [data-alv2-toast]')) return;\n    e.preventDefault(); e.stopPropagation();\n    closeZoom();\n  }, true);\n\n  sortMenu.innerHTML = SORTS.map(function (s) {\n    return '<li><button type=\"button\" class=\"alv2-sort__opt\" data-alv2-sort-opt=\"' + s.key + '\" ' +\n           'role=\"option\" aria-selected=\"' + (s.key === state.sort ? 'true' : 'false') + '\">' +\n           esc(s.label) + '</button></li>';\n  }).join('');\n\n  /* Per-instance API, hung on the element rather than a page-level global so\n     several libraries can coexist. The shell for this instance finds it via\n     its own root reference. */\n  root.alv2 = {\n    activate: activate,\n    deactivate: deactivate,\n    refresh: loadDesigns,\n    clearSelection: clearSelection,\n    closeZoom: closeZoom,\n    focusables: focusablesIn\n  };\n\n  /* Only if we are already on screen \u2014 a full-page surface, or a shell that\n     renders open. Inside a hidden shell or a hidden tab panel offsetParent is\n     null, so nothing loads until activate() / __mdRenderNow() \u2014 or until the\n     observer below sees us displayed. The members portal is the case that\n     needs it: loadAjaxContent() runs injected scripts while the pane is still\n     display:none behind .mp-ajax--loading, and nothing portal-side knows the\n     __mdRenderNow contract, so without this the tab sat on \"Loading your\n     artwork\u2026\" forever. Visibility-driven activation also keeps the deliberate\n     load/render split: a hidden instance still fetches nothing until shown. */\n  if (root.offsetParent !== null) activate();\n  else if ('IntersectionObserver' in window) {\n    var bootIo = new IntersectionObserver(function () {\n      if (root.offsetParent === null) return;\n      bootIo.disconnect();\n      activate();\n    });\n    bootIo.observe(root);\n  }\n})();\n"],
  "mappings": "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",
  "names": []
}
