/* Colors resolve to theme.css tokens: surfaces (bg, panel, panel2), text (ink,
   muted), brand (accent, action), status (ok, warn, err families). This block
   aliases Case Label Maker's legacy var names onto those tokens and defines the
   shared DESIGN TOKENS every page agent builds against (motion, radius, shadow,
   spacing). Fonts, the type scale, and the 12 palettes live in theme.css; the
   shadcn/Basecoat bridge is there too. The LABEL CANVAS and proof images are
   deliberately NOT themed — a label is physically white paper. */
:root {
  /* --- legacy aliases (keep resolving so un-restyled pages stay usable) --- */
  --dim: var(--muted);
  --brand: var(--accent);
  --brand-dark: color-mix(in srgb, var(--accent), black 20%);
  --err-bg: color-mix(in srgb, var(--err) 12%, var(--panel));
  --err-line: color-mix(in srgb, var(--err) 30%, var(--panel));
  --ready: var(--accent);
  --printed: var(--muted);

  /* --- design tokens (contract for Phase 2 page agents) --- *
   * Type scale ....... --fs-eyebrow 11 / --fs-xs 12.5 / --fs-sm 14 /
   *                    --fs-base 16 / --fs-lg 20 / --fs-xl 26   (theme.css)
   * Fonts ............ --font-sans (IBM Plex Sans) / --font-mono (IBM Plex Mono)
   * Radius ........... --radius 10 / --radius-sm 7 / --radius-lg 14 / -pill 999
   * Motion ........... --dur-1 120 / --dur-2 160 / --dur-3 220ms;
   *                    --ease-out, --ease-in-out, --ease-spring
   * Focus ............ --focus-ring (per-theme rgba) -> box-shadow 0 0 0 3px
   * Elevation ........ --shadow-sm / -md / -lg, all built on the theme --shadow.
   * Spacing rhythm ... 4px base; sections gap 20–24, cards pad 16–20, dense
   *                    control clusters 8–12. No vertical scroll at 1400×900. */
  --shadow-sm: 0 1px 2px var(--shadow);
  --shadow-md: 0 2px 8px var(--shadow), 0 1px 2px var(--shadow);
  --shadow-lg: 0 12px 34px var(--shadow), 0 3px 10px var(--shadow);
  --panel-shadow: var(--shadow-md);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink);
  font-size: var(--fs-base);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ---- Nav: integrated top bar, hairline separation, quiet pills ---- */
.topnav {
  display: flex; align-items: center; gap: 18px;
  background: color-mix(in srgb, var(--panel) 55%, var(--bg));
  border-bottom: 1px solid var(--line);
  padding: 0 24px; height: 62px; position: sticky; top: 0; z-index: 20;
  box-shadow: var(--shadow-sm);
}
.topnav .brand {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  color: var(--ink); font-weight: 600; font-size: 15.5px; letter-spacing: -.01em;
  padding: 6px 4px; border-radius: 8px;
}
.brand-mark { width: 25px; height: 25px; display: block; flex: 0 0 auto;
  transition: transform var(--dur-3) var(--ease-spring); }
.topnav .brand:hover .brand-mark { transform: rotate(-6deg) scale(1.05); }
.brand-word { white-space: nowrap; }
.brand-word .soft { color: var(--muted); font-weight: 500; }

.topnav nav { display: flex; gap: 3px; margin-left: auto; }
.topnav nav a {
  position: relative; display: inline-flex; align-items: center;
  text-decoration: none; color: var(--muted); font-weight: 500;
  font-size: var(--fs-sm); padding: 9px 16px; min-height: 40px; border-radius: 8px;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.topnav nav a:hover { background: var(--hover); color: var(--ink); }
.topnav nav a.on {
  color: var(--ink); background: color-mix(in srgb, var(--accent) 15%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 34%, transparent);
}

main { max-width: 1180px; margin: 0 auto; padding: 24px; }

/* ---- Headers ---- */
.page-head { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.page-head h1 { font-size: var(--fs-xl); margin: 0; letter-spacing: -.02em; font-weight: 700; }
.head-actions { margin-left: auto; display: flex; gap: 10px; align-items: center; }
h2 { font-size: var(--fs-lg); margin: 24px 0 12px; letter-spacing: -.01em; font-weight: 600; }
h3 { font-size: var(--fs-xs); margin: 22px 0 8px; color: var(--dim); text-transform: uppercase; letter-spacing: .8px; font-weight: 600; }

/* ---- Flash messages ---- */
.flashes { margin-bottom: 18px; display: grid; gap: 8px; }
.flash { padding: 12px 16px; border-radius: 8px; font-weight: 600; border: 1px solid transparent; }
.flash-ok { background: var(--ok-bg); color: var(--ok-ink); border-color: var(--ok-line); }
.flash-warn { background: var(--warn-bg); color: var(--warn-ink); border-color: var(--warn-line); }
.flash-error { background: var(--err-bg); color: var(--err); border-color: var(--err-line); }

/* ---- Buttons ---- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-weight: 600; font-size: var(--fs-sm); cursor: pointer;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  color: var(--ink); padding: 10px 18px; text-decoration: none; min-height: 44px;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.btn:hover { background: var(--hover); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
.btn-build, .btn-print {
  background: var(--cta); border-color: transparent; color: var(--cta-ink);
  box-shadow: var(--shadow-sm);
}
.btn-build:hover, .btn-print:hover {
  background: color-mix(in srgb, var(--cta) 88%, var(--ink));
  border-color: transparent; box-shadow: var(--shadow-md);
}
.btn-ghost { background: var(--panel); color: var(--ink); }
.btn:disabled { opacity: .55; cursor: default; transform: none; box-shadow: none; }

/* ---- Search ---- */
.search { display: flex; gap: 8px; margin-left: auto; }
.search input {
  min-width: 320px; padding: 10px 14px; font: inherit; min-height: 44px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
}

/* ---- Tables ---- */
table { width: 100%; border-collapse: collapse; background: var(--panel);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--panel-shadow); }
thead th {
  text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--dim); padding: 12px 14px; border-bottom: 1px solid var(--line); background: var(--panel2);
}
tbody td { padding: 14px; border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
.queue tr.row-printed { background: var(--panel2); color: var(--dim); }
.row-highlight { animation: flash-row 2.4s ease-out; }
@keyframes flash-row { 0% { background: var(--active-bg); } 100% { background: transparent; } }

.mono { font-family: var(--font-mono); font-size: var(--fs-sm); letter-spacing: -.01em; }
.dim { color: var(--dim); }
.product-cell { display: flex; flex-direction: column; gap: 2px; }
.product-cell .flavor { font-weight: 700; font-size: 16px; }
.pack { color: var(--dim); font-size: 13px; }
.actions-col { width: 230px; }
.actions { display: flex; gap: 8px; align-items: center; }
.print-form { display: flex; gap: 6px; align-items: center; }
.print-form input { width: 60px; padding: 9px; font: inherit; text-align: center;
  border: 1px solid var(--line); border-radius: 8px; min-height: 44px; }

/* ---- Badges / status ---- */
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.badge-ok { background: var(--ok-bg); color: var(--ok-ink); }
.badge-warn { background: var(--warn-bg); color: var(--warn-ink); }
/* Standing instruction to the floor, not a state: distributor cases take two
   labels on adjacent sides, and the queue is where that gets read. */
.badge-info { background: color-mix(in srgb, var(--accent) 12%, var(--panel)); color: var(--accent); font-weight: 600; }
.status { font-weight: 700; text-transform: capitalize; }
.status-ready { color: var(--ready); }
.status-printed { color: var(--printed); }

.empty { color: var(--dim); font-size: 17px; padding: 30px 0; }

/* ======================================================================= *
 *  RUN page — the picker table + the build modal.                          *
 *  The card "sample wall" was retired 2026-07-20: Run and Setup now share   *
 *  one .ptable component (defined in the SETUP LIST section below). Run is   *
 *  the picker — the whole row opens a modal carrying the three run inputs.   *
 *  JS-load-bearing hooks preserved: #card-filter #no-match .build-form       *
 *  #dup-warning #confirm .run-input .field-hint .inline-warn, plus do_run's  *
 *  field names (product / lot / exp / po / confirm).                         *
 * ======================================================================= */

/* Shared global build CTA size (other pages inherit .btn-build). */
.btn-build { font-size: 17px; padding: 14px 20px; }

/* ---- Page shell: locked to the viewport so only the table scrolls ---- */
main:has(.run-page) { max-width: 1400px; padding: 18px 24px; }
@media (min-width: 921px) and (min-height: 640px) {
  main:has(.run-page) {
    height: calc(100vh - 62px); display: flex; flex-direction: column; overflow: hidden;
  }
}
.run-page { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 18px; }

/* ---- Header: title + subtitle left, live filter right ---- */
.run-head { display: flex; align-items: flex-end; gap: 20px; flex: 0 0 auto; flex-wrap: wrap; }
.run-head-txt { min-width: 0; }
.run-head h1 { font-size: var(--fs-xl); margin: 0; letter-spacing: -.02em; font-weight: 700; }
.run-head-sub { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--muted); }

/* ---- Filter (kept from the retired wall) ---- */
.card-filter-wrap { position: relative; margin-left: auto; display: flex;
  align-items: center; flex: 0 1 340px; }
.card-filter-icon { position: absolute; left: 14px; width: 17px; height: 17px;
  color: var(--muted); pointer-events: none; transition: color var(--dur-2) var(--ease-out); }
.card-filter-wrap:focus-within .card-filter-icon { color: var(--accent); }
.card-filter { font: inherit; font-size: var(--fs-sm); width: 100%; padding: 11px 15px 11px 40px;
  min-height: 46px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--input-bg); color: var(--ink); }
.card-filter::placeholder { color: var(--muted); opacity: .7; }
.card-filter:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }
.card-filter::-webkit-search-cancel-button { -webkit-appearance: none; }

/* ---- Run rows are the click target: whole row opens the build modal ---- */
.ptable-run tbody tr { cursor: pointer; }
.ptable-run tbody tr:focus-visible { outline: none;
  box-shadow: inset 0 0 0 2px var(--accent); background: var(--hover); }
.ptable-run tbody tr:hover .go-chevron { color: var(--accent); transform: translateX(2px); }
.col-go { width: 34px; text-align: right; }
.go-chevron { color: var(--muted); vertical-align: middle;
  transition: color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }

/* ---- No-match message (filter emptied the table) ---- */
.no-match { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; padding: 48px 16px; text-align: center; color: var(--muted); }
.no-match[hidden] { display: none; }
.no-match svg { width: 36px; height: 36px; opacity: .5; }
.no-match p { margin: 0; font-weight: 600; font-size: var(--fs-sm); color: var(--ink); }
.no-match span { font-size: var(--fs-xs); }

/* ======================= Build modal (native <dialog>) ======================= */
/* The dialog fills the viewport and centers its card, so the empty gutter around
   the card is a real click target (target === dialog -> close), reliable at any
   width. The ::backdrop still supplies the dim + blur behind it. */
.rmodal { border: 0; margin: 0; padding: 0; background: transparent; color: var(--ink); }
.rmodal[open] {
  display: grid; place-items: center; inset: 0;
  width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; padding: 24px;
}
.rmodal::backdrop {
  background: color-mix(in srgb, #05070a 74%, transparent);
  backdrop-filter: blur(6px) saturate(1.05); -webkit-backdrop-filter: blur(6px) saturate(1.05);
}
.rmodal[open] .rmodal-inner { animation: rmodal-in var(--dur-3) var(--ease-out); }
@keyframes rmodal-in {
  from { opacity: 0; transform: translateY(10px) scale(.99); }
  to   { opacity: 1; transform: none; }
}
.rmodal-inner {
  position: relative; display: grid; grid-template-columns: 320px 1fr;
  width: 100%; max-width: 940px; max-height: calc(100dvh - 48px);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); overflow: hidden;
}

/* Left: the label matted on a dark workbench (white paper is correct + expected). */
.rmodal-preview {
  display: flex; align-items: center; justify-content: center; padding: 28px;
  border-right: 1px solid var(--line);
  background: radial-gradient(120% 82% at 50% 0%,
              color-mix(in srgb, var(--accent) 12%, #14171c), #0c0e11);
}
.rmodal-label {
  max-width: 100%; max-height: 60vh; width: auto; background: #fff; padding: 7px;
  border-radius: 8px; border: 1px solid rgba(0,0,0,.14); box-shadow: 0 18px 46px rgba(0,0,0,.52);
}

/* Right: the build pane. */
.rmodal-body { position: relative; padding: 26px 28px 28px; overflow-y: auto;
  display: flex; flex-direction: column;
  scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.rmodal-close {
  position: absolute; top: 16px; right: 16px; width: 38px; height: 38px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 10px;
  background: var(--panel2); border: 1px solid var(--line); color: var(--muted); cursor: pointer;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
              transform var(--dur-3) var(--ease-spring);
}
.rmodal-close svg { width: 18px; height: 18px; }
.rmodal-close:hover { background: var(--hover); color: var(--ink); transform: rotate(90deg); }
.rmodal-close:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }

.rmodal-head {
  display: flex; flex-direction: column; gap: 6px; margin-bottom: 20px;
  padding: 0 44px 18px 0; border-bottom: 1px solid var(--line);
}
.rmodal-eyebrow { font-size: var(--fs-eyebrow); font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--label); }
.rmodal-flavor { font-size: var(--fs-lg); font-weight: 700; letter-spacing: -.02em;
  margin: 0; line-height: 1.14; color: var(--ink); }
.rmodal-head .approval-flag { margin-top: 3px; }

/* ---- The three run inputs (shared: also the modal's form) ---- */
.build-form { display: flex; flex-direction: column; gap: 16px; }
.fld { display: flex; flex-direction: column; gap: 7px; }
.fld label { font-weight: 600; font-size: var(--fs-xs); color: var(--label);
  display: flex; align-items: baseline; gap: 8px; }
.fld-note { font-weight: 500; font-size: var(--fs-eyebrow); color: var(--muted);
  text-transform: none; letter-spacing: 0; }
.fld-note[hidden] { display: none; }
.run-input { font: inherit; font-size: var(--fs-base); width: 100%; padding: 13px 15px; min-height: 50px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--input-bg); color: var(--ink); }
.run-input.mono { font-family: var(--font-mono); letter-spacing: .02em; }
.run-input::placeholder { color: var(--muted); opacity: .6; font-style: italic; }

.field-hint { color: var(--muted); font-size: var(--fs-xs); font-weight: 500; min-height: 17px;
  display: flex; align-items: center; }
.field-hint.on { color: var(--accent); font-weight: 600; }
.field-hint[hidden] { display: none; }

.inline-warn { display: flex; gap: 11px; align-items: flex-start;
  background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn-line);
  padding: 12px 14px; border-radius: 10px; font-size: var(--fs-xs); }
.inline-warn[hidden] { display: none; }
.inline-warn .warn-icon { width: 19px; height: 19px; flex: 0 0 auto; margin-top: 1px; }
.inline-warn .warn-body { display: flex; flex-direction: column; gap: 8px; }
.inline-warn strong { font-weight: 700; }
.inline-warn .confirm { display: flex; gap: 9px; align-items: center; font-weight: 600;
  cursor: pointer; min-height: 32px; }
.inline-warn .confirm input { width: 18px; height: 18px; accent-color: var(--warn); cursor: pointer; }

.build-form .btn-build { width: 100%; margin-top: 2px; min-height: 54px; padding: 15px;
  font-size: var(--fs-base); font-weight: 700; letter-spacing: .01em;
  background: var(--cta); color: var(--cta-ink); border-color: transparent;
  box-shadow: var(--shadow-md); }
.build-form .btn-build:hover { background: color-mix(in srgb, var(--cta) 90%, var(--ink));
  border-color: transparent; box-shadow: var(--shadow-lg); }
.build-form .btn-build:active { transform: translateY(1px); }
.build-form .btn-build:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring), var(--shadow-md); }

/* ---- Approval flag (modal head; also reused wherever a print-state is shown) ---- */
.approval-flag { display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--warn-ink); }
.approval-flag .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--warn);
  box-shadow: 0 0 5px color-mix(in srgb, var(--warn) 55%, transparent); }
.approval-flag.ok { color: var(--ok-ink); }
.approval-flag.ok .dot { background: var(--ok-ink); box-shadow: none; }

/* ---- Recent builds ledger (modal) ---- */
.rmodal-recent { margin-top: 22px; }
.rmodal-recent[hidden] { display: none; }
.recent-head { font-size: var(--fs-eyebrow); font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted); margin: 0 0 9px; }
.recent { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 7px; }
.recent li { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 9px 12px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; }
.recent .lot { font-weight: 600; font-size: var(--fs-xs); color: var(--ink); }
.recent .exp, .recent .po, .recent .when { font-size: var(--fs-xs); color: var(--muted); }
.recent .status { margin-left: auto; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; padding: 3px 10px; border-radius: 999px; }
.recent .status-ready { color: var(--ok-ink); background: var(--ok-bg); }
.recent .status-printed { color: var(--muted); background: var(--panel2); }

/* Narrow / short: stack the modal so the label rides above the form. */
@media (max-width: 720px), (max-height: 560px) {
  .rmodal-inner { grid-template-columns: 1fr; }
  .rmodal-preview { padding: 18px; }
  .rmodal-label { max-height: 26vh; }
}

/* ---- Setup ---- */
.settings-box { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 20px; box-shadow: var(--panel-shadow); margin-bottom: 12px; }
.inline-form { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.inline-form label { display: grid; gap: 6px; font-weight: 600; flex: 1; min-width: 260px; }
.inline-form input { padding: 11px 14px; font: inherit; border: 1px solid var(--line); border-radius: 8px; min-height: 44px; }

.req { color: var(--err); }
.hint { color: var(--dim); font-size: 13px; font-weight: 500; }
.bc-status { font-size: 13px; font-weight: 700; min-height: 16px; }
.bc-status.ok { color: var(--ok-ink); }
.bc-status.bad { color: var(--err); }

/* ======================================================================= *
 *  WYSIWYG product editor (setup/new, setup/edit)                         *
 *  One screen, no scroll: dense top bar + editable label canvas beside    *
 *  the live engine proof. The canvas mirrors where each value prints.     *
 * ======================================================================= */

/* Widen and tighten the page shell just for the editor. */
main:has(.wys-page) { max-width: 1360px; padding: 14px 24px 18px; }

.wys-page { display: flex; flex-direction: column; gap: 10px; }

/* ---- Top bar: admin fields (never on the label) ---- */
.wys-bar {
  display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 14px; box-shadow: var(--panel-shadow);
}
.wys-back { min-height: 38px; padding: 6px 12px; }
.tb-field { display: grid; gap: 3px; font-weight: 600; }
.tb-field.tb-grow { flex: 1; min-width: 200px; }
.tb-lab { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--dim); }
.tb-field input, .tb-field select {
  padding: 7px 10px; font: inherit; font-size: 14px; min-height: 36px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--panel);
}
.tb-field input[readonly] { background: var(--bg); color: var(--dim); }
.tb-fixed { font-family: var(--font-mono); font-size: 13px;
  padding: 8px 10px; background: var(--bg); border-radius: 7px; color: var(--dim); min-height: 36px; }
.tb-check { display: flex; align-items: center; gap: 7px; font-weight: 600; font-size: 14px;
  padding-bottom: 7px; white-space: nowrap; }
.tb-check input { width: 18px; height: 18px; }
.wys-save { min-height: 38px; padding: 8px 22px; margin-left: auto; }

.wys-note { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid #f0dfa0;
  padding: 8px 14px; border-radius: 8px; font-weight: 600; font-size: 14px; }

.wys-fallback { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 14px; box-shadow: var(--panel-shadow); }
.wys-fallback-lab { font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--dim); align-self: center; }

/* ---- Stage: canvas + proof + rail. Wraps rather than clipping if a narrower
       viewport cannot seat all three. ---- */
.wys-stage { display: flex; gap: 28px; align-items: flex-start; justify-content: center;
  flex-wrap: wrap; }
.wys-side { display: flex; flex-direction: column; gap: 6px; }
.wys-cap { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  color: var(--dim); display: flex; align-items: center; gap: 10px; min-height: 18px; }
.wys-hint, .wys-spin { text-transform: none; letter-spacing: 0; font-weight: 500; color: var(--dim); }
.wys-spin { color: var(--brand); }
.wys-err { background: var(--err-bg); color: var(--err); border: 1px solid #f5c2bd;
  padding: 7px 12px; border-radius: 7px; font-weight: 600; font-size: 13px; max-width: 100%;
  overflow-wrap: anywhere; }

/* ---- The editable label canvas ---- */
.cv-canvas {
  position: relative; background: #fff; color: #000; overflow: hidden;
  border: 1px solid var(--line); border-radius: 4px;
  box-shadow: 0 2px 10px rgba(20, 24, 29, .12);
  font-family: Arial, Helvetica, "Liberation Sans", sans-serif; line-height: 1;
}
.cv-bar { position: absolute; background: #000; }
.cv-frame { position: absolute; border: 1px solid #999; border-radius: 2px; }
.cv-zone {
  position: absolute; border: 1px solid #b9c0c8; border-radius: 2px;
  background: repeating-linear-gradient(90deg, #cfd5db 0, #cfd5db 2px, #fff 2px, #fff 5px);
  display: flex; align-items: center; justify-content: center;
}
.cv-zone span { font-size: 8px; font-weight: 700; letter-spacing: .5px; color: #5a636d;
  background: rgba(255,255,255,.82); padding: 0 3px; text-transform: uppercase; }
.cv-seal {
  position: absolute; border: 1.5px solid #1a7f37; border-radius: 50%; color: #1a7f37;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: 7px; font-weight: 800; text-align: center; line-height: 1.15; letter-spacing: .3px;
}
.cv-static { position: absolute; color: #000; overflow: hidden; white-space: nowrap; }
.cv-dim { color: #8a929c; font-weight: 600 !important; }
.cv-lotexp { color: #aab1ba; font-weight: 700; }

/* Editable value boxes: transparent inputs positioned where text prints. */
.cv-field { position: absolute; display: flex; align-items: baseline; gap: 0;
  border-radius: 3px; box-shadow: inset 0 0 0 1px transparent; cursor: text;
  line-height: 1.15; }
.cv-field[data-align="right"]  { justify-content: flex-end; }
.cv-field[data-align="center"] { justify-content: center; }
.cv-field[data-align="left"]   { justify-content: flex-start; }
/* A slot whose height the layout allocated exactly (universal maps). An <input>
   will not go below its font's natural line box on its own, which is ~15% taller
   than a line-height:1 label line and collides with the row beneath — so pin the
   box to the slot and centre the text in it. */
.cv-fixed { align-items: center; }
.cv-fixed .cv-input, .cv-fixed .cv-affix { height: 100%; }
/* An empty field must be findable without hunting: keep a faint slot visible
   until it has content. Hover/focus variants below outrank it. */
.cv-field:has(.cv-input:placeholder-shown) {
  box-shadow: inset 0 0 0 1px #c6cfd9; background: rgba(31,111,235,.04);
  min-width: 40px; }
.cv-field:hover, .cv-field:has(.cv-input:placeholder-shown):hover {
  box-shadow: inset 0 0 0 1px #9db6e6; background: rgba(31,111,235,.05); }
.cv-field:focus-within, .cv-field:has(.cv-input:placeholder-shown):focus-within {
  box-shadow: inset 0 0 0 1.5px var(--brand); background: rgba(31,111,235,.08); }
.cv-affix { color: #000; white-space: pre; flex: 0 0 auto; }
.cv-mirror { color: #444; }
.cv-input {
  font: inherit; color: #000; background: transparent; border: 0; padding: 0; margin: 0;
  line-height: inherit; min-width: 4px; text-align: inherit; outline: none;
}
.cv-input::placeholder { color: #b7bec7; font-style: italic; }
.cv-input.cv-mono { font-family: "Courier New", ui-monospace, monospace; letter-spacing: .5px; }
.cv-input.cv-upper { text-transform: uppercase; }
.cv-bc { position: absolute; right: -14px; bottom: 0; min-height: 0; font-size: 12px; }

/* Clear a filled optional back to a ghost (appears on hover, like the x on chips). */
.cv-clear { position: absolute; right: -13px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; color: var(--dim); cursor: pointer; font-size: 12px;
  line-height: 1; padding: 2px; opacity: 0; transition: opacity .1s; }
.cv-field:hover .cv-clear, .cv-field:focus-within .cv-clear { opacity: 1; }
.cv-clear:hover { color: var(--err); }

/* ---- Ghost slots: empty optionals, named and in position ---- */
.cv-ghosts { position: absolute; display: flex; flex-wrap: wrap; align-items: center;
  gap: 2px 3px; overflow: visible; z-index: 2; }
.cv-chip { display: inline-flex; align-items: center; line-height: 1; }
.cv-chip-btn { font: inherit; font-size: inherit; line-height: 1; cursor: pointer;
  color: #8d98a4; background: rgba(255,255,255,.6); border: 1px dashed #c2cad3;
  border-radius: 3px; padding: 1px 3px; white-space: nowrap; text-transform: uppercase;
  letter-spacing: .2px; }
.cv-chip-btn:hover { color: var(--brand); border-color: var(--brand);
  border-style: solid; background: rgba(31,111,235,.06); }
.cv-chip-on { box-shadow: inset 0 0 0 1.5px var(--brand); border-radius: 3px;
  background: rgba(31,111,235,.08); }
.cv-chip-input { font-size: inherit; }

/* ---- Auto zones: generated at build, never editable ---- */
.cv-auto { position: absolute; border: 1px dashed #9aa3ad; border-radius: 2px;
  display: flex; align-items: center; justify-content: center; cursor: not-allowed;
  background: repeating-linear-gradient(45deg, #fff 0 4px, #e9ecef 4px 8px); }
.cv-auto span { font-size: 7px; font-weight: 800; letter-spacing: .6px; color: #6a7482;
  background: rgba(255,255,255,.86); padding: 1px 4px; text-transform: uppercase;
  text-align: center; }

/* ---- Supplied client artwork in its zone ---- */
.cv-auxzone { position: absolute; display: flex; align-items: center;
  justify-content: center; background: #fff; overflow: hidden; }
.cv-auxzone img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* ---- Rail: controls beside the stage, because width is what this page has ---- */
.wys-rail { display: flex; flex-direction: column; gap: 10px; width: 260px;
  flex: 0 0 260px; align-self: stretch; }
.wys-rail .tb-field { width: 100%; }
.wys-rail .tb-field input, .wys-rail .tb-field select { width: 100%; }
.rail-lab { font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--dim); }

.cv-controls { display: flex; align-items: flex-start; flex-direction: column;
  gap: 8px; padding: 10px 12px; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--panel-shadow); font-size: 12px; }
.cv-toggle { display: inline-flex; align-items: center; gap: 5px; font-weight: 600;
  white-space: nowrap; cursor: pointer; }
.cv-toggle input { width: 15px; height: 15px; }
.cv-disabled { opacity: .45; cursor: not-allowed; }
.cv-ghostbtn { font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  color: var(--dim); background: none; border: 1px dashed var(--line);
  border-radius: 6px; padding: 3px 9px; white-space: nowrap; }
.cv-ghostbtn:hover:not(:disabled) { color: var(--brand); border-color: var(--brand);
  background: rgba(31,111,235,.05); }
.cv-auxctl { display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  width: 100%; }
.cv-auxchip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 4px 3px 8px;
  background: var(--ok-bg); border: 1px solid #b7e0c2; border-radius: 6px; font-size: 12px;
  max-width: 100%; flex-wrap: wrap; }
.cv-auxchip code { font-family: var(--font-mono); font-size: 11px;
  color: var(--ok-ink); overflow-wrap: anywhere; }
.cv-auxdel { border: 0; background: none; color: var(--dim); cursor: pointer;
  font-size: 14px; line-height: 1; padding: 0 2px; }
.cv-auxdel:hover { color: var(--err); }
.cv-auxerr { color: var(--err); font-weight: 600; overflow-wrap: anywhere; }
.cv-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cv-chips:empty { display: none; }
.cv-chips-lab { font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--dim); }
.cv-suggest { font: inherit; font-size: 12px; cursor: pointer; color: var(--brand);
  background: rgba(31,111,235,.06); border: 1px solid #9db6e6; border-radius: 6px;
  padding: 3px 9px; white-space: nowrap; }
.cv-suggest:hover { background: var(--brand); color: #fff; border-color: var(--brand); }
.cv-suggest b { font-weight: 800; }

/* ---- Live proof panel (sized to match the canvas) ---- */
.cv-preview { position: relative; background: #fff; border: 1px solid var(--line);
  border-radius: 4px; box-shadow: 0 2px 10px rgba(20,24,29,.12); overflow: hidden; }
.cv-preview img { display: block; width: 100%; height: 100%; object-fit: contain; }
.cv-preview img[hidden] { display: none; }
.cv-preview-empty { position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; text-align: center; padding: 20px; color: var(--dim); font-size: 14px; }
.cv-preview-empty[hidden] { display: none; }

/* ---- PIN ---- */
.pin-card { max-width: 420px; margin: 40px auto; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 28px; box-shadow: var(--panel-shadow); }
.pin-card form { display: grid; gap: 14px; margin-top: 16px; }
.pin-card label { display: grid; gap: 6px; font-weight: 600; }
.pin-card input { padding: 12px 14px; font: inherit; border: 1px solid var(--line); border-radius: 8px; min-height: 48px; }

@media (max-width: 900px) {
  .search input { min-width: 180px; }
  .wys-stage { flex-wrap: wrap; }
}
/* Below the target range both locked pages release and flow naturally
   (the table sizes to content) rather than clipping. */
@media (max-width: 920px), (max-height: 639px) {
  main:has(.run-page), main:has(.setup-products) { height: auto; overflow: visible; }
}

/* ---- Theme picker (nav): native select, shadcn-clean, themeable chevron ---- */
.theme-picker { position: relative; display: inline-flex; align-items: center;
  color: var(--muted); transition: color var(--dur-2) var(--ease-out); }
.theme-picker:hover { color: var(--ink); }
.theme-picker::after {
  content: ""; position: absolute; right: 11px; top: 50%; width: 12px; height: 12px;
  transform: translateY(-50%); pointer-events: none; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.theme-sel {
  font: inherit; font-size: var(--fs-xs); font-weight: 500; color: inherit;
  background: var(--input-bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 32px 8px 12px; height: 40px; max-width: 176px; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  transition: color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out);
}
.theme-sel:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.theme-sel:focus-visible { outline: none; color: var(--ink); border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus-ring); }
/* Native option list follows the OS, not the page; keep it legible on dark. */
.theme-sel option { background: var(--panel); color: var(--ink); }

/* ---- Label preview lightbox: the sample, matted on white, on a blurred
       workbench. Filter / thumb / card styles live in the RUN VIEW block. ---- */
.lightbox { position: fixed; inset: 0; z-index: 100; display: flex;
  align-items: center; justify-content: center; padding: 40px;
  background: color-mix(in srgb, #05070a 78%, transparent);
  backdrop-filter: blur(7px) saturate(1.1); -webkit-backdrop-filter: blur(7px) saturate(1.1); }
.lightbox[hidden] { display: none; }
.lightbox figure { position: relative; margin: 0; display: flex; flex-direction: column;
  align-items: center; gap: 14px; cursor: default; max-width: 90vw; }
.lightbox img { max-height: 82vh; max-width: 88vw; background: #fff; padding: 6px;
  border-radius: 8px; box-shadow: 0 24px 70px rgba(0, 0, 0, .6); }
.lightbox figcaption { color: #f4f2ec; font-weight: 600; font-size: 14px; letter-spacing: -.005em;
  background: rgba(0, 0, 0, .42); border: 1px solid rgba(255, 255, 255, .12);
  backdrop-filter: blur(4px); padding: 7px 16px; border-radius: 999px; }
.lightbox-close { position: absolute; top: 20px; right: 24px; width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center; color: #fff; cursor: pointer;
  background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .16); border-radius: 50%;
  transition: background var(--dur-2) var(--ease-out), transform var(--dur-3) var(--ease-spring); }
.lightbox-close svg { width: 20px; height: 20px; }
.lightbox-close:hover { background: rgba(255, 255, 255, .18); transform: rotate(90deg); }

/* ---- Propose GTIN from UPC ---- */
.propose-row { display: grid; gap: 6px; margin: 6px 0 2px; }
.propose-btn { min-height: 34px; padding: 5px 12px; font-size: 13px; }
.propose-chips { display: grid; gap: 5px; }
.propose-chip { font: inherit; font-size: 13px; text-align: left; cursor: pointer;
  font-family: var(--font-mono);
  background: var(--panel); color: var(--ink); border: 1px dashed var(--line);
  border-radius: 6px; padding: 6px 9px; }
.propose-chip b { color: var(--accent); }
.propose-chip span { color: var(--dim); font-family: inherit; float: right; }
.propose-chip:hover { border-color: var(--accent); border-style: solid;
  background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.propose-note { font-size: 12.5px; font-weight: 600; color: var(--warn-ink);
  background: var(--warn-bg); border: 1px solid var(--warn-line);
  border-radius: 6px; padding: 7px 10px; }

/* Autofill affordance on proposal chips (the whole row is the click target). */
.propose-chip { display: flex; align-items: center; gap: 8px; }
.propose-chip span { float: none; margin-left: auto; }
.propose-fill { font-style: normal; font-family: -apple-system, BlinkMacSystemFont,
  "Segoe UI", sans-serif; font-size: 11.5px; font-weight: 700; color: var(--accent-ink);
  background: var(--accent); border-radius: 5px; padding: 2px 7px; }

/* A long engine error must wrap inside the proof column, not widen it: width 0
   takes it out of the flex item's intrinsic sizing, min-width fills whatever
   width the preview actually established. */
.wys-err { width: 0; min-width: 100%; overflow-wrap: anywhere; }


/* ======================================================================= *
 *  Shared focus ring — glows slightly, consistent across form controls.
 *  Canvas inputs (.cv-input) are excluded: they get their ring from the
 *  .cv-field:focus-within treatment so the white label stays clean.
 * ======================================================================= */
input:not(.cv-input):focus-visible,
select:not(.theme-sel):focus-visible,
textarea:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
input:not(.cv-input), select, textarea, .search input, .card-filter {
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}

/* ======================================================================= *
 *  Toasts — Basecoat toaster (fixed bottom-right, slide-up, auto-dismiss)
 *  gives structure + motion + JS; the box + category accents are ours.
 *  Flashes render server-side into #toaster on load; ok/warn auto-dismiss,
 *  errors are sticky (data-duration="-1" in base.html).
 * ======================================================================= */
.toaster .toast { --toast-accent: var(--accent); }
.toaster .toast[data-category="success"] { --toast-accent: var(--ok-ink); }
.toaster .toast[data-category="warning"] { --toast-accent: var(--warn); }
.toaster .toast[data-category="error"]   { --toast-accent: var(--err); }
.toaster .toast .toast-content {
  background: var(--popover); color: var(--popover-foreground);
  border: 1px solid var(--line); border-left: 3px solid var(--toast-accent);
  border-radius: var(--radius); padding: 12px 14px; gap: 11px;
  box-shadow: var(--shadow-lg);
}
.toaster .toast .toast-content > svg { color: var(--toast-accent); margin-top: 1px; flex: 0 0 auto; }
.toaster .toast .toast-content section { flex: 1 1 auto; min-width: 0; }
.toast-close {
  flex: 0 0 auto; margin-left: 4px; align-self: flex-start; display: inline-flex;
  align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: 6px; background: none; color: var(--muted); cursor: pointer;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.toast-close:hover { background: var(--hover); color: var(--ink); }
.toaster .toast .toast-content section h2 {
  font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: 600;
  color: var(--ink); letter-spacing: -.005em; margin: 0; }
.toaster .toast .toast-content section p {
  font-family: var(--font-sans); font-size: var(--fs-sm); color: var(--popover-foreground);
  font-weight: 500; margin: 0; line-height: 1.4; }
.toaster .toast .toast-content section h2 + p { color: var(--muted); font-weight: 400; margin-top: 2px; }

/* ---- Motion is a garnish, never a blocker: honor reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .card:hover, .topnav .brand:hover .brand-mark { transform: none; }
}

/* ======================================================================= *
 *  PAGE: PRINT QUEUE  (Phase 2 / Agent B)                                  *
 *  The floor's print manifest. Each build is a "docket": a shipping-tag    *
 *  row echoing the wordmark: a status edge-stripe (the go/no-go signal),   *
 *  a flavor+brand+pack lockup, a joined Plex-Mono code strip (lot/exp/po), *
 *  and a tablet-sized action cluster. Tuned to hold at 1024×768-landscape. *
 *  New classes throughout so the shared table/.badge/.status rules that    *
 *  setup + run still use are left untouched.                               *
 * ======================================================================= */

/* ---- Head: title + at-a-glance ready count + icon search ---- */
.queue-title { display: flex; align-items: center; gap: 13px; }
.queue-count {
  font-family: var(--font-mono); font-size: 12.5px; font-weight: 600;
  color: var(--ok-ink); background: var(--ok-bg);
  border: 1px solid var(--ok-line); padding: 3px 11px; border-radius: var(--radius-pill);
  display: inline-flex; align-items: baseline; gap: 5px; white-space: nowrap;
}
.queue-count-tot { color: var(--muted); font-weight: 500; }
.queue-count.is-zero { color: var(--muted); background: var(--panel2); border-color: var(--line); }

.queue-search { gap: 8px; }
.search-wrap { position: relative; display: inline-flex; align-items: center; }
.search-icon { position: absolute; left: 13px; width: 16px; height: 16px;
  color: var(--muted); pointer-events: none; }
.queue-search input { padding-left: 38px; }

/* ---- Designed empty state ---- */
.queue-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 5px;
  padding: 60px 24px 64px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.queue-empty-mark {
  width: 70px; height: 70px; display: grid; place-items: center; margin-bottom: 10px;
  color: var(--muted); background: color-mix(in srgb, var(--accent) 8%, var(--panel));
  border: 1px solid var(--line); border-radius: 18px;
}
.queue-empty-mark svg { width: 38px; height: 38px; }
.queue-empty-title { font-size: 20px; font-weight: 700; margin: 0; letter-spacing: -.01em; color: var(--ink); }
.queue-empty-line { color: var(--muted); margin: 0; max-width: 44ch; font-size: 14.5px; line-height: 1.5; }
.queue-empty-cta { margin-top: 16px; }

/* ---- The manifest: dockets stacked ---- */
.manifest { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }

.docket {
  position: relative; display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center; gap: 18px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 15px 20px 15px 22px; box-shadow: var(--shadow-sm);
  transition: border-color var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out),
              background var(--dur-2) var(--ease-out);
}
.docket:hover { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); box-shadow: var(--shadow-md); }

/* Share column tracks across every row so the code strip, status, and actions
   line up as one manifest: auto tracks size to the widest row, identity keeps
   the remainder. Guarded: engines without subgrid keep the per-row grid above
   (aligned enough), never a broken single-column fallback. */
@supports (grid-template-columns: subgrid) {
  .manifest { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; }
  .docket { grid-column: 1 / -1; grid-template-columns: subgrid; }
}

/* Status edge-stripe: the row's go/no-go signal, rhyming with the tag mark. */
.docket::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  border-radius: var(--radius) 0 0 var(--radius);
}
.docket--ready::before { background: var(--action); }
.docket--printed { background: var(--panel2); }
.docket--printed::before { background: var(--dot-muted); }
.docket--printed .docket-flavor { color: var(--muted); }
.docket--printed .docket-codes { opacity: .82; }
/* A printed row's action is a reprint, not the primary act: quiet the button. */
.docket--printed .btn-print {
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); box-shadow: none;
}
.docket--printed .btn-print:hover {
  background: var(--hover); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); box-shadow: none;
}

/* Highlighted arrival (?highlight=): a brief accent glow that settles, no flash. */
@keyframes docket-arrive {
  0%   { box-shadow: 0 0 0 1px var(--accent), 0 0 0 7px var(--focus-ring);
         background: color-mix(in srgb, var(--accent) 9%, var(--panel)); }
  70%  { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent), 0 0 0 3px transparent; }
  100% { box-shadow: var(--shadow-sm); background: var(--panel); }
}
.docket--arriving { animation: docket-arrive 2.2s var(--ease-out); }

/* Identity zone */
.docket-id { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.docket-flavor {
  font-size: 18px; font-weight: 700; letter-spacing: -.01em; line-height: 1.15; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.docket-sub {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); display: flex; align-items: center; gap: 6px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.docket-brand { color: var(--label); }
.docket-dot { opacity: .5; }
.docket-tags { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 3px; }

.tag {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600;
  padding: 3px 9px 3px 7px; border-radius: var(--radius-pill); line-height: 1; white-space: nowrap;
}
.tag svg { width: 13px; height: 13px; flex: 0 0 auto; }
.tag-ok { background: var(--ok-bg); color: var(--ok-ink); }
.tag-warn { background: var(--warn-bg); color: var(--warn-ink); }
.tag-info {
  background: color-mix(in srgb, var(--accent) 13%, var(--panel)); color: var(--accent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 26%, transparent);
}

/* Code strip: lot / exp / po as a joined, labeled Plex-Mono chip */
.docket-codes {
  display: flex; align-items: stretch; margin: 0; background: var(--input-bg);
  border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden;
}
.code { display: flex; flex-direction: column; gap: 3px; padding: 6px 15px;
  min-width: 0; border-left: 1px solid var(--line); }
.code:first-child { border-left: 0; }
.code-lab { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); margin: 0; }
.code-val { font-size: 14px; font-weight: 600; color: var(--ink); margin: 0; line-height: 1.2; }

/* Status zone */
.docket-status { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; min-width: 84px; }
.dstat { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 700;
  text-transform: capitalize; }
.dstat-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.dstat-ready { color: var(--ok-ink); }
.dstat-ready .dstat-dot { background: var(--action);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--action) 22%, transparent); }
.dstat-printed { color: var(--muted); }
.dstat-printed .dstat-dot { background: var(--dot-muted); }
.dstat-count { font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--muted); }
.docket-when { font-size: 11.5px; color: var(--muted); font-weight: 500; }

/* Action zone: stepper + Print (primary) + PDF (secondary), all ≥44px touch */
.docket-actions { display: flex; align-items: center; gap: 12px; justify-self: end; }
.docket-actions .print-form { display: flex; align-items: center; gap: 10px; }
.docket-actions .btn svg { width: 16px; height: 16px; flex: 0 0 auto; }

.stepper {
  display: inline-flex; align-items: stretch; height: 44px; background: var(--input-bg);
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.stepper-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; min-width: 44px;
  border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 0;
  transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.stepper-btn svg { width: 16px; height: 16px; }
.stepper-btn:hover { background: var(--hover); color: var(--ink); }
.stepper-btn:active { background: var(--active-bg); }
.stepper input {
  width: 44px; border: 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line);
  background: transparent; text-align: center; color: var(--ink);
  font-family: var(--font-mono); font-size: 15px; font-weight: 600;
  -moz-appearance: textfield; appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper input:focus { outline: none; }
.stepper:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }

.docket-pdf {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 8px 10px;
  font-size: 13px; font-weight: 600; color: var(--muted); text-decoration: none;
  border-radius: 8px; transition: color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.docket-pdf svg { width: 15px; height: 15px; }
.docket-pdf:hover { color: var(--ink); background: var(--hover); }
.docket-pdf:focus-visible { outline: none; color: var(--ink); box-shadow: 0 0 0 3px var(--focus-ring); }

/* Tablet-landscape (queue's second device): keep one row, tighten the rhythm. */
@media (max-width: 1080px) {
  .docket { gap: 13px; padding: 14px 16px 14px 18px; }
  .code { padding: 6px 11px; }
  .docket-status { min-width: 0; }
  .docket-actions { gap: 10px; }
  .docket-pdf { padding: 8px 7px; }
  .queue-search input { min-width: 230px; }
}

/* ======================================================================= *
 *  PAGE: PIN  (Phase 2 / Agent B)                                          *
 *  The product's front door: a vertically-centred card carrying the        *
 *  wordmark and a Plex-Mono code entry with a real glow ring. A rejected   *
 *  PIN shakes the card (JS-gated, reduced-motion-safe). All rules are      *
 *  .pin-shell-scoped so they cleanly outrank the legacy .pin-card block.   *
 * ======================================================================= */
.pin-shell {
  position: relative; display: flex; align-items: center; justify-content: center;
  min-height: calc(100vh - 110px);
}
.pin-shell::before {
  content: ""; position: absolute; z-index: 0; width: min(560px, 90%); height: 340px;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 16%, transparent), transparent 68%);
  filter: blur(6px);
}
.pin-shell .pin-card {
  position: relative; z-index: 1; width: 100%; max-width: 384px; margin: 0; text-align: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 32px 30px 30px; box-shadow: var(--shadow-lg);
}
.pin-shell .pin-mark {
  display: inline-flex; align-items: center; gap: 9px; margin-bottom: 22px; color: var(--ink);
}
.pin-shell .pin-mark svg { width: 30px; height: 30px; }
.pin-shell .pin-wordmark { font-size: 15px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap; }
.pin-shell .pin-wordmark .soft { color: var(--muted); font-weight: 500; }

.pin-shell .pin-h { font-size: 21px; font-weight: 700; margin: 0 0 6px; letter-spacing: -.01em; color: var(--ink); }
.pin-shell .pin-lead { color: var(--muted); margin: 0 0 22px; font-size: 14px; line-height: 1.5; }

.pin-shell .pin-form { display: grid; gap: 16px; text-align: left; margin: 0; }
.pin-shell .pin-field { display: grid; gap: 7px; }
.pin-shell .pin-lab { font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted); }
.pin-shell .pin-input {
  /* A text input carries a ~20-char intrinsic width; inside a grid its
     min-width:auto refuses to shrink below that, so it blows past the card and
     overflow:hidden clips the field + focus ring. min-width:0 lets it obey the
     card. */
  min-width: 0; width: 100%;
  font-family: var(--font-mono); font-size: 22px; font-weight: 600; letter-spacing: .3em;
  text-align: center; padding: 13px 12px; min-height: 56px; color: var(--ink);
  background: var(--input-bg); border: 1px solid var(--line); border-radius: 10px;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.pin-shell .pin-input::placeholder { color: var(--muted); opacity: .55; letter-spacing: .3em; }
.pin-shell .pin-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--focus-ring); }
.pin-shell .pin-submit { width: 100%; margin-top: 4px; font-size: 15px; min-height: 48px; }

@keyframes pin-shake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-7px); }
  30% { transform: translateX(6px); }
  45% { transform: translateX(-5px); }
  60% { transform: translateX(4px); }
  75% { transform: translateX(-2px); }
}
.pin-shell .pin-shake { animation: pin-shake .45s var(--ease-in-out); }

/* ======================================================================= *
 *  PAGES: SETUP LIST + PRODUCT FORM CHROME   (Phase 2 / Agent D)
 *  Additive, setup/form-scoped. The label CANVAS interior (.cv-canvas
 *  inner elements: geometry, colors, fonts) is deliberately UNTOUCHED —
 *  only its outer frame, caption bars, toolbar, rail and page chrome
 *  are styled here.
 * ======================================================================= */

/* ----------------------------------------------------------------------- *
 *  Setup list — settings cards + the product manifest
 * ----------------------------------------------------------------------- */
.setup-head { margin-bottom: 10px; }

/* Setup page: lock to the viewport at the target sizes so the product table
   scrolls internally and the page never grows (Greg's no-scroll rule). */
main:has(.setup-products) { max-width: 1400px; }
@media (min-width: 921px) and (min-height: 640px) {
  main:has(.setup-products) {
    height: calc(100vh - 62px); display: flex; flex-direction: column; overflow: hidden;
  }
  .setup-products { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
}

.setup-settings { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 8px; }
.scard {
  display: flex; align-items: center; gap: 12px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 10px 14px; box-shadow: var(--shadow-sm);
}
.scard-eyebrow {
  display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto;
  font-size: var(--fs-eyebrow); font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--muted);
}
.scard-eyebrow svg { color: var(--accent); }
.scard-input {
  flex: 1; min-width: 0; padding: 9px 12px; min-height: 40px; font: inherit;
  font-size: var(--fs-sm); color: var(--ink);
  border: 1px solid var(--input); border-radius: var(--radius-sm); background: var(--input-bg);
}
.scard-input::placeholder { color: var(--muted); }
.scard-save { min-height: 40px; padding: 8px 18px; flex: 0 0 auto; }
.access-state {
  flex: 1; display: inline-flex; align-items: center; gap: 9px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink);
}
.pin-dots {
  font-family: var(--font-mono); font-size: 17px; letter-spacing: 3px;
  color: var(--accent); line-height: 1; transform: translateY(1px);
}
.setup-note { margin: 0 0 8px; font-size: var(--fs-xs); color: var(--muted); line-height: 1.5; }
.setup-note .mono { font-size: 12px; color: var(--label); }

.products-head { display: flex; align-items: center; gap: 8px; margin: 0 0 9px; }
.products-eyebrow {
  font-size: var(--fs-eyebrow); font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--muted);
}
.products-count {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600; line-height: 1;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent);
  border-radius: var(--radius-pill); padding: 3px 8px;
}

/* ----------------------------------------------------------------------- *
 *  Shared product table (.ptable) — used by BOTH Setup (adds Template /
 *  GTIN / Edit columns) and Run (a click-to-build picker). Dense but
 *  readable; the thead sticks while the body scrolls inside .ptable-scroll
 *  so the page itself never grows. Amber scan-rail hover + Draft/Approved
 *  pills are the table's signature.
 * ----------------------------------------------------------------------- */
.ptable-scroll {
  /* Columns are normalized to this container's width (tables.js), so sideways
     overflow is impossible by construction — hide the axis outright. */
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); background: var(--panel);
  scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
.ptable-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
.ptable-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 999px;
  border: 3px solid transparent; background-clip: padding-box; }
.ptable-scroll::-webkit-scrollbar-thumb:hover { background: var(--muted); }

.ptable { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--panel); }
.ptable thead th {
  position: sticky; top: 0; z-index: 2;
  padding: 10px 11px; text-align: left; background: var(--panel2);
  font-family: var(--font-sans); font-size: var(--fs-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
.ptable tbody td {
  padding: 8px 11px; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  vertical-align: middle; line-height: 1.25;
}
.ptable tbody tr:last-child td { border-bottom: 0; }
.ptable tbody tr { transition: background var(--dur-2) var(--ease-out); }
.ptable tbody tr:hover { background: var(--hover); }
.ptable tbody tr[hidden] { display: none; }

/* Scan rail: a barcode bar that lights the wordmark's gold on hover. */
.ptable .col-rail { width: 12px; padding: 0 0 0 10px; }
.scan-rail { display: block; width: 3px; height: 22px; border-radius: 2px;
  background: color-mix(in srgb, var(--muted) 32%, transparent);
  transition: background var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.ptable tbody tr:hover .scan-rail { background: var(--clm-mark);
  box-shadow: 0 0 9px color-mix(in srgb, var(--clm-mark) 55%, transparent); }

/* Thumbnail cell: the label preview, matted on white. */
.col-thumb { width: 48px; padding-right: 6px; }
.ptable-thumb { position: relative; display: block; width: 38px; height: 54px; overflow: hidden;
  border-radius: 5px; background: #f1f0ec; border: 1px solid rgba(0,0,0,.16);
  box-shadow: 0 1px 3px var(--shadow); }
.ptable-setup .ptable-thumb { cursor: zoom-in; }
.ptable-thumb::after { content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(100deg, #e7e6e2 30%, #f5f4f1 50%, #e7e6e2 70%);
  background-size: 220% 100%; animation: thumb-shimmer 1.3s ease-in-out infinite; }
.ptable-thumb.loaded::after { opacity: 0; animation: none; }
.ptable-thumb img { position: relative; z-index: 1; width: 100%; height: 100%;
  object-fit: contain; background: #fff; }

/* Identity columns. */
.cell-brand { font-weight: 600; font-size: var(--fs-sm); color: var(--label); overflow-wrap: anywhere; }
/* Text cells fill whatever width tables.js normalization gives their column
   (fixed layout: the th width governs) — capping them here only re-truncates
   text the column has room for. */
.cell-line { font-size: var(--fs-sm); color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Setup carries more columns than Run; tighten its cell padding and cap its
   identity text so all 11 columns (through State + Edit) stay on-screen at 1400
   without a horizontal scroll, while the product line keeps enough room to read. */
.ptable-setup tbody td, .ptable-setup thead th { padding-left: 9px; padding-right: 9px; }
.ptable-setup .tmpl-badge { font-size: var(--fs-eyebrow); }
.flavor-lockup { display: flex; align-items: center; gap: 7px; min-width: 0; }
.prod-flavor { font-weight: 600; font-size: var(--fs-sm); color: var(--ink); letter-spacing: -.005em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prod-id { display: block; font-size: var(--fs-eyebrow); color: var(--muted); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row-flag { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--warn);
  box-shadow: 0 0 6px color-mix(in srgb, var(--warn) 55%, transparent); }

.col-num { white-space: nowrap; }
.ptable .col-num { color: var(--label); font-size: var(--fs-xs); }

.pack-pill { display: inline-block; font-size: var(--fs-eyebrow); font-weight: 600; white-space: nowrap;
  color: var(--label); background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 2px 9px; }
.tmpl-badge { display: inline-block; font-size: var(--fs-xs); color: var(--muted);
  background: color-mix(in srgb, var(--line) 42%, transparent);
  border-radius: var(--radius-sm); padding: 2px 8px; white-space: nowrap; }
.ptable .prod-code { font-size: var(--fs-xs); color: var(--label); letter-spacing: -.01em; white-space: nowrap; }

.state-pill { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: .01em;
  border-radius: var(--radius-pill); padding: 2px 10px 2px 9px; }
.state-pill.is-approved { color: var(--ok-ink); background: var(--ok-bg); border: 1px solid var(--ok-line); }
.state-pill.is-approved svg { color: var(--ok-ink); }
/* Draft is the normal default (pending sign-off): a calm neutral pill with a
   small amber "pending" dot so a green Approved row is what pops. */
.state-pill.is-draft { color: var(--muted); background: var(--panel2); border: 1px solid var(--line); }
.state-pill.is-draft::before { content: ""; width: 5px; height: 5px; border-radius: 50%;
  flex: 0 0 auto; background: var(--warn); }

/* Case-code column: names the KIND of product symbol a spec prints (GS1 GTIN /
   Internal GTIN / Code-128 / None), distinct from the pack-level pill. */
.code-pill { display: inline-block; font-size: var(--fs-eyebrow); font-weight: 600;
  white-space: nowrap; color: var(--label); background: var(--panel2);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 2px 9px; }
.code-pill.is-pending { color: var(--warn); border-color: var(--warn); }
/* Pending-GTIN products are not print-ready: an amber pill on the run/setup rows. */
.state-pill.is-pending { color: var(--warn); background: var(--panel2);
  border: 1px solid var(--warn); margin-left: 5px; }

.col-edit { width: 146px; text-align: right; }
.row-actions { display: inline-flex; align-items: center; gap: 2px; justify-content: flex-end; }
.row-dupe { display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
  color: var(--muted); padding: 6px; border-radius: var(--radius-sm); line-height: 0;
  transition: color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out); }
.ptable tbody tr:hover .row-dupe { color: var(--ink); }
.row-dupe:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.row-dupe:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
.row-edit { display: inline-flex; align-items: center; gap: 3px; text-decoration: none;
  font-size: var(--fs-xs); font-weight: 600; color: var(--muted); line-height: 1;
  padding: 5px 9px 5px 12px; border-radius: var(--radius-sm);
  transition: color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out); }
.row-edit svg { transition: transform var(--dur-2) var(--ease-out); }
.ptable tbody tr:hover .row-edit { color: var(--ink); }
.row-edit:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.row-edit:hover svg { transform: translateX(2px); }
.row-edit:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }

/* ----------------------------------------------------------------------- *
 *  Product form chrome — toolbar, canvas/proof frames, rail sections
 * ----------------------------------------------------------------------- */

/* Keep canvas + proof + rail on ONE row down to 1280px. The 4x2 canvas is the
   widest pair (480 + 480), so trim the editor's side padding, the stage gap and
   the rail so the three columns still seat without wrapping (a wrap pushes the
   rail below and re-introduces vertical scroll). */
main:has(.wys-page) { padding-left: 16px; padding-right: 16px; }
.wys-stage { gap: 18px; }
.wys-rail { width: 242px; flex: 0 0 242px; }

/* Top toolbar: admin fields as one refined row; Save is the loud control. */
.wys-bar { align-items: flex-end; gap: 11px; padding: 11px 14px; border-radius: var(--radius-lg); }
.wys-back {
  width: 38px; min-height: 38px; padding: 0; font-size: 17px;
  display: inline-flex; align-items: center; justify-content: center;
}
.tb-lab { font-size: var(--fs-eyebrow); font-weight: 700; letter-spacing: .06em; color: var(--muted); }
.tb-field input, .tb-field select {
  border-radius: var(--radius-sm); background: var(--input-bg); border-color: var(--input); color: var(--ink);
}
.tb-field input[readonly] { background: var(--panel2); color: var(--muted); cursor: default; }
.tb-fixed { background: var(--panel2); color: var(--muted); border: 1px solid var(--line); }
.tb-check { gap: 7px; font-size: var(--fs-sm); font-weight: 500; color: var(--ink); }
.tb-check input { accent-color: var(--accent); width: 17px; height: 17px; }
.wys-save { min-height: 40px; padding: 9px 24px; margin-left: auto; font-weight: 700; }

/* Approved-artwork alert (edit mode): a real warning component. */
.wys-alert {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--warn-bg); color: var(--warn-ink);
  border: 1px solid var(--warn-line); border-left: 3px solid var(--warn);
  border-radius: var(--radius); padding: 10px 14px; font-size: var(--fs-sm);
}
.wys-alert-icon { color: var(--warn); flex: 0 0 auto; margin-top: 1px; }
.wys-alert-body strong { font-weight: 700; }

/* Caption bars over the canvas + proof. */
.wys-cap { color: var(--muted); letter-spacing: .09em; gap: 9px; }
.wys-hint { color: var(--muted); }
.wys-spin { color: var(--accent); font-weight: 600; animation: wys-pulse 1.15s var(--ease-in-out) infinite; }
@keyframes wys-pulse { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

/* Canvas + proof: matched white "pages" floating on the dark chrome. */
.cv-canvas, .cv-preview {
  border: 1px solid color-mix(in srgb, var(--line) 80%, #000);
  border-radius: 6px; box-shadow: var(--shadow-lg);
}

/* Skeleton shimmer while /api/preview renders (hooks #wys-spin visibility). */
.cv-preview::after {
  content: ""; position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, transparent 22%,
              rgba(20,24,29,.05) 42%, rgba(20,24,29,.09) 50%, rgba(20,24,29,.05) 58%, transparent 78%);
  background-size: 220% 100%; background-position: 180% 0;
  transition: opacity var(--dur-2) var(--ease-out);
}
.wys-side:has(#wys-spin:not([hidden])) .cv-preview::after {
  opacity: 1; animation: proof-shimmer 1.15s var(--ease-in-out) infinite;
}
@keyframes proof-shimmer { to { background-position: -40% 0; } }

/* Error banner keeps its wrap sizing (defined above); just the palette here. */
.wys-err {
  background: color-mix(in srgb, var(--destructive) 12%, var(--panel));
  color: var(--destructive); border: 1px solid color-mix(in srgb, var(--destructive) 34%, var(--panel));
}

/* Rail sections: eyebrow headings with a hairline divider. */
.cv-controls { gap: 9px; padding: 13px 14px; border-radius: var(--radius-lg); }
.rail-lab {
  display: block; width: 100%; font-size: var(--fs-eyebrow); font-weight: 700;
  letter-spacing: .09em; color: var(--muted);
  padding-bottom: 9px; margin-bottom: 1px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.cv-toggle { gap: 8px; font-size: var(--fs-sm); font-weight: 500; color: var(--ink); }
.cv-toggle input { accent-color: var(--accent); width: 16px; height: 16px; }

/* Native selects in the form get a themed chevron (ids/names preserved). */
.wys-page select {
  appearance: none; -webkit-appearance: none; padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239a9a9a' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 13px;
  cursor: pointer;
}

/* Aux upload: a real dropzone + a decoded-value chip. */
.cv-ghostbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px dashed color-mix(in srgb, var(--line) 90%, var(--accent));
  color: var(--muted); background: color-mix(in srgb, var(--accent) 4%, transparent);
  transition: color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out),
              background var(--dur-2) var(--ease-out);
}
.cv-ghostbtn:hover:not(:disabled), .cv-ghostbtn:not(.cv-disabled):hover {
  color: var(--accent); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
.cv-auxchip {
  background: var(--ok-bg); border: 1px solid var(--ok-line); border-radius: var(--radius-sm);
  padding: 5px 6px 5px 9px; gap: 7px;
}
.cv-auxchip b { color: var(--ok-ink); font-size: 11px; font-weight: 700; }
.cv-auxchip code { font-family: var(--font-mono); font-size: 11px; color: var(--ok-ink); }
.cv-auxdel { color: var(--muted); }
.cv-auxdel:hover { color: var(--destructive); }
.cv-auxerr { color: var(--destructive); font-weight: 600; font-size: var(--fs-xs); }

/* Weight suggestion chips. */
.cv-chips { gap: 6px; }
.cv-chips-lab { color: var(--muted); }
.cv-suggest {
  font-size: var(--fs-xs); font-weight: 600; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius-sm); padding: 4px 9px;
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
              border-color var(--dur-2) var(--ease-out);
}
.cv-suggest:hover { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.cv-suggest b { font-family: var(--font-mono); font-weight: 700; }

/* Propose GTIN from UPC: mono digits, indicator chip, amber confirm note. */
.propose-row { gap: 7px; margin: 8px 0 2px; }
.propose-btn { width: 100%; min-height: 36px; padding: 7px 12px; font-size: var(--fs-xs); }
.propose-chip {
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink);
  background: var(--panel2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 7px 9px; gap: 8px;
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.propose-chip b { color: var(--accent); font-weight: 700; }
.propose-chip span { color: var(--muted); font-size: 11px; }
.propose-chip:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.propose-fill {
  font-family: var(--font-sans); font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--accent-ink); background: var(--accent); border-radius: var(--radius-sm); padding: 2px 7px;
}
.propose-note {
  font-size: var(--fs-xs); font-weight: 500; line-height: 1.45; color: var(--warn-ink);
  background: var(--warn-bg); border: 1px solid var(--warn-line);
  border-left: 3px solid var(--warn); border-radius: var(--radius-sm); padding: 8px 10px;
}
/* UPC digits directly under their "Print unit UPC-A" checkbox (owner request):
   indented so it reads as belonging to the toggle above it. */
.cv-upcrail { margin: 2px 0 4px 24px; }

/* The internal-GTIN alternative is a different KIND of number, not proposal #10:
   a divider names the split and the chip drops the mono/gold styling for a
   dashed, muted look so it can't be misread as one of the client's GS1 numbers. */
.propose-divider {
  margin-top: 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
  display: flex; align-items: center; gap: 8px;
}
.propose-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.propose-chip--internal { border-style: dashed; }
.propose-chip--internal b { color: var(--muted); }
.propose-chip--internal:hover { border-color: var(--muted); background: var(--panel2); }
.propose-chip--internal .propose-fill { background: var(--muted); color: var(--panel); }

/* ======================================================================= *
 *  POLISH PASS  (2026-07-20) — targeted fixes from the blind-judge defect
 *  list. Appended last so these rules resolve the cascade intentionally.
 *  Additive only: no JS/form contract touched, canvas interiors + proof
 *  IMAGES stay white; only chrome is retuned.
 * ======================================================================= */

/* --- Accessibility utility the bundled Basecoat build shipped broken
       (`.sr-only{width:auto}` does NOT hide, so "ROW LABEL" / "OPEN BUILD"
       leaked as visible column headers). Restore a real visually-hidden
       utility: the tick-strip + thumbnail + chevron headers now read to
       screen readers only, killing the ambiguous visible labels. --- */
.sr-only {
  position: absolute !important; width: 1px !important; height: 1px !important;
  padding: 0 !important; margin: -1px !important; overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important;
}

/* --- Numeric columns right-align (NET WT, UNITS/CASE) so digits read as a
       column of figures, header included. --- */
.ptable th.col-num, .ptable td.col-num { text-align: right; }
.ptable td.col-num { font-variant-numeric: tabular-nums; }

/* --- Scan-rail: a hover-only reveal, not an always-on "measle" tick. At rest
       it is invisible; hovering a row lights the wordmark gold as a scan cue. --- */
.scan-rail { background: transparent; }

/* ----------------------------------------------------------------------- *
 *  PRODUCT FORM — the biggest lift (proof pane read as broken white box)
 * ----------------------------------------------------------------------- */

/* Live-proof pane: a themed matte "workbench" when empty/loading instead of a
   raw white rectangle. The RENDERED proof <img> fills the box and stays white
   (a physical-label facsimile); only the empty + loading chrome is themed. */
.cv-preview {
  background: radial-gradient(130% 105% at 50% -12%,
              color-mix(in srgb, var(--accent) 11%, var(--panel2)),
              color-mix(in srgb, var(--panel2) 74%, #000));
}
.cv-preview-empty {
  flex-direction: column; gap: 11px; padding: 24px; background: transparent;
  color: var(--muted);
}
.cv-preview-icon {
  width: 42px; height: 42px; opacity: .9;
  color: color-mix(in srgb, var(--accent) 60%, var(--muted));
}
.cv-preview-empty-title {
  font-size: var(--fs-sm); font-weight: 700; letter-spacing: -.01em; color: var(--ink);
}
.cv-preview-empty-sub {
  font-size: var(--fs-xs); color: var(--muted); max-width: 27ch; line-height: 1.5;
}

/* Skeleton shimmer while /api/preview renders — a light-on-dark (or dark-on-
   light) sweep keyed off #wys-spin, legible on the themed matte. */
.cv-preview::after {
  content: ""; position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, transparent 20%,
              color-mix(in srgb, var(--ink) 9%, transparent) 42%,
              color-mix(in srgb, var(--ink) 15%, transparent) 50%,
              color-mix(in srgb, var(--ink) 9%, transparent) 58%, transparent 80%);
  background-size: 220% 100%; background-position: 180% 0;
  transition: opacity var(--dur-2) var(--ease-out);
}

/* Ghost optional-field chips: ALWAYS visible (hard client ruling) but calmed —
   quiet + tight at rest so they read as one intentional "add a field" strip,
   brightening to the accent on hover. */
.cv-ghosts { gap: 2px 2px; }
.cv-chip-btn {
  color: #aab2bb; background: transparent; border: 1px dashed #dbe0e6;
  padding: 1px 4px; letter-spacing: .3px; opacity: .82;
  transition: color .12s, border-color .12s, background .12s, opacity .12s;
}
.cv-chip-btn:hover {
  opacity: 1; color: var(--brand); border-color: var(--brand);
  border-style: solid; background: rgba(31,111,235,.06);
}

/* Placeholder-vs-value: make an empty field read unmistakably EMPTY (a lighter,
   clearly-a-hint placeholder + a neutral "slot" tint) so ghost placeholders no
   longer look like committed defaults. */
.cv-input::placeholder { color: #ccd3da; font-style: italic; }
.cv-field:has(.cv-input:placeholder-shown) {
  box-shadow: inset 0 0 0 1px #d3dae1; background: #f5f8fa;
}
.cv-field:has(.cv-input:placeholder-shown):hover {
  box-shadow: inset 0 0 0 1px #9db6e6; background: rgba(31,111,235,.05);
}

/* Top toolbar: breathing room + the FILENAME STEM demoted to a secondary,
   technical field (it exposes an internal naming convention) so Product ID /
   SKU read as the primary identity inputs. */
.wys-bar { gap: 13px 16px; padding: 9px 16px; }
.wys-bar .tb-field:has(input[name="name_stem"]) .tb-lab { color: var(--muted); opacity: .78; }
.wys-bar .tb-field:has(input[name="name_stem"]) input {
  font-family: var(--font-mono); font-size: 12.5px; color: var(--muted);
  background: var(--panel2);
}
.wys-bar .tb-check:first-of-type { margin-left: 4px; }

/* Rail: differentiate the two near-identical cards + give MORE FIELDS real
   hierarchy (labelled Barcode / Run-defaults sub-groups, icons on each card). */
.rail-lab { display: flex; align-items: center; gap: 7px; padding-bottom: 6px; }
.rail-lab svg { width: 14px; height: 14px; flex: 0 0 auto; color: var(--accent); }
.rail-group { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.rail-group + .rail-group {
  margin-top: 1px; padding-top: 6px;
  border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
}
.rail-sub {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  color: var(--label);
}
/* The advanced/config card reads a touch quieter than the primary artwork card. */
.rail-card--fields { background: color-mix(in srgb, var(--panel) 70%, var(--bg)); }

/* Compact the rail's + toolbar's vertical rhythm so the grouped card never
   outgrows the label canvas (keeps the form on one screen at 1280×800;
   horizontal breathing in the toolbar is untouched). */
.wys-rail { gap: 9px; }
.cv-controls { padding: 9px 13px; gap: 6px; }
.wys-rail .tb-field input, .wys-rail .tb-field select { min-height: 32px; }
.wys-rail .propose-btn { min-height: 32px; }
.wys-bar .tb-field input, .wys-bar .tb-field select { min-height: 34px; }

/* ----------------------------------------------------------------------- *
 *  RUN — build modal surface unification + PO format hint
 * ----------------------------------------------------------------------- */

/* Was a cold near-black (#0c0e11) preview panel bolted to a warm modal body.
   Now a theme-derived matte one step off the body surface, with a soft accent
   glow — one graceful family. The white label facsimile still lifts off it. */
.rmodal-preview {
  position: relative;
  background: radial-gradient(120% 88% at 50% 0%,
              color-mix(in srgb, var(--accent) 12%, var(--panel2)),
              color-mix(in srgb, var(--panel2) 72%, #000));
}
/* Live-proof status chips over the modal preview: a quiet "rendering…" pulse
   while the engine works, and a red note when the typed inputs can't render. */
.rmodal-spin {
  position: absolute; top: 10px; right: 12px; font-size: 11px; font-weight: 650;
  letter-spacing: .04em; color: var(--muted); animation: rm-pulse 1.1s ease-in-out infinite;
}
@keyframes rm-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .rmodal-spin { animation: none; } }
.rmodal-preverr {
  position: absolute; left: 12px; right: 12px; bottom: 10px;
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.4; color: var(--err);
  background: color-mix(in srgb, var(--err) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--err) 40%, var(--line));
  border-radius: var(--radius-sm); padding: 6px 9px;
}

/* ----------------------------------------------------------------------- *
 *  PRINT QUEUE
 * ----------------------------------------------------------------------- */

/* Kill the dead mid-row gap: the flexible space now sits between the info
   group (identity · codes · status) and the action cluster, so the docket
   reads as one unit that ends in its controls, still column-aligned per row. */
.docket { grid-template-columns: minmax(0, auto) auto auto minmax(0, 1fr); }
@supports (grid-template-columns: subgrid) {
  .manifest { grid-template-columns: minmax(0, auto) auto auto minmax(0, 1fr); }
}

/* Title hierarchy: brand+flavor lead; Verified / two-labels badges recede to a
   quiet tertiary strip so they stop competing with the name. */
.docket-tags { margin-top: 5px; gap: 6px; }
.docket-tags .tag { font-size: 11px; padding: 2px 8px 2px 6px; font-weight: 600; }
.docket-tags .tag svg { width: 12px; height: 12px; }
.tag-ok { background: color-mix(in srgb, var(--ok-bg) 72%, var(--panel)); color: var(--ok-ink); }
.tag-info {
  background: color-mix(in srgb, var(--muted) 10%, var(--panel)); color: var(--muted);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--muted) 20%, transparent);
}

/* Printed (done) rows clearly de-emphasised at rest, restored to full presence
   on hover (still a valid re-print target). */
.docket--printed { opacity: .64; box-shadow: none;
  border-color: color-mix(in srgb, var(--line) 62%, transparent); }
.docket--printed:hover { opacity: 1; }

/* ----------------------------------------------------------------------- *
 *  SETUP LIST — card balance, count contrast, friendly template names
 * ----------------------------------------------------------------------- */

/* Access card: the status now reads as a filled "field" that fills the middle,
   mirroring the Printer input + Save so the two cards balance and the dead gap
   before Sign out is gone. */
.scard-access .access-state {
  background: var(--input-bg); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 0 13px; min-height: 40px;
}
.scard-access .access-state .pin-dots { color: var(--ok-ink); }

/* Products count: a clear neutral pill (was low-contrast teal-on-teal). */
.products-count {
  color: var(--ink); background: var(--panel2);
  border: 1px solid var(--line); font-weight: 700;
}
.products-head { justify-content: space-between; }
.products-head .products-lead { display: flex; align-items: center; gap: 8px; }

/* Friendly template label (raw slug preserved as a tooltip in the markup). */
.tmpl-badge { text-transform: none; letter-spacing: 0; font-family: var(--font-sans);
  font-weight: 600; }

/* ----------------------------------------------------------------------- *
 *  PIN — identity + atmosphere, clear empty field, visible error state
 * ----------------------------------------------------------------------- */

/* Atmosphere: a stronger accent bloom + a giant, faint barcode field behind the
   card so the vast dark space reads as the product's own world, not emptiness. */
.pin-shell::before {
  width: min(720px, 94%); height: 460px; filter: blur(12px);
  background: radial-gradient(circle,
              color-mix(in srgb, var(--accent) 20%, transparent), transparent 70%);
}
.pin-shell::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: .06;
  background: repeating-linear-gradient(90deg, var(--ink) 0 2px, transparent 2px 9px);
  -webkit-mask: radial-gradient(ellipse 62% 58% at 50% 46%, #000, transparent 76%);
          mask: radial-gradient(ellipse 62% 58% at 50% 46%, #000, transparent 76%);
}
/* The card wears a barcode strip across its top edge like a real label tag. */
.pin-shell .pin-card { overflow: hidden; padding-top: 34px; }
.pin-shell .pin-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: repeating-linear-gradient(90deg,
              var(--accent) 0 3px, transparent 3px 5px,
              var(--accent) 5px 6px, transparent 6px 11px);
  opacity: .92;
}
/* Clearly-empty PIN field: drop the ambiguous resting dots, widen the tracking
   so typed digits read as discrete slots. */
.pin-shell .pin-input { letter-spacing: .55em; padding-right: 6px; }
.pin-shell .pin-input::placeholder { color: transparent; }
.pin-shell .pin-input.pin-input--error {
  border-color: var(--err);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--err) 22%, transparent);
}
/* Visible wrong-PIN error (replaces the easy-to-miss corner toast). */
.pin-error {
  display: flex; align-items: center; gap: 8px; margin: 2px 0 -4px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--err); text-align: left;
}
.pin-error svg { width: 15px; height: 15px; flex: 0 0 auto; }

/* Queue live-search empty state (mirrors Run's .no-match). */
.queue-nomatch {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; padding: 54px 16px; text-align: center; color: var(--muted);
}
.queue-nomatch[hidden] { display: none; }
.queue-nomatch svg { width: 34px; height: 34px; opacity: .5; }
.queue-nomatch p { margin: 0; font-weight: 600; font-size: var(--fs-sm); color: var(--ink); }
.queue-nomatch span { font-size: var(--fs-xs); }

/* Relocated "New product" CTA sits in the products section header — sized to
   that dense row rather than the page hero. */
.products-new { min-height: 40px; padding: 9px 16px; font-size: var(--fs-sm); flex: 0 0 auto; }

/* ----------------------------------------------------------------------- *
 *  Sortable table headers (Setup + Run) + Setup fit-on-screen
 * ----------------------------------------------------------------------- */

/* The header label becomes a real button; the <th> keeps aria-sort. */
.th-sort {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  transition: color var(--dur-2) var(--ease-out);
}
.th-sort:hover { color: var(--ink); }
.th-sort:focus-visible { outline: none; border-radius: 3px; box-shadow: 0 0 0 2px var(--focus-ring); }
th[aria-sort="ascending"] .th-sort, th[aria-sort="descending"] .th-sort { color: var(--ink); }

/* Neutral dim double-chevron when sortable-inactive; the active direction lights
   the accent and dims its opposite. */
.th-arrow {
  display: inline-flex; flex-direction: column; align-items: center;
  line-height: .58; font-size: 7px; opacity: .34; color: var(--muted);
  transition: opacity var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.th-arrow::before { content: "\25B2"; }
.th-arrow::after { content: "\25BC"; }
.th-sort:hover .th-arrow { opacity: .6; }
th[aria-sort="ascending"] .th-arrow,
th[aria-sort="descending"] .th-arrow { opacity: 1; color: var(--accent); }
th[aria-sort="ascending"] .th-arrow::after { opacity: .26; }
th[aria-sort="descending"] .th-arrow::before { opacity: .26; }

/* Setup carries the most columns; trim its widths so all 11 (through Edit) sit
   on screen at 1280 without the EDIT column running off — the .ptable-scroll
   still contains any residual overflow so the PAGE never scrolls horizontally. */
.ptable-setup tbody td, .ptable-setup thead th { padding-left: 7px; padding-right: 7px; }
.ptable-setup .cell-line { max-width: 144px; }
.ptable-setup .cell-flavor { max-width: 168px; }
.ptable-setup .col-thumb { width: 42px; }
.ptable-setup .ptable-thumb { width: 33px; height: 47px; }

/* ---- Resizable table columns (tables.js) ---- */
.ptable thead th { position: relative; }
.ptable .th-resize { position: absolute; top: 0; right: -4px; width: 10px; height: 100%;
  display: flex; align-items: center; justify-content: center;
  cursor: col-resize; z-index: 3; touch-action: none; }
/* Always-visible grip: two short vertical bars at the column boundary so it
   reads as "drag me". Brightens + grows on hover / while dragging. */
.ptable .th-resize::after { content: ""; height: 42%; width: 4px;
  border-left: 1.5px solid var(--muted); border-right: 1.5px solid var(--muted);
  opacity: .45; transition: opacity var(--dur-1) var(--ease-out),
    height var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.ptable .th-resize:hover::after,
body.col-resizing .ptable .th-resize::after {
  opacity: 1; height: 62%; border-color: var(--accent); }
body.col-resizing { cursor: col-resize; user-select: none; }
/* Fixed layout + explicit widths make cells clip cleanly rather than reflow. */
.ptable td, .ptable th { overflow: hidden; text-overflow: ellipsis; }

/* ----------------------------------------------------------------------- *
 *  Delete: danger button, row action, and the shared confirm modal
 * ----------------------------------------------------------------------- */
.btn-danger { color: var(--err); border-color: color-mix(in srgb, var(--err) 45%, var(--line)); }
.btn-danger:hover { background: color-mix(in srgb, var(--err) 12%, var(--panel));
  border-color: var(--err); color: var(--err); }
.row-del { display: inline-flex; align-items: center; justify-content: center; line-height: 0;
  border: 0; background: none; font: inherit; cursor: pointer; color: var(--muted);
  padding: 6px; border-radius: var(--radius-sm);
  transition: color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out); }
.ptable tbody tr:hover .row-del { color: var(--ink); }
.row-del:hover { color: var(--err); background: color-mix(in srgb, var(--err) 10%, transparent); }
.row-del:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }

.confirm-overlay { position: fixed; inset: 0; z-index: 110; display: flex;
  align-items: center; justify-content: center; background: rgba(0, 0, 0, .55); }
.confirm-overlay[hidden] { display: none; }
.confirm-box { width: min(420px, calc(100vw - 40px)); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md); padding: 20px 22px; }
.confirm-box h3 { margin: 0 0 8px; font-size: var(--fs-md, 16px); color: var(--ink); }
.confirm-msg { margin: 0 0 16px; font-size: var(--fs-sm); color: var(--label); line-height: 1.45; }
.confirm-msg .confirm-target { font-weight: 700; color: var(--ink); }
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* Toolbar duplicate warnings (Product ID / Filename stem live name-check) */
.tb-warn { display: block; margin-top: 2px; font-size: var(--fs-eyebrow); font-weight: 700;
  letter-spacing: .02em; color: var(--warn); }
.tb-warn:empty, .tb-warn[hidden] { display: none; }

/* UX-review polish: keep the destructive button off the Save button's shoulder,
   let the Product ID show a full auto-suggested id, tint auto-filled fields,
   and give the modal's id line its own quiet row. */
.wys-delete { margin-right: 16px; }
.wys-bar input[name="id"] { min-width: 250px; }
.tb-field input.is-auto { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 6%, var(--panel)); }
.confirm-target-id { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--muted); }
.confirm-target-id:empty { display: none; }
