/* ════════════════════════════════════════════════════════════════════════════
   AKUMA 4X4 — INTERNAL HUB DESIGN SYSTEM  v1
   One set of tokens, two themes. Nothing below hardcodes a colour.

   Theme:  <html data-theme="light">  |  "dark"  |  absent = follow the OS
   Type:   Inter for UI, tabular numerals everywhere a figure appears,
           Archivo Black kept for the wordmark only.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── tokens ──────────────────────────────────────────────────────────────── */

:root {
  /* type scale — 14px base, 13px in dense tables */
  --fs-11: 11px;  --fs-12: 12px;  --fs-13: 13px;  --fs-14: 14px;
  --fs-16: 16px;  --fs-18: 18px;  --fs-20: 20px;  --fs-24: 24px;  --fs-30: 30px;
  --lh-tight: 1.25;  --lh: 1.5;  --lh-loose: 1.65;

  /* spacing — 4px base */
  --s1: 4px;  --s2: 8px;  --s3: 12px;  --s4: 16px;  --s5: 20px;
  --s6: 24px; --s7: 32px; --s8: 40px; --s9: 48px;  --s10: 64px;

  --r-sm: 6px;  --r: 8px;  --r-lg: 12px;  --r-full: 999px;

  --ff: "Inter", -apple-system, "Segoe UI Variable Text", "Segoe UI",
        Roboto, system-ui, sans-serif;
  --ff-brand: "Archivo Black", var(--ff);
  --ff-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Menlo, monospace;

  --nav-w: 232px;
  --topbar-h: 56px;
  --speed: 140ms;
}

/* ── light (default) ─────────────────────────────────────────────────────── */

:root, :root[data-theme="light"] {
  color-scheme: light;
  --bg:            #f5f6f8;
  --surface:       #ffffff;
  --surface-2:     #fafbfc;
  --surface-3:     #f0f2f5;
  --surface-hover: #f5f7fa;

  --border:        #e3e6ea;
  --border-strong: #cfd4db;

  --text:    #14161a;
  --text-2:  #596072;
  --text-3:  #878e9d;
  --text-on-accent: #ffffff;

  --accent:       #d10000;
  --accent-hover: #a80000;
  --accent-soft:  #fdecec;
  --accent-line:  #f6c9c9;

  --ok:        #0b7a45;   --ok-soft:     #e7f6ee;   --ok-line:     #b7e3cb;
  --warn:      #9a5b00;   --warn-soft:   #fdf2df;   --warn-line:   #f2d9a8;
  --danger:    #be1f1f;   --danger-soft: #fdeaea;   --danger-line: #f4c4c4;
  --info:      #1560c4;   --info-soft:   #e8f1fd;   --info-line:   #bcd7f7;

  --shadow-1: 0 1px 2px rgba(16,20,30,.06), 0 1px 3px rgba(16,20,30,.04);
  --shadow-2: 0 2px 6px rgba(16,20,30,.07), 0 8px 20px rgba(16,20,30,.06);
  --shadow-3: 0 10px 34px rgba(16,20,30,.14);
  --ring: 0 0 0 3px rgba(209,0,0,.16);
}

/* ── dark ────────────────────────────────────────────────────────────────── */

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:            #0c0d10;
  --surface:       #15171c;
  --surface-2:     #1a1d23;
  --surface-3:     #21252c;
  --surface-hover: #1f232a;

  --border:        #262a32;
  --border-strong: #363c46;

  --text:    #eceef2;
  --text-2:  #a0a8b6;
  --text-3:  #757d8c;
  --text-on-accent: #ffffff;

  --accent:       #ff453a;
  --accent-hover: #ff6961;
  --accent-soft:  #2a1010;
  --accent-line:  #4d1c1c;

  --ok:        #3ecf8e;   --ok-soft:     #0f2a1e;   --ok-line:     #1d5138;
  --warn:      #f0a92b;   --warn-soft:   #2d2109;   --warn-line:   #554112;
  --danger:    #ff6b5e;   --danger-soft: #2d1211;   --danger-line: #542120;
  --info:      #5aa2ff;   --info-soft:   #0f1e33;   --info-line:   #1e3c63;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 2px 8px rgba(0,0,0,.45), 0 10px 26px rgba(0,0,0,.35);
  --shadow-3: 0 12px 38px rgba(0,0,0,.6);
  --ring: 0 0 0 3px rgba(255,69,58,.26);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:#0c0d10; --surface:#15171c; --surface-2:#1a1d23; --surface-3:#21252c;
    --surface-hover:#1f232a; --border:#262a32; --border-strong:#363c46;
    --text:#eceef2; --text-2:#a0a8b6; --text-3:#757d8c;
    --accent:#ff453a; --accent-hover:#ff6961; --accent-soft:#2a1010; --accent-line:#4d1c1c;
    --ok:#3ecf8e; --ok-soft:#0f2a1e; --ok-line:#1d5138;
    --warn:#f0a92b; --warn-soft:#2d2109; --warn-line:#554112;
    --danger:#ff6b5e; --danger-soft:#2d1211; --danger-line:#542120;
    --info:#5aa2ff; --info-soft:#0f1e33; --info-line:#1e3c63;
    --shadow-1:0 1px 2px rgba(0,0,0,.4);
    --shadow-2:0 2px 8px rgba(0,0,0,.45), 0 10px 26px rgba(0,0,0,.35);
    --shadow-3:0 12px 38px rgba(0,0,0,.6);
    --ring:0 0 0 3px rgba(255,69,58,.26);
  }
}

/* ── base ────────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-14)/var(--lh) var(--ff);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Figures line up in columns. This is the single biggest readability win
   in a system where people scan quantities down a page. */
.num, td.num, th.num, .stat-v, .tnum, input[type="number"] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "cv05" 1;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: var(--lh-tight); letter-spacing: -.011em; }
h1 { font-size: var(--fs-20); }
h2 { font-size: var(--fs-16); }
h3 { font-size: var(--fs-14); }
p  { margin: 0 0 var(--s3); }
a  { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
code, kbd, .mono { font-family: var(--ff-mono); font-size: .92em; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }

.muted   { color: var(--text-2); }
.faint   { color: var(--text-3); }
.small   { font-size: var(--fs-12); }
.label   { font-size: var(--fs-11); font-weight: 600; letter-spacing: .06em;
           text-transform: uppercase; color: var(--text-3); }
.right   { text-align: right; }
.nowrap  { white-space: nowrap; }
.spacer  { flex: 1; }
.hide    { display: none !important; }

/* ── app shell ───────────────────────────────────────────────────────────── */

.app { display: grid; grid-template-columns: var(--nav-w) 1fr; min-height: 100vh; }

.nav {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}

.nav-brand {
  height: var(--topbar-h); display: flex; flex-direction: column;
  align-items: flex-start; justify-content: center; gap: 3px;
  padding: 0 var(--s4); border-bottom: 1px solid var(--border); flex: none;
}

/* The wordmark is black on one artwork and white on the other, so the sheet
   carries both and the theme decides which is in the flow. Swapping with CSS
   rather than script means it is already right on the first paint, with no
   flash of the wrong one. */
.brandmark { display: block; width: 118px; line-height: 0; }
.brandmark img { display: block; width: 100%; height: auto; }
.brandmark .bm-dark { display: none; }
:root[data-theme="dark"] .brandmark .bm-light { display: none; }
:root[data-theme="dark"] .brandmark .bm-dark  { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brandmark .bm-light { display: none; }
  :root:not([data-theme="light"]) .brandmark .bm-dark  { display: block; }
}
.nav-brand .mark {
  font-family: var(--ff-brand); font-size: var(--fs-13); letter-spacing: .02em;
  color: var(--text);
}
.nav-brand .mark b { color: var(--accent); }

.nav-group { padding: var(--s4) var(--s2) var(--s1); }
.nav-group .label { padding: 0 var(--s3) var(--s2); display: block; }

.nav-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3); margin: 1px var(--s1);
  border-radius: var(--r-sm); color: var(--text-2);
  font-size: var(--fs-13); font-weight: 500;
  cursor: pointer; border: 0; background: none; width: calc(100% - var(--s2));
  text-align: left; transition: background var(--speed), color var(--speed);
}
.nav-item:hover { background: var(--surface-hover); color: var(--text); }
.nav-item.on    { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.nav-item .ico  { width: 16px; height: 16px; flex: none; opacity: .85; }
.nav-item .count {
  margin-left: auto; font-size: var(--fs-11); font-weight: 600;
  background: var(--surface-3); color: var(--text-2);
  padding: 1px 7px; border-radius: var(--r-full);
}
.nav-item.on .count { background: var(--accent); color: var(--text-on-accent); }

.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: var(--topbar-h); flex: none;
  display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s6);
  background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { font-size: var(--fs-16); }
.topbar .sub { font-size: var(--fs-12); color: var(--text-3); }

.content { padding: var(--s6); max-width: 1400px; width: 100%; }
.content.wide { max-width: none; }

.page-head { margin-bottom: var(--s5); }
.page-head h1 { margin-bottom: var(--s1); }
.page-head p  { color: var(--text-2); margin: 0; font-size: var(--fs-13); }

/* ── cards ───────────────────────────────────────────────────────────────── */

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1);
}
.card + .card { margin-top: var(--s4); }
.card-head {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5); border-bottom: 1px solid var(--border);
}
.card-head h2 { flex: none; }
.card-head .sub { font-size: var(--fs-12); color: var(--text-3); }
.card-body { padding: var(--s5); }
.card-body.flush { padding: 0; }
.card-foot {
  padding: var(--s3) var(--s5); border-top: 1px solid var(--border);
  background: var(--surface-2); border-radius: 0 0 var(--r-lg) var(--r-lg);
  font-size: var(--fs-12); color: var(--text-2);
}

/* ── stat tiles ──────────────────────────────────────────────────────────── */

.stats { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--s4) var(--s5);
  box-shadow: var(--shadow-1); text-align: left;
  cursor: default; transition: border-color var(--speed), box-shadow var(--speed);
}
.stat.click { cursor: pointer; }
.stat.click:hover { border-color: var(--border-strong); box-shadow: var(--shadow-2); }
.stat.on { border-color: var(--accent); box-shadow: var(--ring); }
.stat-v { font-size: var(--fs-24); font-weight: 660; line-height: 1.1; letter-spacing: -.02em; }
.stat-k { font-size: var(--fs-12); color: var(--text-2); margin-top: var(--s1); }
.stat.is-danger .stat-v { color: var(--danger); }
.stat.is-warn   .stat-v { color: var(--warn); }
.stat.is-ok     .stat-v { color: var(--ok); }

/* ── tables ──────────────────────────────────────────────────────────────── */

.table-wrap { overflow-x: auto; }
table.t { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
table.t th {
  text-align: left; font-size: var(--fs-11); font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase; color: var(--text-3);
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border);
  background: var(--surface-2); position: sticky; top: 0; z-index: 1;
  white-space: nowrap;
}
table.t th.sortable { cursor: pointer; user-select: none; }
table.t th.sortable:hover { color: var(--text); }
table.t th .arrow { opacity: .4; margin-left: 3px; }
table.t td { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); vertical-align: top; }
table.t tbody tr:hover { background: var(--surface-hover); }
table.t tbody tr.click { cursor: pointer; }
table.t tbody tr:last-child td { border-bottom: 0; }
table.t .strong { font-weight: 600; color: var(--text); }
table.t .sub { font-size: var(--fs-12); color: var(--text-3); margin-top: 2px; }
table.t .sku { font-family: var(--ff-mono); font-size: var(--fs-12); font-weight: 600; }

/* ── badges ──────────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: var(--r-full);
  font-size: var(--fs-11); font-weight: 600; line-height: 1.6;
  border: 1px solid var(--border); background: var(--surface-3); color: var(--text-2);
  white-space: nowrap;
}
.badge.ok     { background: var(--ok-soft);     color: var(--ok);     border-color: var(--ok-line); }
.badge.warn   { background: var(--warn-soft);   color: var(--warn);   border-color: var(--warn-line); }
.badge.danger { background: var(--danger-soft); color: var(--danger); border-color: var(--danger-line); }
.badge.info   { background: var(--info-soft);   color: var(--info);   border-color: var(--info-line); }
.badge.accent { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-line); }
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

/* ── buttons ─────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  padding: 8px 14px; border-radius: var(--r-sm);
  font: 600 var(--fs-13)/1.2 var(--ff);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  cursor: pointer; white-space: nowrap;
  transition: background var(--speed), border-color var(--speed), transform var(--speed);
}
.btn:hover:not(:disabled) { background: var(--surface-hover); border-color: var(--text-3); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.btn.primary {
  background: var(--accent); border-color: var(--accent); color: var(--text-on-accent);
}
.btn.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn.ghost:hover:not(:disabled) { background: var(--surface-hover); color: var(--text); }
.btn.sm { padding: 5px 10px; font-size: var(--fs-12); }
.btn.icon { padding: 7px; }

.btn-row { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }

/* ── forms ───────────────────────────────────────────────────────────────── */

.field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.field > .label { margin: 0; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="search"], select, textarea {
  font: var(--fs-13)/1.4 var(--ff);
  padding: 8px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  width: 100%; min-width: 0;
  transition: border-color var(--speed), box-shadow var(--speed);
}
input:hover:not(:disabled), select:hover:not(:disabled) { border-color: var(--text-3); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
input::placeholder { color: var(--text-3); }
input:disabled, select:disabled { background: var(--surface-3); color: var(--text-3); cursor: not-allowed; }
select {
  appearance: none; padding-right: 30px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 8l3-3.5' stroke='%23878e9d' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
.check { display: inline-flex; align-items: center; gap: var(--s2); cursor: pointer; font-size: var(--fs-13); }
.check input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; margin: 0; }

.toolbar {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  padding: var(--s3) var(--s5); border-bottom: 1px solid var(--border);
  background: var(--surface-2); border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.toolbar .search { min-width: 200px; flex: 1; max-width: 340px; }

/* ── notices ─────────────────────────────────────────────────────────────── */

.notice {
  display: flex; gap: var(--s3); padding: var(--s3) var(--s4);
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface-2); font-size: var(--fs-13); color: var(--text-2);
  margin-bottom: var(--s4);
}
.notice b { color: var(--text); }
/* The tint and the rule carry the meaning. Body text stays at full
   readability — a whole sentence in accent colour reads as a link. */
.notice::before { content: ""; width: 3px; border-radius: 2px; flex: none; background: var(--border-strong); }
.notice.ok     { background: var(--ok-soft);     border-color: var(--ok-line); }
.notice.warn   { background: var(--warn-soft);   border-color: var(--warn-line); }
.notice.danger { background: var(--danger-soft); border-color: var(--danger-line); }
.notice.info   { background: var(--info-soft);   border-color: var(--info-line); }
.notice.ok::before     { background: var(--ok); }
.notice.warn::before   { background: var(--warn); }
.notice.danger::before { background: var(--danger); }
.notice.info::before   { background: var(--info); }
.notice.ok b     { color: var(--ok); }
.notice.warn b   { color: var(--warn); }
.notice.danger b { color: var(--danger); }
.notice.info b   { color: var(--info); }

.empty { padding: var(--s9) var(--s5); text-align: center; color: var(--text-3); }
.empty h3 { color: var(--text-2); margin-bottom: var(--s2); }

/* ── tabs ────────────────────────────────────────────────────────────────── */

.tabs { display: flex; gap: var(--s1); border-bottom: 1px solid var(--border); overflow-x: auto; }
.tab {
  padding: var(--s3) var(--s4); border: 0; background: none; cursor: pointer;
  font: 600 var(--fs-13)/1.2 var(--ff); color: var(--text-2);
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
}
.tab:hover { color: var(--text); }
.tab.on { color: var(--accent); border-bottom-color: var(--accent); }

/* ── misc ────────────────────────────────────────────────────────────────── */

.kv { display: grid; grid-template-columns: minmax(110px, auto) 1fr; gap: var(--s2) var(--s4); font-size: var(--fs-13); }
.kv dt { color: var(--text-3); font-size: var(--fs-12); }
.kv dd { margin: 0; color: var(--text); }

.bar { height: 6px; border-radius: var(--r-full); background: var(--surface-3); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: inherit; }

.theme-toggle { margin-left: auto; }

@keyframes spin { to { transform: rotate(360deg); } }
.spin { animation: spin .8s linear infinite; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .45 } }
.skeleton { background: var(--surface-3); border-radius: var(--r-sm); animation: pulse 1.4s ease-in-out infinite; }

/* ── mobile ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .nav {
    position: fixed; inset: 0 auto 0 0; width: min(84vw, var(--nav-w));
    z-index: 60; transform: translateX(-100%);
    transition: transform var(--speed) ease-out; box-shadow: var(--shadow-3);
  }
  .nav.open { transform: none; }
  .nav-scrim {
    position: fixed; inset: 0; background: rgba(0,0,0,.45);
    z-index: 50; opacity: 0; pointer-events: none; transition: opacity var(--speed);
  }
  .nav-scrim.on { opacity: 1; pointer-events: auto; }
  .topbar { padding: 0 var(--s4); }
  .content { padding: var(--s4); }
  .nav-burger { display: inline-flex !important; }

  /* dense tables become cards — each cell labelled by its column */
  table.t.stack thead { display: none; }
  table.t.stack, table.t.stack tbody, table.t.stack tr, table.t.stack td { display: block; width: 100%; }
  table.t.stack tr {
    border: 1px solid var(--border); border-radius: var(--r);
    margin-bottom: var(--s3); padding: var(--s2) var(--s3); background: var(--surface);
  }
  table.t.stack td {
    border: 0; padding: var(--s1) 0;
    display: grid; grid-template-columns: 88px 1fr; gap: var(--s3); align-items: baseline;
  }
  table.t.stack td::before {
    content: attr(data-label);
    font-size: var(--fs-11); font-weight: 600; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text-3); line-height: 1.7;
  }
  table.t.stack td.num { text-align: left; }
  table.t.stack td > * { grid-column: 2; justify-self: start; }
  table.t.stack td .sub { margin-top: 1px; }
  .stats { grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); }
  .stat-v { font-size: var(--fs-20); }
}
.nav-burger { display: none; }

@media (min-width: 901px) { .nav-scrim { display: none; } }

@media print {
  .nav, .topbar, .toolbar, .btn, .nav-scrim { display: none !important; }
  .app { display: block; }
  .content { padding: 0; max-width: none; }
  .card { border: 1px solid #ccc; box-shadow: none; break-inside: avoid; }
  body { background: #fff; color: #000; }
}

/* ════════════════════════════════════════════════════════════════════════════
   The printed purchase order

   A document that leaves the building, not a screenshot of a screen. It is
   built into the page only for the moment of printing and removed again, so
   nothing here can leak into the app: every rule is scoped to #poPrint, and
   the element is display:none until body carries .print-po.
   ════════════════════════════════════════════════════════════════════════════ */
#poPrint { display: none; }

.po-total {
  display: flex; align-items: baseline; gap: var(--s3);
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--line); font-size: var(--fs-13);
}
.po-total > span:first-child { color: var(--text-3); }
/* A note bound for the supplier reads differently from one that is ours. */
.po-card .po-note-out { color: var(--text); }
.po-card .po-note-out .flag { margin-right: var(--s2); }
.po-card .line .ln-note {
  font-size: var(--fs-11); color: var(--text-3); font-style: italic;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14ch;
}
.po-total b { margin-left: auto; font-variant-numeric: tabular-nums; }
.po-card .line .amt {
  font-variant-numeric: tabular-nums; text-align: right;
  min-width: 78px; color: var(--text-2);
}
.spec-list { padding-left: 1.3em; font-size: var(--fs-13); line-height: 1.75; }
.spec-list li { margin-bottom: 2px; }

@media print {
  body.print-po > *:not(#poPrint) { display: none !important; }
  body.print-po #poPrint { display: block; }
  @page { size: A4; margin: 14mm 14mm 16mm; }
}

/* Deliberately outside the media query as well, so the layout can be checked
   on screen by toggling the class rather than guessing at a preview. */
#poPrint {
  color: #000; background: #fff; font-size: 10.5pt; line-height: 1.45;
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
#poPrint .pp-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 20mm; padding-bottom: 5mm; border-bottom: 2px solid #000;
}
#poPrint .pp-brand { font-size: 17pt; font-weight: 800; letter-spacing: .02em; margin-bottom: 2mm; }
/* The mark, at a letterhead size. Height is left to the ratio so the artwork
   is never squashed, and print-color-adjust keeps the red red when the
   browser would otherwise drop background graphics. */
#poPrint .pp-logo {
  display: block; width: 42mm; height: auto; margin-bottom: 3mm;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
#poPrint .pp-from div { font-size: 9pt; color: #333; }
#poPrint .pp-title h1 { font-size: 15pt; font-weight: 700; margin: 0 0 3mm; text-align: right; }
#poPrint .pp-meta { border-collapse: collapse; margin-left: auto; font-size: 9.5pt; }
#poPrint .pp-meta th {
  text-align: left; font-weight: 500; color: #555; padding: 0 4mm 1mm 0; white-space: nowrap;
}
#poPrint .pp-meta td { text-align: right; font-weight: 600; padding: 0 0 1mm; }

#poPrint .pp-to { margin: 5mm 0 6mm; }
#poPrint .pp-lbl {
  font-size: 7.5pt; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: #666; margin-bottom: 1.5mm;
}
#poPrint .pp-sup { font-size: 12pt; font-weight: 700; }
#poPrint .pp-addr { white-space: pre-line; }
#poPrint .pp-terms { margin-top: 2mm; }

#poPrint .pp-lines { width: 100%; border-collapse: collapse; table-layout: fixed; }
#poPrint .pp-lines thead th {
  font-size: 7.5pt; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  text-align: left; color: #000; border-bottom: 1.5px solid #000; padding: 2mm 3mm 1.5mm 0;
}
#poPrint .pp-lines td { padding: 2mm 3mm 2mm 0; vertical-align: top; }
#poPrint tr.pp-line > td { border-bottom: .5px solid #ccc; }
#poPrint .pp-n { width: 7mm; color: #777; }
#poPrint .pp-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
#poPrint .pp-sku { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 9.5pt; }

/* The specification starts with its line and then flows over the page break
   like any other document. Two earlier attempts to hold it together both made
   it worse: keeping the whole block as a unit threw the entire specification
   onto a fresh page, and asking merely to keep the line row with the row after
   it did the same thing by another route — the row after it IS the whole
   specification, so the browser moved the lot and left page one empty. Nothing
   here may bind a row to a block that can be taller than a page. What is kept
   together is small and bounded: a single requirement never splits across two
   pages, and the specification heading never sits alone at the foot of one. */
/* A plain block between two tables, not a row inside one. A browser will not
   split a table row that would fit on a page of its own — it moves the whole
   row to the next page — so a long specification sitting in a row dragged the
   first page down with it and left it blank. Out here it fragments like the
   ordinary text it is. */
#poPrint .pp-spec { padding: 0 3mm 3mm 10mm; border-bottom: .5px solid #ccc; }
#poPrint .pp-spec + .pp-lines { margin-top: 3mm; }
/* The totals carry no column headings, so where they follow a specification
   the rule beneath that specification and the rule above the totals would
   print as two lines a millimetre apart. One of them is enough. */
#poPrint .pp-lines.pp-tail { margin-top: 0; }
#poPrint .pp-spec:has(+ .pp-lines.pp-tail) { border-bottom: none; }
#poPrint .pp-spec-h {
  font-size: 7.5pt; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: #000; background: #eee; padding: 1mm 2mm; margin: 0 0 2mm -2mm;
  break-after: avoid; page-break-after: avoid; break-inside: avoid;
}
/* Set the way it was typed: the author's own indents and dashes, nothing added.
   pre-wrap keeps the leading spaces and wraps a long requirement under itself
   instead of back to the margin. */
#poPrint .pp-spec-body {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9pt; line-height: 1.55;
}
#poPrint .pp-sr {
  white-space: pre-wrap; padding-left: 2.6em; text-indent: -2.6em;
  break-inside: avoid; page-break-inside: avoid;
}
#poPrint .pp-sr-gap { height: 1.55em; }
#poPrint .pp-spec-same { font-size: 9.5pt; color: #333; font-style: italic; }

#poPrint .pp-lines tr.pp-tot td {
  padding: 2.5mm 3mm 0 0; font-size: 10.5pt; font-weight: 700;
  border-top: 1.5px solid #000; text-align: right;
}
#poPrint .pp-lines tr.pp-tot { break-inside: avoid; page-break-inside: avoid; }
#poPrint .pp-aud td { font-size: 9pt; color: #444; text-align: right; padding-top: 1mm; }

#poPrint .pp-notes {
  margin-top: 6mm; white-space: pre-line;
  border: .75px solid #000; padding: 3mm 4mm; break-inside: avoid;
}
#poPrint .pp-linenote {
  font-size: 9.5pt; padding: 1.5mm 2mm; margin: 0 0 1.5mm -2mm;
  border-left: 2px solid #000; background: #f6f6f6;
}
#poPrint .pp-foot { margin-top: 8mm; break-inside: avoid; }
#poPrint .pp-foot p {
  font-size: 8.5pt; color: #333; line-height: 1.5;
  border-top: .5px solid #999; padding-top: 3mm; margin: 0;
}
#poPrint .pp-sign { display: flex; gap: 14mm; margin-top: 12mm; font-size: 9pt; }
#poPrint .pp-sign > div { flex: 1; }
#poPrint .pp-sign span {
  display: block; border-bottom: .5px solid #000; height: 10mm; margin-bottom: 1.5mm;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ════════════════════════════════════════════════════════════════════════════
   v2 — the layer that makes it feel like a product rather than a page
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  --nav-w: 248px;
  /* depth: a real surface has an edge catching light, not just a drop shadow */
  --lift: inset 0 1px 0 rgba(255,255,255,.7);
  --ease: cubic-bezier(.2,.7,.3,1);
}
:root[data-theme="dark"] { --lift: inset 0 1px 0 rgba(255,255,255,.045); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --lift: inset 0 1px 0 rgba(255,255,255,.045); }
}

.card, .stat { box-shadow: var(--shadow-1), var(--lift); }

/* ── nav: icons, sections, footer ────────────────────────────────────────── */

.nav-brand .who { margin-left: 1px; }
.nav-logo {
  width: 26px; height: 26px; border-radius: 7px; flex: none;
  background: var(--accent); color: #fff;
  display: grid; place-items: center;
  font: 800 11px/1 var(--ff); letter-spacing: -.03em;
  box-shadow: 0 1px 2px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.28);
}
.nav-brand .mark { font-size: var(--fs-13); line-height: 1.1; }
.nav-brand .who { font-size: var(--fs-11); color: var(--text-3); font-family: var(--ff); }

.nav-item .ico { width: 17px; height: 17px; flex: none; opacity: .75; stroke-width: 1.6; }
.nav-item.on .ico { opacity: 1; }
.nav-item { position: relative; }
.nav-item.on::before {
  content: ""; position: absolute; left: -5px; top: 7px; bottom: 7px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--accent);
}
.nav-foot { margin-top: auto; padding: var(--s3); border-top: 1px solid var(--border); }

.kbd {
  font: 600 10px/1 var(--ff-mono); color: var(--text-3);
  background: var(--surface-3); border: 1px solid var(--border);
  border-bottom-width: 2px; border-radius: 4px; padding: 3px 5px; white-space: nowrap;
}

/* ── command palette ─────────────────────────────────────────────────────── */

.cmdk-scrim {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: start center;
  padding-top: 12vh; background: rgba(10,12,16,.44);
  backdrop-filter: blur(3px); opacity: 0; pointer-events: none; transition: opacity 120ms;
}
.cmdk-scrim.on { opacity: 1; pointer-events: auto; }
.cmdk {
  width: min(640px, 92vw); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3); overflow: hidden;
  transform: translateY(-8px) scale(.985); transition: transform 160ms var(--ease);
}
.cmdk-scrim.on .cmdk { transform: none; }
.cmdk-in { display: flex; align-items: center; gap: var(--s3); padding: var(--s4) var(--s5);
           border-bottom: 1px solid var(--border); }
.cmdk-in input {
  border: 0; padding: 0; background: none; font-size: var(--fs-16); box-shadow: none !important;
}
.cmdk-list { max-height: 46vh; overflow-y: auto; padding: var(--s2); }
.cmdk-sec { padding: var(--s3) var(--s3) var(--s1); }
.cmdk-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3); border-radius: var(--r-sm); cursor: pointer; font-size: var(--fs-13);
}
.cmdk-row .ico { width: 16px; height: 16px; color: var(--text-3); flex: none; }
.cmdk-row .meta { margin-left: auto; font-size: var(--fs-12); color: var(--text-3); }
.cmdk-row.sel { background: var(--accent-soft); color: var(--accent); }
.cmdk-row.sel .ico, .cmdk-row.sel .meta { color: var(--accent); }
.cmdk-foot {
  display: flex; gap: var(--s4); padding: var(--s3) var(--s5);
  border-top: 1px solid var(--border); background: var(--surface-2);
  font-size: var(--fs-11); color: var(--text-3); align-items: center;
}

/* ── inline data: sparkline, coverage meter, delta ───────────────────────── */

.spark { display: block; overflow: visible; }
.spark path { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.spark .fill { stroke: none; }
.spark .tip { r: 2.6; }

.meter { display: flex; align-items: center; gap: var(--s2); }
.meter .track {
  position: relative; flex: 1; min-width: 54px; height: 6px;
  border-radius: var(--r-full); background: var(--surface-3); overflow: hidden;
}
.meter .track > i { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--text-3); }
.meter.ok     .track > i { background: var(--ok); }
.meter.warn   .track > i { background: var(--warn); }
.meter.danger .track > i { background: var(--danger); }
.meter .lead {
  position: absolute; top: -2px; bottom: -2px; width: 2px;
  background: var(--text); opacity: .5; border-radius: 1px;
}
.meter .v { font-size: var(--fs-12); color: var(--text-2); min-width: 42px; }

.delta { display: inline-flex; align-items: center; gap: 3px; font-size: var(--fs-12); font-weight: 600; }
.delta.up   { color: var(--danger); }   /* demand rising = a supply problem */
.delta.down { color: var(--ok); }
.delta.flat { color: var(--text-3); font-weight: 500; }

/* ── row actions reveal on hover ─────────────────────────────────────────── */

table.t tbody tr { transition: background 90ms var(--ease); }
.row-act { opacity: 0; transition: opacity 120ms var(--ease); display: flex; gap: 4px; justify-content: flex-end; }
tr:hover .row-act, tr:focus-within .row-act { opacity: 1; }
@media (hover: none) { .row-act { opacity: 1; } }

/* ── slide-over detail panel ─────────────────────────────────────────────── */

.sheet-scrim {
  position: fixed; inset: 0; z-index: 90; background: rgba(10,12,16,.4);
  opacity: 0; pointer-events: none; transition: opacity 160ms;
}
.sheet-scrim.on { opacity: 1; pointer-events: auto; }
.sheet {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 100;
  width: min(560px, 100vw); height: 100%; background: var(--surface);
  border-left: 1px solid var(--border); box-shadow: var(--shadow-3);
  display: flex; flex-direction: column; overflow: hidden;
  transform: translateX(100%); transition: transform 200ms var(--ease);
}
/* the small viewport unit, so a phone's address bar cannot push the foot of
   the sheet below the edge of the screen */
@supports (height: 100dvh) { .sheet { height: 100dvh; } }
.sheet.on { transform: none; }
/* The sheet's markup puts a plain wrapper div between the panel and its
   head/body, so the body's `flex:1` was being handed to a block that simply
   grew — which is why nothing ever scrolled and the foot of the panel sat
   below the bottom of the screen. The wrapper has to carry the column. */
#sheetInner {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0; overflow: hidden;
}
.sheet-head {
  padding: var(--s5); border-bottom: 1px solid var(--border);
  display: flex; align-items: flex-start; gap: var(--s3); flex-shrink: 0;
}
/* min-height:0 is what makes this scroll at all. A flex child defaults to
   min-height:auto, so the body refused to shrink below its content, the
   sheet grew past the bottom of the screen, and overflow-y had nothing to
   do — which is why the panel would not scroll and the page behind moved
   instead. overscroll-behavior stops the scroll handing off at the ends. */
.sheet-body {
  padding: var(--s5); flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.sheet-foot {
  padding: var(--s3) var(--s5); border-top: 1px solid var(--border);
  background: var(--surface-2); display: flex; gap: var(--s2); flex-shrink: 0;
}
@media (max-width: 640px) { .sheet { width: 100vw; border-left: 0; } }

/* the page behind a sheet is parked where it was, not scrolled to the top */
body.locked { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }

/* ── segmented control & filter chips ────────────────────────────────────── */

.seg { display: inline-flex; background: var(--surface-3); border-radius: var(--r-sm); padding: 2px; gap: 2px; }
.seg button {
  border: 0; background: none; cursor: pointer; border-radius: 5px;
  padding: 5px 11px; font: 600 var(--fs-12)/1.3 var(--ff); color: var(--text-2);
  transition: background 120ms var(--ease), color 120ms var(--ease);
}
.seg button:hover { color: var(--text); }
.seg button.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow-1); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 10px; border-radius: var(--r-full);
  border: 1px solid var(--accent-line); background: var(--accent-soft); color: var(--accent);
  font-size: var(--fs-12); font-weight: 600;
}
.chip button { border: 0; background: none; color: inherit; cursor: pointer; padding: 0 2px; line-height: 1; opacity: .7; }
.chip button:hover { opacity: 1; }

/* ── toast ───────────────────────────────────────────────────────────────── */

.toasts { position: fixed; bottom: var(--s5); right: var(--s5); z-index: 300;
          display: flex; flex-direction: column; gap: var(--s2); }
.toast {
  display: flex; align-items: center; gap: var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); padding: var(--s3) var(--s4);
  box-shadow: var(--shadow-2), var(--lift); font-size: var(--fs-13);
  animation: toast-in 220ms var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(8px) scale(.97); } }
.toast .ico { width: 16px; height: 16px; flex: none; }
.toast.ok .ico { color: var(--ok); }

/* ── stat tile with its own trend ────────────────────────────────────────── */

.stat { position: relative; overflow: hidden; }
.stat .spark { position: absolute; right: 0; bottom: 0; left: 0; height: 30px; opacity: .5; }
.stat-top { display: flex; align-items: baseline; gap: var(--s2); }
.stat-rel { position: relative; z-index: 1; }

@media (max-width: 900px) { .toasts { left: var(--s4); right: var(--s4); bottom: var(--s4); } }

/* ── status is never colour alone ─────────────────────────────────────────
   Red, amber and green are precisely the axis red-green colour blindness
   collapses: our "order soon" amber and "out" red measure ΔE 1.2 apart under
   deuteranopia — indistinguishable. No hue at this lightness fixes that, so
   each state carries its own GLYPH and its own weight of ink. The badge then
   reads in greyscale, printed, and on a sunlit phone. */

.badge .gi { width: 12px; height: 12px; flex: none; stroke-width: 2.2; }
.badge.ok     { font-weight: 600; }
.badge.warn   { font-weight: 650; }
.badge.danger { font-weight: 700; }
.badge.danger { border-width: 1px; box-shadow: inset 0 0 0 1px var(--danger-line); }

/* the tile's trend line sits in a band beneath the text, never through it */
.stat { padding: var(--s4) var(--s5) var(--s7); }
.stat .spark { height: 24px; opacity: .4; }
.stat .spark path { stroke-width: 1.8; }

/* the topbar subtitle is a desk-screen luxury; on a phone the title wins */
@media (max-width: 560px) {
  .topbar .sub { display: none; }
  .topbar h1 { font-size: var(--fs-14); }
}


/* ── stock: the supply plan that opens under a row ─────────────────────────
   A SKU opens in place and walks its balance forward month by month. The
   current month is lifted, the month it runs dry is marked, and the closing
   balance is the row people actually read, so it carries the weight. */
.stock-tbl .chev{display:inline-block;width:12px;color:var(--text-3);font-size:11px;
  transition:color var(--speed)}
.tl-trigger.open .chev{color:var(--accent)}
.tl-trigger.open>td{background:var(--surface-2)}
.tl-row>td{padding:0 0 var(--s4);background:var(--surface-2);border-top:0}
.tl{padding:var(--s4) var(--s4) var(--s1)}
.tl-head{font-size:var(--fs-13);color:var(--text);margin-bottom:var(--s3)}
.tl-head b{font-family:var(--ff-mono);color:var(--accent)}
.tl-meta{display:block;font-family:var(--ff-mono);font-size:var(--fs-11);
  color:var(--text-3);margin-top:3px}
.tl-tbl{width:100%;border-collapse:collapse;min-width:780px;font-size:var(--fs-12);
  font-variant-numeric:tabular-nums}
.tl-tbl th,.tl-tbl td{padding:5px 7px;text-align:right;white-space:nowrap}
.tl-tbl thead th{color:var(--text-3);font-size:var(--fs-11);font-weight:600;
  border-bottom:1px solid var(--border)}
.tl-tbl thead th:first-child,.tl-tbl tbody th{width:104px;text-align:left;
  color:var(--text-3);font-size:var(--fs-11);font-weight:600}
.tl-tbl tbody th{border-bottom:1px solid var(--border)}
.tl-tbl tbody td{border-bottom:1px solid var(--border);color:var(--text-2)}
.tl-tbl tr:last-child td,.tl-tbl tr:last-child th{border-bottom:0}
.tl-tbl .tl-now{background:var(--surface-3)}
.tl-tbl th.tl-now{color:var(--text)}
.tl-tbl .tl-out{background:color-mix(in srgb,var(--danger) 16%,transparent)}
.tl-tbl tr.tl-eom td{font-weight:700;color:var(--text)}
.tl-tbl tr.tl-eom th{color:var(--text)}
.tl-foot{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  font-size:var(--fs-12);color:var(--text-3);padding:var(--s3) 2px 2px;line-height:1.5}
.tl-foot b{color:var(--text)}
.tl-foot .btn{margin-left:auto}



/* ── dimensions: the grid, and the alternatives panel ──────────────────────
   The alternatives panel is the reason this screen exists: it answers which
   already-tooled canister and side rails a new cover could be built from. */
.dim-group{margin-bottom:var(--s7)}
.dim-grid{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}
.dim-card{overflow:hidden;display:flex;flex-direction:column}
.dim-img{cursor:pointer;background:var(--surface-2);border-bottom:1px solid var(--border)}
.dim-img img{display:block;width:100%;aspect-ratio:4/3;object-fit:contain}
.dim-none{aspect-ratio:4/3;display:grid;place-items:center;color:var(--text-3);font-size:var(--fs-12)}
.dim-body{padding:var(--s3) var(--s4);display:flex;flex-direction:column;gap:2px;flex:1}
.dim-acts{display:flex;align-items:center;gap:4px;margin-top:var(--s3);flex-wrap:wrap}

.alt-scrim{position:fixed;inset:0;z-index:70;display:none;align-items:center;justify-content:center;
  padding:var(--s5);background:color-mix(in srgb,#000 55%,transparent);backdrop-filter:blur(2px)}
.alt-scrim.on{display:flex}
.alt-box{width:min(860px,96vw);max-height:90vh;overflow:auto;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-3)}
.alt-head{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s5);
  border-bottom:1px solid var(--border)}
.alt-head h3{margin:0}
.alt-tol{display:flex;align-items:center;gap:var(--s3);padding:var(--s4) var(--s5);
  border-bottom:1px solid var(--border);background:var(--surface-2)}
.alt-tol input[type=range]{flex:1;max-width:280px;accent-color:var(--accent)}
.alt-tol .tolval{font-weight:700;min-width:64px}
.alt-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);padding:var(--s5)}
.alt-col h4{margin:0 0 var(--s3);font-size:var(--fs-11);letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-3)}
.alt-row{display:flex;justify-content:space-between;gap:var(--s3);padding:7px 9px;
  border:1px solid var(--border);border-radius:var(--r);margin-bottom:5px;font-size:var(--fs-13)}
.alt-row.exact{border-color:var(--ok);background:color-mix(in srgb,var(--ok) 10%,transparent)}
.alt-row .ad{color:var(--text-3);white-space:nowrap}
.alt-none{color:var(--text-3);font-size:var(--fs-12);padding:7px 0}
.alt-build{padding:0 var(--s5) var(--s5)}
.alt-build h4{margin:0 0 var(--s3);font-size:var(--fs-11);letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-3)}
.alt-pick{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;font-size:var(--fs-13)}
.alt-pick select{width:auto;min-width:150px}

/* ── lightbox ─────────────────────────────────────────────────────────────*/
.lb{position:fixed;inset:0;z-index:80;display:flex;flex-direction:column;
  background:color-mix(in srgb,#000 82%,transparent)}
.lb-bar{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4);
  background:var(--surface);border-bottom:1px solid var(--border)}
.lb-cap{font-weight:600;font-size:var(--fs-13)}
.lb-stage{flex:1;overflow:auto;display:grid;place-items:center;padding:var(--s5)}
.lb-stage img{max-width:100%;max-height:100%;border-radius:var(--r);background:var(--surface);
  cursor:zoom-in}
.lb.zoomed .lb-stage{place-items:start}
.lb.zoomed .lb-stage img{max-width:none;max-height:none;cursor:zoom-out}

@media (max-width:900px){
  .alt-grid{grid-template-columns:1fr;gap:var(--s4)}
  .alt-pick select{width:100%}
  .alt-pick{flex-direction:column;align-items:stretch}
}


/* ── setup sheet: chips for the kit relationship, and a two-up field row ───*/
.grid-2{display:grid;gap:var(--s4);grid-template-columns:1fr 1fr}
.chip-pick{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--s2);
  max-height:190px;overflow:auto;padding:2px}
.chip-pick .chip{cursor:pointer;user-select:none;font-family:var(--ff-mono);
  font-size:var(--fs-11);border:1px solid var(--border);border-radius:999px;
  padding:4px 10px;background:var(--surface);transition:background var(--speed),
  border-color var(--speed),color var(--speed)}
.chip-pick .chip input{display:none}
.chip-pick .chip.on{background:var(--accent);border-color:var(--accent);color:var(--text-on-accent)}
.check{display:flex;align-items:flex-start;gap:var(--s3);font-size:var(--fs-13);cursor:pointer}
.check input{margin-top:2px;flex:none}
@media (max-width:640px){ .grid-2{grid-template-columns:1fr} }


/* ── vehicles: what bolts on to what ──────────────────────────────────────*/
.veh-row{padding:var(--s3) var(--s4);border-bottom:1px solid var(--border);
  display:flex;flex-direction:column;gap:5px}
.veh-row:last-child{border-bottom:0}
.veh-row-top{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap}
.veh-row-fit{display:flex;flex-wrap:wrap;gap:4px}
.veh-var{border:1px solid var(--border);border-radius:var(--r);padding:var(--s3);
  background:var(--surface-2);display:flex;flex-direction:column;gap:var(--s2)}
.veh-var-top{display:grid;grid-template-columns:1fr 1.6fr 34px;gap:var(--s2)}
.veh-fit{display:flex;flex-direction:column;gap:5px}
.veh-fit-row{display:grid;grid-template-columns:1.4fr .9fr 1.4fr 34px;gap:var(--s2)}
@media (max-width:640px){
  .veh-var-top,.veh-fit-row{grid-template-columns:1fr;gap:5px}
}


/* ── the stockist log: follow-ups and a dated note history ────────────────*/
.log-wrap{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);margin-top:var(--s6)}
.log-col{display:flex;flex-direction:column;gap:var(--s2);min-width:0}
.task-list{display:flex;flex-direction:column;gap:5px}
.task{display:grid;grid-template-columns:20px 1fr 140px 30px;gap:6px;align-items:center}
.task.done .task-text{text-decoration:line-through;color:var(--text-3)}
.task-due.over{border-color:var(--danger);color:var(--danger)}
.task-new{display:grid;grid-template-columns:1fr 140px auto;gap:6px;margin-top:var(--s2)}
.note-new{display:flex;flex-direction:column;gap:6px;align-items:flex-start}
.note-new .btn{align-self:flex-end}
.note-list{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s2);
  max-height:280px;overflow:auto}
.note{border:1px solid var(--border);border-radius:var(--r);padding:var(--s2) var(--s3);
  background:var(--surface-2);font-size:var(--fs-13)}
.note-top{display:flex;align-items:center;gap:var(--s2)}
.stat.click{cursor:pointer;text-align:left;font:inherit;width:100%}
.stat.click.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
@media (max-width:900px){
  .log-wrap{grid-template-columns:1fr}
  .task,.task-new{grid-template-columns:20px 1fr;grid-auto-rows:auto}
  .task-due,.task-new input[type=date]{grid-column:2}
}


/* ── sortable table headers ───────────────────────────────────────────────*/
th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
th.sortable:hover{color:var(--text)}
th.sortable.on{color:var(--accent)}


/* ── purchase orders grouped by the day they land ─────────────────────────*/
.po-group{margin-bottom:var(--s6)}
.po-date{font-size:var(--fs-12);font-weight:600;letter-spacing:.02em;color:var(--text-2);
  padding:0 0 var(--s2);margin-bottom:var(--s3);border-bottom:1px solid var(--border)}
.po-date.late{color:var(--danger)}
.po-done{margin-top:var(--s6)}
.po-done summary{cursor:pointer;font-size:var(--fs-13);color:var(--text-3);
  padding:var(--s2) 0;user-select:none}
.po-done summary:hover{color:var(--text)}
.seg.step{display:inline-flex}
.seg.step button{padding:3px 9px;font-size:var(--fs-11)}


/* ── project attachments ──────────────────────────────────────────────────*/
.proj-files{display:flex;flex-wrap:wrap;gap:5px;margin-top:var(--s3)}
.file-chip{display:inline-flex;align-items:center;border:1px solid var(--border);
  border-radius:999px;overflow:hidden;background:var(--surface-2);font-size:var(--fs-11)}
.file-open{border:0;background:none;padding:4px 4px 4px 10px;cursor:pointer;color:var(--text-2);
  font:inherit;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-open:hover{color:var(--accent);text-decoration:underline}
.file-del{border:0;background:none;padding:4px 9px 4px 4px;cursor:pointer;color:var(--text-3);font:inherit}
.file-del:hover{color:var(--danger)}


/* ── website roadmap priorities ───────────────────────────────────────────*/
.prio{font-family:var(--ff-mono);font-size:var(--fs-11);font-weight:700;
  padding:2px 7px;border-radius:var(--r-sm);border:1px solid var(--border)}
.prio-P1{color:var(--danger);border-color:color-mix(in srgb,var(--danger) 40%,transparent)}
.prio-P2{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 40%,transparent)}
.prio-P3{color:var(--text-3)}


/* ── competitors: what moved since the last check ─────────────────────────*/
.chg-grid{display:grid;gap:var(--s5);grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.chg-col h4{margin:0 0 var(--s2);font-size:var(--fs-11);letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-3)}
.chg-col h4.bad{color:var(--danger)}
.chg-row{display:flex;justify-content:space-between;gap:var(--s3);align-items:baseline;
  font-size:var(--fs-12);padding:3px 0;border-bottom:1px solid var(--border)}
.chg-row:last-child{border-bottom:0}
.badge.click:hover{border-color:var(--accent);color:var(--accent)}


/* the scroller only works if it is allowed to be narrower than its content */
.chart-wrap{overflow-x:auto;overflow-y:hidden;max-width:100%;min-width:0;
  padding-right:2px;-webkit-overflow-scrolling:touch}


@media (max-width:900px){
  /* a long "cheapest X $1,234" was pushing the card wider than the phone */
  .card-head{flex-wrap:wrap;row-gap:4px}
  .card-head .sub{min-width:0;overflow-wrap:anywhere}
  .chg-grid{grid-template-columns:1fr}
}


/* ── distributor pack: editable, but it still has to read as a price sheet ──
   Making every cell a bordered input turned the pack into a form. These cells
   look like text and only become a field under the cursor. */
#packBody .pk-edit{
  border:1px solid transparent;background:transparent;border-radius:var(--r-sm);
  padding:3px 6px;margin:-3px -6px;width:calc(100% + 12px);
  font:inherit;color:inherit;letter-spacing:inherit}
#packBody .pk-edit.num{text-align:right;font-variant-numeric:tabular-nums}
#packBody .pk-edit.muted{color:var(--text-3);font-size:var(--fs-12)}
#packBody .pk-edit::placeholder{color:var(--text-3);opacity:.55}
#packBody .pk-row:hover .pk-edit{border-color:var(--border)}
#packBody .pk-edit:hover{border-color:var(--border-strong)}
#packBody .pk-edit:focus{border-color:var(--accent);background:var(--surface);
  outline:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 16%,transparent)}
/* the number spinners crowd a narrow cell */
#packBody .pk-edit[type=number]::-webkit-outer-spin-button,
#packBody .pk-edit[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* the two per-distributor figures keep the boxes they always had */
#packBody .pk-num{width:78px;text-align:right;font-variant-numeric:tabular-nums}

#packBody .pk-cat td{background:var(--surface-2);font-weight:650}
#packBody .pk-add{border:0;background:none;cursor:pointer;font:inherit;
  font-size:var(--fs-11);font-weight:600;color:var(--text-3);margin-left:10px;
  padding:2px 6px;border-radius:var(--r-sm);opacity:0;transition:opacity var(--speed)}
#packBody .pk-cat:hover .pk-add,#packBody .pk-add:focus{opacity:1}
#packBody .pk-add:hover{color:var(--accent);background:var(--surface)}

/* row actions stay out of the way until you are on the row */
#packBody .pk-acts{white-space:nowrap;text-align:right;width:74px}
#packBody .pk-acts button{border:0;background:none;cursor:pointer;color:var(--text-3);
  font:inherit;font-size:var(--fs-12);line-height:1;padding:3px 4px;border-radius:var(--r-sm);
  opacity:0;transition:opacity var(--speed),color var(--speed)}
#packBody .pk-row:hover .pk-acts button,#packBody .pk-acts button:focus{opacity:1}
#packBody .pk-acts button:hover{color:var(--text);background:var(--surface-2)}
#packBody .pk-acts button[data-del]:hover{color:var(--danger)}

/* on a touch screen there is no hover, so nothing may be hidden behind it */
@media (hover:none){
  #packBody .pk-edit{border-color:var(--border)}
  #packBody .pk-add,#packBody .pk-acts button{opacity:1}
}

.warn-txt{color:var(--warn)}

/* ════════════════════════════════════════════════════════════════════════════
   REFINEMENT LAYER — density, measure and card anatomy
   ────────────────────────────────────────────────────────────────────────────
   The tokens were fine; the component layer was not. Three faults ran through
   every screen and are corrected here rather than screen by screen:

   1. `auto-fit` + `1fr` lets a single card stretch the full viewport, so one
      purchase order became a 1400px box holding two lines of text.
   2. Cards in a row did not share a height, so footers floated at different
      levels and short cards left a ragged hole.
   3. A table inside a card inherits the card's width, which threw a SKU to the
      far left and its quantity to the far right — related values a foot apart.

   The through-line: constrain the measure, group what belongs together, and
   spend vertical space on information rather than padding.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── measure ──────────────────────────────────────────────────────────────
   A card grid fills left to right and stops at a readable width. Tracks are
   capped so the last card in a row cannot stretch to fill the gap. */
.split{
  display:grid; gap:var(--s4);
  grid-template-columns:repeat(auto-fill,minmax(324px,384px));
  justify-content:start; align-items:stretch;
}
.split.wide{grid-template-columns:repeat(auto-fill,minmax(400px,520px))}
@media (max-width:760px){ .split,.split.wide{grid-template-columns:1fr} }

.content{max-width:1320px}

/* ── card ─────────────────────────────────────────────────────────────────
   One anatomy everywhere: a head that stays on one line, a body that grows,
   a foot pinned to the bottom so a row of cards lines up. */
.card{display:flex; flex-direction:column; min-width:0; overflow:hidden}
.card-head{
  padding:var(--s3) var(--s4); gap:var(--s2);
  min-height:44px; flex:none;
}
.card-head h2{
  font-size:var(--fs-14); font-weight:640; letter-spacing:-.01em;
  line-height:1.3; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.card-head .sub{
  font-size:var(--fs-12); color:var(--text-3); white-space:nowrap; flex:none;
  font-variant-numeric:tabular-nums;
}
.card-body{padding:var(--s4); flex:1 1 auto; min-width:0}
.card-body.flush{padding:0}
.card-foot{
  margin-top:auto; flex:none; padding:var(--s2) var(--s4);
  display:flex; align-items:center; gap:var(--s2); min-height:40px;
}

/* ── KPI strip ────────────────────────────────────────────────────────────
   These are a glance, not a feature. Label first, figure under it, and the
   whole strip the height of one comfortable row. */
.stats{
  gap:var(--s2);
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  margin-bottom:var(--s4);
}
.stat{
  padding:var(--s3) var(--s4); border-radius:var(--r);
  box-shadow:none; display:flex; flex-direction:column-reverse; gap:2px;
}
.stat-v{
  font-size:var(--fs-20); font-weight:650; letter-spacing:-.02em;
  font-variant-numeric:tabular-nums; line-height:1.15;
}
.stat-k{
  font-size:var(--fs-11); font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; color:var(--text-3); line-height:1.3;
}
.stat.is-danger .stat-v{color:var(--danger)}
.stat.is-warn   .stat-v{color:var(--warn)}
.stat.is-ok     .stat-v{color:var(--ok)}
.stat.click{cursor:pointer; transition:border-color var(--speed), background var(--speed)}
.stat.click:hover{border-color:var(--border-strong); background:var(--surface-2)}
.stat.click.on{border-color:var(--accent); background:var(--accent-soft)}
.stat.click.on .stat-k{color:var(--accent)}

/* ── a line list inside a card ────────────────────────────────────────────
   Three columns sized to their content, so a SKU, what it is and how many
   read as one thing instead of three things at opposite ends of a card. */
.lines{display:flex; flex-direction:column}
.line{
  display:grid; grid-template-columns:auto 1fr auto; gap:var(--s3);
  align-items:baseline; padding:6px 0; border-bottom:1px solid var(--border);
  font-size:var(--fs-13);
}
.line:last-child{border-bottom:0}
.line .sku{
  font-family:var(--ff-mono); font-size:var(--fs-11); font-weight:600;
  color:var(--text-2); white-space:nowrap;
}
.line .what{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text)}
.line .qty{font-variant-numeric:tabular-nums; font-weight:620; white-space:nowrap}

/* ── group heading above a set of cards ───────────────────────────────────*/
.group-head{
  display:flex; align-items:baseline; gap:var(--s2);
  margin:var(--s6) 0 var(--s3); padding-bottom:var(--s2);
  border-bottom:1px solid var(--border);
}
.group-head:first-child{margin-top:0}
.group-head .t{
  font-size:var(--fs-12); font-weight:650; letter-spacing:.01em; color:var(--text);
}
.group-head .m{font-size:var(--fs-12); color:var(--text-3); font-variant-numeric:tabular-nums}
.group-head.late .t,.group-head.late .m{color:var(--danger)}
.group-head .count{margin-left:auto; font-size:var(--fs-11); color:var(--text-3)}

/* ── status chip ──────────────────────────────────────────────────────────
   Tinted, ringed, quiet. It labels a row; it is not the point of the row. */
.badge{
  padding:1px 8px; font-size:var(--fs-11); font-weight:620; line-height:1.7;
  letter-spacing:.01em; white-space:nowrap; flex:none;
}
.badge .gi{width:11px; height:11px}

/* ── segmented control ────────────────────────────────────────────────────*/
.seg{background:var(--surface-3); border-radius:var(--r-sm); padding:2px; gap:2px}
.seg button{
  border-radius:calc(var(--r-sm) - 1px); font-size:var(--fs-12); font-weight:600;
  padding:4px 10px; color:var(--text-2); border:0; background:none; cursor:pointer;
  transition:background var(--speed), color var(--speed);
}
.seg button:hover{color:var(--text)}
.seg button.on{background:var(--surface); color:var(--text); box-shadow:var(--shadow-1)}
.seg.step{margin-left:auto}
.seg.step button{padding:3px 9px; font-size:var(--fs-11)}

/* ── triage row ───────────────────────────────────────────────────────────
   Was a bordered row inside a bordered card, with the chevron marooned at the
   far right of a 1500px line. Now one quiet list, and the whole row is the
   target. */
.triage{gap:0}
.tr-row{
  display:grid; grid-template-columns:3px 1fr auto; gap:var(--s3);
  align-items:center; padding:var(--s3) var(--s4);
  border:0; border-bottom:1px solid var(--border); border-radius:0;
  background:none; box-shadow:none; cursor:pointer;
  transition:background var(--speed);
}
.tr-row:last-child{border-bottom:0}
.tr-row:hover{background:var(--surface-2)}
.tr-row .grip{width:3px; height:26px; border-radius:2px; align-self:center}
.tr-row .title{font-size:var(--fs-13); font-weight:620; letter-spacing:-.005em}
.tr-row .body{font-size:var(--fs-12); color:var(--text-2); margin-top:1px}
.tr-row .go{color:var(--text-3); font-size:var(--fs-14); flex:none; transition:color var(--speed), transform var(--speed)}
.tr-row:hover .go{color:var(--accent); transform:translateX(2px)}

/* ── toolbar ──────────────────────────────────────────────────────────────
   A page toolbar is chrome. It sits on the page, not in a raised card, and
   the primary action is the only thing wearing the accent. */
.page-bar{
  display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap;
  margin-bottom:var(--s4);
}
.page-bar .search{flex:1 1 260px; max-width:420px}
.page-bar .spacer{flex:1}

/* ── tables ───────────────────────────────────────────────────────────────*/
table.t th{padding:var(--s2) var(--s4); font-size:var(--fs-11)}
table.t td{padding:var(--s3) var(--s4); vertical-align:middle}
table.t tbody tr{transition:background var(--speed)}
table.t tbody tr.click:hover{background:var(--surface-2)}
.num{font-variant-numeric:tabular-nums}

/* ── focus, consistently ──────────────────────────────────────────────────*/
:where(button,a,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r-sm);
}

/* ── purchase order card ──────────────────────────────────────────────────*/
.po-card .card-head h2{font-family:var(--ff-mono); font-size:var(--fs-13); letter-spacing:0; cursor:pointer}
.po-card .card-head h2:hover{color:var(--accent)}
.po-meta{
  display:flex; align-items:baseline; gap:var(--s2); margin-bottom:var(--s2);
  font-size:var(--fs-12); color:var(--text-2);
}
.po-meta .who{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.po-meta .num{margin-left:auto; color:var(--text-3); white-space:nowrap}
.po-note{
  margin-top:var(--s3); padding-top:var(--s2); border-top:1px solid var(--border);
  font-size:var(--fs-12); color:var(--text-3); line-height:1.5;
}
.po-done{margin-top:var(--s7)}
.po-done summary{
  cursor:pointer; user-select:none; font-size:var(--fs-12); font-weight:600;
  color:var(--text-3); padding:var(--s2) 0;
}
.po-done summary:hover{color:var(--text)}

/* ── home ─────────────────────────────────────────────────────────────────*/
.home-today{max-width:760px}

/* ── KPI strip, second pass ───────────────────────────────────────────────
   Five separate boxes with shouty uppercase labels wrapped onto two lines and
   left the row ragged. One bar, divided — always level, never wraps, and it
   reads as a summary of the screen rather than five competing cards. */
.stats{
  display:flex; flex-wrap:wrap; gap:0; margin-bottom:var(--s5);
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r);
  overflow:hidden;
}
.stats > *{
  flex:1 1 0; min-width:132px;
  border:0; border-left:1px solid var(--border); border-radius:0;
  background:none; box-shadow:none;
  padding:var(--s3) var(--s4);
  display:flex; flex-direction:column-reverse; gap:1px; text-align:left;
}
.stats > *:first-child{border-left:0}
.stats .stat-k{
  font-size:var(--fs-12); font-weight:500; letter-spacing:0; text-transform:none;
  color:var(--text-3); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.stats .stat-v{font-size:var(--fs-20); line-height:1.2}
.stats .stat.click:hover{background:var(--surface-2)}
.stats .stat.click.on{background:var(--accent-soft); box-shadow:inset 0 -2px 0 var(--accent)}
@media (max-width:640px){ .stats > *{flex:1 1 42%; min-width:0} }

/* ── card grids, second pass ──────────────────────────────────────────────
   Cards size to their content. Stretching a two-line order to match a
   five-line one just manufactures an empty box. */
.split{align-items:start; margin-bottom:var(--s5)}
.split:last-child{margin-bottom:0}
.group-head{margin-top:var(--s7)}

/* ── page toolbar, second pass ────────────────────────────────────────────
   Search and the action belong together at the top-left, where the eye
   starts — not at opposite ends of a 1300px bar. */
.page-bar{gap:var(--s2); margin-bottom:var(--s5)}
.page-bar .search{flex:0 1 360px}
.page-bar .spacer{flex:1 1 auto}

/* ── group heading, second pass ───────────────────────────────────────────
   A full-width rule directly under a left-aligned card drew a hard line
   across empty space and made the heading feel stuck to the card above it.
   The date carries itself; it does not need a border to be a heading. */
.group-head{
  border-bottom:0; padding-bottom:0;
  margin:var(--s8) 0 var(--s3); align-items:baseline;
}
.group-head:first-child{margin-top:0}
.group-head .t{font-size:var(--fs-13); font-weight:650}
.group-head .m{font-size:var(--fs-12)}
.group-head .count{font-size:var(--fs-11); color:var(--text-3)}

/* ── stock table ──────────────────────────────────────────────────────────
   Ten columns in 1300px is 130px each, which is not enough for a product
   name or a supplier. Fixed widths, one line per value, and anything longer
   truncates with the whole string on the tooltip. */
.stock-tbl{table-layout:fixed; width:100%}
.stock-tbl > thead > tr > th,.stock-tbl > tbody > tr > td{padding:var(--s2) var(--s3); vertical-align:middle; overflow:hidden}
.stock-tbl > thead > tr > th{white-space:nowrap; text-overflow:ellipsis; letter-spacing:.02em}
.stock-tbl .c-date{white-space:nowrap}
.stock-tbl .c-status{overflow:visible}
/* With table-layout:fixed the widths are taken from the FIRST row — the
   header — so they have to be declared there, not on the body cells. */
.stock-tbl > thead > tr > th:nth-child(1){width:auto}      /* SKU / product, takes the rest */
/* Measured, not guessed: each column is wide enough for its own header and
   for the longest value it carries. */
.stock-tbl > thead > tr > th:nth-child(2){width:118px}     /* demand sparkline (96 + pad) */
.stock-tbl > thead > tr > th:nth-child(3){width:78px}      /* on hand — what is on the shelf */
.stock-tbl > thead > tr > th:nth-child(4){width:84px}      /* available — less commitments   */
.stock-tbl > thead > tr > th:nth-child(5){width:88px}      /* on order                    */
.stock-tbl > thead > tr > th:nth-child(6){width:92px}      /* arriving                    */
.stock-tbl > thead > tr > th:nth-child(7){width:58px}      /* per week                    */
.stock-tbl > thead > tr > th:nth-child(8){width:100px}     /* runs out                    */
.stock-tbl > thead > tr > th:nth-child(9){width:92px}      /* order by                    */
.stock-tbl > thead > tr > th:nth-child(10){width:60px}      /* order qty                   */
.stock-tbl > thead > tr > th:nth-child(11){width:148px}    /* status — must not clip      */
.stock-tbl .c-spark{padding-left:var(--s2); padding-right:var(--s2)}
.stock-tbl .sku{white-space:nowrap}
.stock-tbl .c-sku{min-width:0}

.stock-tbl .sku-top{display:flex; align-items:center; gap:5px; min-width:0}
.stock-tbl .sku-name{
  font-size:var(--fs-13); font-weight:560; color:var(--text);
  margin-top:1px; padding-left:17px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.stock-tbl .sub{font-size:var(--fs-11); line-height:1.35; margin-top:1px}
.stock-tbl td{font-size:var(--fs-12)}
.stock-tbl .spark{display:block}
.flag{
  font-size:var(--fs-11); font-weight:600; color:var(--text-3);
  background:var(--surface-3); border-radius:var(--r-sm); padding:0 5px; white-space:nowrap;
}
.flag.warn{color:var(--warn); background:var(--warn-soft)}
/* A SKU the hub counts itself, and the two directions a ledger line can go. */
.flag.ok{color:var(--ok); background:var(--ok-soft)}
.cnt-row b.pos{color:var(--ok)}
.cnt-row b.faint{color:var(--text-3);font-weight:500}
.t td.neg{color:var(--danger)}
.danger-txt{color:var(--danger)}
.ok-txt{color:var(--ok)}

/* the chip must never be the thing that widens the table */
.stock-tbl .badge{max-width:100%; overflow:hidden; text-overflow:ellipsis}

@media (max-width:900px){
  .stock-tbl{table-layout:auto}
  .stock-tbl .c-sku,.stock-tbl .c-spark,.stock-tbl .c-n,
  .stock-tbl .c-date,.stock-tbl .c-status{width:auto; min-width:0}
  .stock-tbl .sku-name{padding-left:0; white-space:normal}
}

/* Uppercase headers run about 15% wider than sentence case for no gain in a
   dense table — they were the reason "On order" and "Arriving" clipped. */
.stock-tbl thead th{
  text-transform:none; letter-spacing:.01em; font-size:var(--fs-11);
  font-weight:600; color:var(--text-3);
}

/* ── table headers, everywhere ────────────────────────────────────────────
   Sentence case across the app, not just the stock table — uppercase was
   costing width and shouting at the reader in every list. */
table.t thead th{
  text-transform:none; letter-spacing:.01em; font-size:var(--fs-11);
  font-weight:600; color:var(--text-3); white-space:nowrap;
}

/* ── dimension card ───────────────────────────────────────────────────────
   The media box was taller than the information, and the actions wrapped
   onto a second line and read as bold text rather than controls. */
.dim-grid{grid-template-columns:repeat(auto-fill,minmax(232px,272px)); justify-content:start; gap:var(--s3)}
.dim-card .dim-img img,.dim-card .dim-none{aspect-ratio:16/10}
.dim-none{font-size:var(--fs-11)}
.dim-body{padding:var(--s3); gap:1px}
.dim-body .strong{font-size:var(--fs-13); font-weight:620;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.dim-body .sub{font-size:var(--fs-12)}
.dim-acts{
  display:flex; align-items:center; gap:2px; margin-top:var(--s2);
  padding-top:var(--s2); border-top:1px solid var(--border); flex-wrap:nowrap;
}
.dim-acts .btn{padding:3px 7px; font-size:var(--fs-11); font-weight:600}
.dim-acts .spacer{flex:1}
.dim-acts [data-mv]{
  opacity:0; padding:3px 4px; color:var(--text-3);
  transition:opacity var(--speed), color var(--speed);
}
.dim-card:hover .dim-acts [data-mv]{opacity:1}
.dim-acts [data-mv]:hover{color:var(--text)}
.dim-acts [data-mv][disabled]{opacity:0 !important}
@media (hover:none){ .dim-acts [data-mv]{opacity:1} }

.dim-group{margin-bottom:var(--s7)}
.dim-group .card-head h2{font-size:var(--fs-13); font-weight:650}

/* ── ghost buttons need to look like controls ─────────────────────────────*/
.btn.ghost{border-color:transparent; background:transparent; color:var(--text-2)}
.btn.ghost:hover{background:var(--surface-3); color:var(--text); border-color:transparent}

/* ── competitors ──────────────────────────────────────────────────────────
   A 560px chart in a 1600px card left a thousand pixels of nothing, and the
   row under it flung the brand and the date to opposite ends of the screen. */
#v-competitors > .card{max-width:920px}
#v-competitors .card-body{padding:var(--s3) var(--s4) 0}
.comp-tbl{table-layout:fixed; width:100%}
.comp-tbl td{padding:var(--s2) var(--s3); vertical-align:middle; font-size:var(--fs-12)}
.comp-tbl td:nth-child(1){width:22%}
.comp-tbl td:nth-child(2){width:104px}
.comp-tbl td:nth-child(3){width:110px}
.comp-tbl td:nth-child(4){width:128px}
.comp-tbl td:nth-child(5){width:84px}
.comp-tbl td:nth-child(6){width:90px}
.comp-tbl td:nth-child(7){width:96px; text-align:right}
.comp-tbl .strong{overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block; max-width:100%}
.chg{max-width:920px}
@media (max-width:900px){
  .comp-tbl{table-layout:auto}
  .comp-tbl td:nth-child(n){width:auto}
}

/* ── column width per screen ──────────────────────────────────────────────
   A KPI strip running the full width above cards that stop at 920px left a
   ragged right edge. Screens whose content is inherently narrow are
   constrained as a whole, so every element shares the same two margins. */
#v-competitors{max-width:920px}
#v-competitors > .card{max-width:none}
#v-home{max-width:920px}
.home-today{max-width:none}
#v-projects{max-width:1100px}

@media (max-width:900px){
  /* the stacked pack puts each cell on its own row; the borderless inline
     edits need their full width there or the value is cut off */
  #packBody .pk-edit{width:100%; margin:0; border-color:var(--border)}
  #packBody .pk-num{width:100%}
  #packBody .pk-acts{width:auto; text-align:left}
}

/* Each group heading is the first child of its own <section>, so
   `.group-head:first-child{margin-top:0}` was zeroing every one of them and
   leaving each heading sitting on the card above. Space the sections instead
   — it cannot be defeated by nesting. */
.group-head{margin-top:0}
.view > section + section{margin-top:var(--s8)}
.view > section > .split:last-child{margin-bottom:0}


/* ══════════════════════════════════════════════════════════════════════════
   STOCK & REORDER — the grid, the phone card, and the supply plan
   The screen answers one question, "what do I order and when", so the
   layout is built round that: cover as a bar you can scan down, and a plan
   that shows its working rather than asserting a number.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── days of cover, as a bar ─────────────────────────────────────────────── */
.cov{display:flex;flex-direction:column;gap:3px;min-width:0}
.cov-t{height:5px;border-radius:3px;background:var(--surface-3);overflow:hidden}
.cov-t i{display:block;height:5px;border-radius:3px;background:var(--text-3)}
.cov-t i.bad{background:var(--danger)}
.cov-t i.warn{background:var(--warn)}
.cov-t i.ok{background:var(--ok)}
.cov-t i.na{background:var(--border-strong)}
.cov-l{font-family:var(--ff-mono);font-size:var(--fs-12);font-weight:600;color:var(--text-2);
  white-space:nowrap;line-height:1.2}
.cov-l.bad{color:var(--danger)}
.cov-l.warn{color:var(--warn)}
.cov-l.ok{color:var(--ok)}
.cov-d{font-family:var(--ff-mono);font-size:var(--fs-11);line-height:1.2}

/* ── the desktop grid ────────────────────────────────────────────────────── */
.stock-cards{display:none}
/* Fixed widths take their cue from the header row, so they are trimmed to
   leave the product name a readable column on a 1280 laptop, and the table
   is given a floor below which the wrapper scrolls — without one the name
   column collapsed to nothing at 1024 instead. */
.stock-tbl{min-width:980px}
.stock-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.stock-tbl > thead > tr > th:nth-child(2){width:88px}    /* demand sparkline           */
.stock-tbl > thead > tr > th:nth-child(3){width:76px}    /* on hand                    */
.stock-tbl > thead > tr > th:nth-child(4){width:90px}    /* available — was clipping   */
.stock-tbl > thead > tr > th:nth-child(5){width:88px}    /* on order                   */
.stock-tbl > thead > tr > th:nth-child(6){width:86px}    /* arriving                   */
.stock-tbl > thead > tr > th:nth-child(7){width:58px}    /* per week                   */
.stock-tbl > thead > tr > th:nth-child(8){width:118px}   /* cover — bar, days, date    */
.stock-tbl > thead > tr > th:nth-child(9){width:94px}    /* order by                   */
.stock-tbl > thead > tr > th:nth-child(10){width:60px}    /* order qty                  */
.stock-tbl > thead > tr > th:nth-child(11){width:146px}  /* status — must not clip     */
.stock-tbl .c-cover{overflow:visible}

/* ── the phone card ──────────────────────────────────────────────────────────
   Four lines in the order you read them: what it is, how bad it is, how
   long you have, and the numbers that decide whether you act. The stacked
   table put ten labelled rows on screen per SKU, so four SKUs filled a
   phone and finding the one you wanted meant scrolling past the rest. */
.skuc{display:block;width:100%;text-align:left;appearance:none;cursor:pointer;
  background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--border-strong);
  border-radius:var(--r);padding:var(--s3) var(--s4);margin-bottom:var(--s3);
  font:inherit;color:var(--text)}
.skuc:active{background:var(--surface-hover)}
.skuc.bad{border-left-color:var(--danger)}
.skuc.warn{border-left-color:var(--warn)}
.skuc.ok{border-left-color:var(--ok)}
.skuc-top{display:flex;align-items:flex-start;gap:var(--s3);margin-bottom:var(--s3)}
.skuc-id{min-width:0;flex:1}
.skuc-name{font-size:var(--fs-14);font-weight:600;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.skuc-sku{font-family:var(--ff-mono);font-size:var(--fs-11);color:var(--text-3);margin-top:2px}
.skuc .badge{flex-shrink:0}
.skuc-n{display:flex;flex-wrap:wrap;gap:2px var(--s4);margin-top:var(--s3);
  font-size:var(--fs-12);color:var(--text-3)}
.skuc-n b{font-family:var(--ff-mono);color:var(--text);font-weight:600}
.skuc-n .bad,.skuc-n .bad b{color:var(--danger)}
.skuc-n .qty b{color:var(--accent)}

/* ── the supply plan ─────────────────────────────────────────────────────── */
/* The numbers get the width: the month grid takes the top row on its own,
   the working sits under it, and the decision stays beside both. */
.sp{display:grid;gap:var(--s5) var(--s5);padding:var(--s4) var(--s5) var(--s5);
  grid-template-columns:minmax(0,1fr) 264px}
.sp-chart{grid-column:1;grid-row:1}
.sp-work{grid-column:1;grid-row:2}
.sp-plan{grid-column:2;grid-row:1 / span 2;align-self:start}
.sp-h{display:flex;align-items:baseline;gap:var(--s3);margin-bottom:var(--s3)}
.sp-h h4{margin:0;font-size:var(--fs-13);font-weight:600;color:var(--text)}
.sp-h span{font-size:var(--fs-11);color:var(--text-3)}
.sp-note{margin:var(--s3) 0 0;font-size:var(--fs-12);line-height:1.55;color:var(--text-3)}
.sp-note b{color:var(--text)}


/* ── the month grid ──────────────────────────────────────────────────────────
   Nine columns of real numbers. The label column is pinned so a phone can
   push the months sideways without losing which row it is reading, and the
   current month is marked because every figure to its right is forecast. */
.mg-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid var(--border);border-radius:var(--r);background:var(--surface)}
.mg-wrap .mg{border-collapse:separate;border-spacing:0;width:100%;table-layout:fixed;
  font-family:var(--ff-mono);font-variant-numeric:tabular-nums;font-size:var(--fs-12)}
.mg-wrap .mg th,.mg-wrap .mg td{box-sizing:border-box;padding:6px 8px;text-align:right;
  white-space:nowrap;text-transform:none;letter-spacing:0;position:static;
  border-bottom:1px solid var(--border)}
.mg-wrap .mg tbody tr:last-child th,.mg-wrap .mg tbody tr:last-child td{border-bottom:0}

/* the pinned row-label column */
.mg-wrap .mg thead th:first-child,.mg-wrap .mg tbody th{position:sticky;left:0;z-index:1;
  width:92px;text-align:left;font-family:var(--ff);font-weight:500;
  background:var(--surface);color:var(--text-2);border-right:1px solid var(--border)}
.mg-wrap .mg thead th{background:var(--surface-2);color:var(--text-3);font-family:var(--ff);
  font-size:var(--fs-11);font-weight:600;letter-spacing:.03em}
.mg-wrap .mg thead th:first-child{background:var(--surface-2)}
.mg-wrap .mg thead th i{font-style:normal;color:var(--text-3);opacity:.7;margin-left:3px}
.mg-wrap .mg td{color:var(--text-2);overflow:hidden;text-overflow:ellipsis}

/* months already behind us are history, not forecast — they recede */
.mg-wrap .mg td.past{color:var(--text-3)}
.mg-wrap .mg thead th.past{opacity:.7}
/* this month, where actual stops and forecast starts */
.mg-wrap .mg .now{background:var(--surface-2)}
.mg-wrap .mg thead th.now{color:var(--text);background:var(--accent-soft)}
.mg-wrap .mg tbody th{z-index:2}
/* the month it runs dry */
.mg-wrap .mg .out{background:var(--danger-soft)}

.mg-wrap .mg .mg-sold td{color:var(--text)}
.mg-wrap .mg .mg-close th,.mg-wrap .mg .mg-close td{font-weight:700;color:var(--text)}
.mg-wrap .mg .neg{color:var(--danger)}
.mg-wrap .mg .in{color:var(--info)}
.mg-foot{margin:var(--s3) 0 0;font-size:var(--fs-11);line-height:1.6;color:var(--text-3)}
.mg-foot b{color:var(--text)}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* the rate blend */
.rb{display:flex;align-items:center;gap:var(--s3);margin-bottom:6px}
.rb-k{width:78px;flex-shrink:0;font-family:var(--ff-mono);font-size:var(--fs-11);color:var(--text-3)}
.rb-t{flex:1;min-width:0;height:5px;border-radius:3px;background:var(--surface-3);overflow:hidden}
.rb-t i{display:block;height:5px;border-radius:3px;background:var(--border-strong)}
.rb-v{width:38px;flex-shrink:0;text-align:right;font-family:var(--ff-mono);
  font-size:var(--fs-12);font-weight:500;color:var(--text-2)}
.rb.on .rb-t i{background:var(--accent)}
.rb.on .rb-v{color:var(--text);font-weight:700}
.sp-say{margin:var(--s4) 0 0;padding-top:var(--s3);border-top:1px solid var(--border);
  font-size:var(--fs-12);line-height:1.6;color:var(--text-3)}
.sp-say b{color:var(--text)}
.sp-chips{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);margin-top:var(--s4)}
.sp-chips span{display:flex;flex-direction:column;gap:2px}
.sp-chips i{font-style:normal;font-size:var(--fs-11);color:var(--text-3)}
.sp-chips b{font-family:var(--ff-mono);font-size:var(--fs-13);font-weight:600;color:var(--text)}

/* the decision */
.sp-plan{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:var(--s4);display:flex;flex-direction:column}
.sp-plan h4{margin:0 0 var(--s3);font-size:var(--fs-13);font-weight:600}
.sp-big{display:flex;align-items:baseline;gap:var(--s3);margin-bottom:var(--s3)}
.sp-big b{font-family:var(--ff-brand,var(--ff));font-size:var(--fs-30);font-weight:800;
  line-height:1;letter-spacing:-.02em;color:var(--text)}
.sp-big span{font-size:var(--fs-12);color:var(--text-3)}
.sp-row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);
  padding:5px 0;border-top:1px solid var(--border);font-size:var(--fs-12);color:var(--text-3)}
.sp-row b{font-family:var(--ff-mono);font-size:var(--fs-12);font-weight:600;color:var(--text);
  text-align:right}
.sp-row b.bad{color:var(--danger)}
.sp-acts{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--border);
  display:flex;flex-direction:column;gap:6px}
.sp-acts .btn{width:100%;justify-content:center}


/* ── narrow: everything stacks, numbers first ────────────────────────────── */
@media (max-width:1080px){
  .sp{grid-template-columns:minmax(0,1fr)}
  .sp-chart,.sp-work,.sp-plan{grid-column:1;grid-row:auto}
  .sp-acts{flex-direction:row}
}

/* ── phone ───────────────────────────────────────────────────────────────────
   The grid goes away entirely and the cards take over; the plan is reached
   through the sheet, where it has a full screen and its own scroll. */
@media (max-width:900px){
  .stock-wrap{display:none}
  .stock-cards{display:block;padding:var(--s4)}
  .stock-tbl .chev{display:none}

  .stock-bar{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3);padding:var(--s4)}
  .stock-bar .search{grid-column:1/-1;width:100%}
  .stock-bar .seg{grid-column:1/-1;display:flex}
  .stock-bar .seg button{flex:1;min-width:0}
  .stock-bar .spacer{display:none}
  .stock-bar select{width:100%!important}
  .stock-bar .btn{width:100%;justify-content:center}
  .stock-bar #stockPull{grid-column:1/-1}

  /* minmax(0,…) not 1fr: an auto-min track lets a wide table push the whole
     column out instead of scrolling inside its own wrapper */
  .sp{grid-template-columns:minmax(0,1fr);gap:var(--s5);padding:0}
  /* the foot of a sheet has to wrap rather than squeeze its button away */
  .sheet-foot{flex-wrap:wrap}
  .sheet-foot .btn{flex-shrink:0}
  .sp-plan{order:-1}
  .sp-acts{flex-direction:column}
  .sheet-plan{margin:0 0 var(--s5)}

  /* Nine columns cannot share 350px and stay legible — squeezed to fit they
     ellipsised to "1…". Here the grid keeps its natural column widths and
     slides sideways under the pinned row labels instead. */
  .mg-wrap .mg{table-layout:auto;width:auto;min-width:100%}
  .mg-wrap .mg th,.mg-wrap .mg td{padding:7px 9px}
  .mg-wrap .mg thead th:not(:first-child),.mg-wrap .mg tbody td{min-width:48px}
  .mg-wrap .mg thead th:first-child,.mg-wrap .mg tbody th{width:82px;min-width:82px}
}


/* ── the secondary stock controls ────────────────────────────────────────────
   On a desktop they sit in the toolbar as they always have. On a phone the
   window picker and the two export buttons were costing a third of the
   screen above the first SKU, so they fold behind one control. */
.stock-more{display:contents}
.stock-more>summary{display:none}

@media (max-width:900px){
  /* closed, "More" shares its row with Refresh; open, it takes the row */
  .stock-more{display:block;grid-column:1}
  .stock-more[open]{grid-column:1/-1}
  .stock-bar #stockPull{grid-column:2}
  .stock-bar .stock-more[open] ~ #stockPull{grid-column:1/-1}
  .stock-more>summary{display:flex;align-items:center;justify-content:center;gap:6px;
    height:34px;cursor:pointer;list-style:none;border:1px solid var(--border);
    border-radius:var(--r);background:var(--surface);color:var(--text-2);
    font-size:var(--fs-13);font-weight:500}
  .stock-more>summary::-webkit-details-marker{display:none}
  .stock-more>summary::after{content:"▾";font-size:10px;color:var(--text-3)}
  .stock-more[open]>summary::after{content:"▴"}
  .stock-more[open]{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
  .stock-more[open]>summary{grid-column:1/-1}
  .stock-more>select{width:100%!important;grid-column:1/-1}
  .stock-more>.btn{width:100%;justify-content:center}

  /* the counts are a glance, not the point of the screen. Stacked two-up
     they were three rows deep and pushed the first SKU 650px down the page,
     so they become one strip that scrolls sideways instead. */
  #v-stock .stats{display:flex;flex-wrap:nowrap;gap:var(--s2);overflow-x:auto;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;
    margin-bottom:var(--s4)!important;padding-bottom:2px}
  #v-stock .stats::-webkit-scrollbar{display:none}
  #v-stock .stats>*{flex:0 0 auto!important;min-width:112px!important;width:auto!important;
    padding:var(--s3) var(--s4)!important}
  #v-stock .stat-v{font-size:var(--fs-18)!important}
  #v-stock .stat-k{font-size:var(--fs-11)!important;white-space:nowrap}

  /* the toolbar loses a row of its own padding too */
  .stock-bar{padding:var(--s3) var(--s4)}

  /* on a card the cover reads as one line, not three — the run-out date is
     already implied by the days, and the card is a summary, not the record */
  .skuc .cov{flex-direction:row;align-items:center;gap:var(--s3)}
  .skuc .cov-t{flex:1;min-width:0}
  .skuc .cov-l{flex-shrink:0}
  .skuc .cov-d{display:none}

  /* H. a product name is worth two lines on a phone; one line ended most of
     them in an ellipsis, which is the one part you needed to read */
  .skuc-name{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
    -webkit-box-orient:vertical;overflow:hidden}
}




/* a kit-component chip carries the code and what we call it, so it can be
   picked by eye instead of by memory */
.chip-pick .chip{align-items:baseline;gap:6px;flex-wrap:wrap}
.chip-pick .chip .mono{font-family:var(--ff-mono);font-size:var(--fs-11)}
.chip-pick .chip i{font-style:normal;font-size:var(--fs-11);color:var(--text-3)}
.chip-pick .chip.on i{color:var(--text-2)}

.flag-btn{border:0;font:inherit;cursor:pointer;padding:1px 6px}
.flag-btn:hover{color:var(--accent)}


/* ── Setup ───────────────────────────────────────────────────────────────────
   A screen, not a button at the bottom of a panel. Names are edited straight
   in the list because renaming is something you do to several at once. */
/* a card head is a flex row, so a long title was being squeezed into a
   six-line column beside its own explanation — here they stack */
.set-head{display:block}
.set-head h3{margin:0 0 3px}
.set-head .sub{display:block}
.set-grid{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.set-tbl td{vertical-align:middle}
.set-tbl .set-alias{width:100%;min-width:160px}
.set-tbl .set-alias::placeholder{color:var(--text-3);font-style:italic}
.set-tbl .set-src{color:var(--text-3);font-size:var(--fs-12);max-width:280px}
.set-tbl .set-src span:first-child{display:inline-block;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}
.set-tbl tr.set-off td{opacity:.55}
.set-tbl tr.set-off .set-alias{opacity:1}
@media (max-width:900px){
  .set-tbl .set-src{max-width:none}
  .set-tbl .set-alias{min-width:0}
  /* the stacked table gives every column its own labelled row; lead and
     buffer are overrides you set once, so they stay in More… rather than
     making each SKU five rows tall */
  .set-tbl td:nth-child(4),.set-tbl td:nth-child(5){display:none}
}


/* ── where the count comes from ──────────────────────────────────────────────
   The arithmetic behind the available figure, because a number that differs
   from what Shopify shows has to be able to defend itself. */
.cnt{margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--border)}
.cnt-h{font-size:var(--fs-12);font-weight:600;color:var(--text);margin-bottom:var(--s2)}
.cnt-row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);
  padding:4px 0;font-size:var(--fs-12);color:var(--text-3)}
.cnt-row span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cnt-row b{flex-shrink:0;font-family:var(--ff-mono);font-weight:600;color:var(--text-2)}
.cnt-row b.neg{color:var(--danger)}
.cnt-tot{border-top:1px solid var(--border);margin-top:2px;padding-top:6px;color:var(--text-2)}
.cnt-tot b{font-size:var(--fs-14);color:var(--text)}

/* ════════════════════════════════════════════════════════════════════════════
   Eleven columns on a thirteen-inch laptop

   Splitting on hand from available added a column, and at 1180 the row no
   longer fits — the wrapper scrolls and Status ends up half off the edge,
   which reads as broken rather than as scrollable.

   Rather than shave every column until they are all cramped, one stands
   down: the weekly rate. It is the most redundant thing on the row — the
   sparkline beside it shows the shape, and opening the row spells the number
   out three ways. It comes back above 1400 where there is room.
   ════════════════════════════════════════════════════════════════════════════ */
@media (min-width:900px) and (max-width:1399px){
  .stock-tbl > thead > tr > th:nth-child(7),
  .stock-tbl > tbody > tr > td:nth-child(7){display:none}
  .stock-tbl{min-width:872px}
  .stock-tbl > thead > tr > th:nth-child(2){width:78px}    /* demand   */
  .stock-tbl > thead > tr > th:nth-child(5){width:80px}    /* on order */
  .stock-tbl > thead > tr > th:nth-child(6){width:78px}    /* arriving */
  .stock-tbl > thead > tr > th:nth-child(8){width:106px}   /* cover    */
  .stock-tbl > thead > tr > th:nth-child(11){width:134px}  /* status   */
}

/* A purchase order fills the screen: a dozen fields and a line table with six
   columns do not fit a 560px drawer. Capped so the form does not stretch to
   absurd line lengths on a wide monitor. */
.sheet.wide { width: 100vw; border-left: 0; }
.sheet.wide .sheet-body,
.sheet.wide .sheet-head,
.sheet.wide .sheet-foot { max-width: 1180px; margin-left: auto; margin-right: auto; width: 100%; }

/* The product list does two jobs in one walk: naming and counting. Fixed
   widths on the numbers so the name column takes whatever is left. */
.sc-tbl > thead > tr > th:nth-child(1){width:150px}
.sc-tbl > thead > tr > th:nth-child(3){width:90px}
.sc-tbl > thead > tr > th:nth-child(4){width:120px}
.sc-tbl > thead > tr > th:nth-child(5){width:90px}
.sc-tbl .sc-alias{width:100%}
.sc-tbl .sc-qty{width:100%;max-width:100px;margin-left:auto}
@media (max-width:640px){
  .sc-tbl .sc-qty{max-width:none;margin-left:0}
}

/* A number you can open. Used on the month grid's Sold row and on the
   committed figure, both of which are sums over order lines. */
.mg-drill{
  background:none;border:0;font:inherit;color:inherit;padding:0;cursor:pointer;
  border-bottom:1px dotted var(--text-3);
}
.mg-drill:hover{color:var(--accent);border-bottom-color:var(--accent)}
.flag-btn.link{
  background:none;padding:0;color:var(--text-3);
  border-bottom:1px dotted var(--text-3);border-radius:0;font-weight:500;
}
.flag-btn.link:hover{color:var(--accent);border-bottom-color:var(--accent)}
.txn-tbl td,.txn-tbl th{vertical-align:top}
.txn-tbl .txn-zero td{border-bottom:1.5px solid var(--text-3)}
.cnt-row b.pos{color:var(--ok)}

/* Receiving: ordered, already in, outstanding, and what is landing now. */
.rcv-tbl .rcv-qty{width:100%;max-width:110px;margin-left:auto}
.rcv-tbl td,.rcv-tbl th{vertical-align:top}
/* the unattributed-stock picker inside the receive notice */
.orph-tbl{background:transparent}
.orph-tbl td{padding:4px 8px;border-color:color-mix(in srgb,currentColor 18%,transparent)}
.orph-tbl td:first-child{padding-left:0}
.orph-tbl input[type=checkbox]{margin:0;vertical-align:middle}
/* ── freight setup ─────────────────────────────────────────────────────── */
.fr-origin{display:grid;grid-template-columns:1.4fr .6fr .8fr;gap:var(--s3);margin-top:var(--s2)}
.fr-origin label{display:flex;flex-direction:column;gap:2px}
.fr-origin input{width:100%}
.fr-tbl{margin-top:var(--s2)}
.fr-tbl .fr-num{width:100%;max-width:92px;margin-left:auto;text-align:right}
.fr-tbl td,.fr-tbl th{vertical-align:middle}
.fr-tbl th.num{white-space:nowrap}
@media (max-width:640px){
  .fr-origin{grid-template-columns:1fr 1fr;gap:var(--s2)}
  .fr-tbl .fr-num{max-width:none}
}
@media (max-width:640px){
  .orph-tbl td{display:table-cell;padding:4px 6px}
  .orph-tbl td:before{content:none}
}
.po-card .line .qty b{font-variant-numeric:tabular-nums}

/* ══ the dashboard ═══════════════════════════════════════════════════════
   Built from the Concept canvas's Main artboard. The artboard was drawn in
   dark mode with literal hexes; these use the hub's tokens so the same
   layout holds in light and dark. Chart and info hues are declared here
   because the palette only had brand, status and text before — and they are
   validated against both surfaces, not flipped. */
:root, :root[data-theme="light"] {
  --chart-1: #2b5fd9;
  --chart-2: #0e8a52;
  --info:    #2b5fd9;  --info-soft: #eaf0fd;  --info-line: #c3d4f6;
}
:root[data-theme="dark"] {
  --chart-1: #5b8cf0;
  --chart-2: #2fae77;
  --info:    #5b8cf0;  --info-soft: #141c2b;  --info-line: #27385c;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --chart-1: #5b8cf0;
    --chart-2: #2fae77;
    --info:    #5b8cf0;  --info-soft: #141c2b;  --info-line: #27385c;
  }
}
.info-txt   { color: var(--info) }
.danger-txt { color: var(--danger) }
.warn-txt   { color: var(--warn) }
.ok-txt     { color: var(--ok) }

.dash-head { display:flex; align-items:flex-end; gap:var(--s4); margin-bottom:var(--s5); flex-wrap:wrap }
.dash-h1 { margin:0; font-size:30px; font-weight:800; letter-spacing:-.022em; color:var(--text-1) }
.dash-sub { margin:5px 0 0; font-size:var(--fs-13); color:var(--text-2) }

/* the three decision cards */
.dcards { display:grid; grid-template-columns:repeat(3,1fr); gap:var(--s4); margin-bottom:var(--s4) }
.dcard { background:var(--surface); border:1px solid var(--border); border-radius:14px;
  padding:15px 17px; display:flex; flex-direction:column; gap:7px; min-height:130px; box-shadow:var(--lift) }
.dc-top { display:flex; align-items:center; gap:7px }
.dc-dot { width:6px; height:6px; border-radius:50%; flex:0 0 auto }
.dc-dot.now { background:var(--danger) } .dc-dot.warn { background:var(--warn) }
.dc-dot.info { background:var(--info) }  .dc-dot.ok { background:var(--ok) }
.dc-kind { font-size:10px; font-weight:700; letter-spacing:.12em; text-transform:uppercase }
.dc-kind.now { color:var(--danger) } .dc-kind.warn { color:var(--warn) }
.dc-kind.info { color:var(--info) }   .dc-kind.ok { color:var(--ok) }
.dc-ref { margin-left:auto; font-size:10.5px; color:var(--text-3) }
.dc-title { font-size:15px; font-weight:600; line-height:1.3; color:var(--text-1) }
.dc-body { font-size:var(--fs-12); line-height:1.45; color:var(--text-2) }
.dc-go { margin-top:auto; font-size:var(--fs-12); font-weight:600; display:inline-flex;
  align-items:center; gap:5px; color:var(--accent); text-decoration:none }
.dc-go:hover { text-decoration:underline }

/* KPI tiles with a sparkline */
.ktiles { display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s4); margin-bottom:var(--s5) }
.ktile { background:var(--surface); border:1px solid var(--border); border-radius:14px;
  padding:13px 16px 10px; display:flex; flex-direction:column; min-height:104px; box-shadow:var(--lift) }
.kt-k { font-size:10.5px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--text-3) }
.kt-row { display:flex; align-items:baseline; gap:8px; margin-top:4px }
.kt-v { font-size:27px; font-weight:800; letter-spacing:-.02em; color:var(--text-1); line-height:1.1 }
.kt-d { font-size:11.5px; font-weight:500 }
.kt-d.up { color:var(--ok) } .kt-d.down { color:var(--danger) } .kt-d.flat { color:var(--text-3) }
.kt-spark { width:100%; height:28px; margin-top:auto; display:block }

/* queue / side column */
.dash-2col { display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  gap:var(--s4); align-items:start; margin-bottom:var(--s5) }
.dash-side { display:flex; flex-direction:column; gap:var(--s4) }

.rq-row { display:flex; align-items:center; gap:14px; padding:13px 18px;
  border-bottom:1px solid var(--border); cursor:pointer }
.rq-row:last-child { border-bottom:0 }
.rq-row:hover { background:var(--surface-hover) }
.rq-id { width:178px; flex:0 0 auto; min-width:0 }
.rq-name { font-size:13.5px; font-weight:600; color:var(--text-1);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.rq-sku { font-size:10.5px; color:var(--text-3); margin-top:2px }
.rq-mid { flex:1 1 auto; min-width:0 }
.rq-bar { position:relative; height:6px; border-radius:3px; background:var(--surface-3); overflow:hidden }
.rq-bar span { position:absolute; inset:0 auto 0 0; border-radius:3px }
.rq-bar span.danger { background:var(--danger) }
.rq-bar span.warn   { background:var(--warn) }
.rq-bar span.ok     { background:var(--ok) }
.rq-meta { display:flex; gap:12px; margin-top:6px; font-size:11px; flex-wrap:wrap }
.rq-n { flex:0 0 auto; text-align:right; display:flex; flex-direction:column; gap:2px; min-width:48px }
.rq-n .faint { font-size:10px }
.rq-n b { font-size:13px }
.rq-act { flex:0 0 auto; min-width:92px; text-align:right }

/* on the water */
.wtr { padding:10px 0; border-bottom:1px solid var(--border); cursor:pointer }
.wtr:last-child { border-bottom:0 }
.wtr-top { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap }
.wtr-steps { display:flex; gap:3px; margin-top:8px }
.wtr-steps span { flex:1 1 0; height:4px; border-radius:2px; background:var(--surface-3) }
.wtr-steps span.on { background:var(--info) }
.wtr-labels { display:flex; justify-content:space-between; margin-top:6px; font-size:10px; color:var(--text-3) }

/* gone quiet */
.gq-row { display:flex; align-items:center; gap:10px; padding:11px 18px; border-bottom:1px solid var(--border) }
.gq-row:last-child { border-bottom:0 }
.gq-row:hover { background:var(--surface-hover) }

/* the trading band sits below the operational half */
.dash-band { margin-bottom:var(--s5) }
.hb-head { display:flex; align-items:flex-end; gap:var(--s3); margin-bottom:var(--s4); flex-wrap:wrap }
.hb-h2 { margin:4px 0 0; font-size:20px; font-weight:600; color:var(--text-1) }
.hb-stats { margin-bottom:var(--s3) }
.hb-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s4) }
.hp { background:var(--surface); border:1px solid var(--border); border-radius:14px;
  padding:14px 16px; box-shadow:var(--lift); min-width:0 }
.hp-head { display:flex; align-items:baseline; gap:8px; margin-bottom:var(--s2); flex-wrap:wrap }
.hp-now { margin-left:auto; font-size:15px; color:var(--text-1) }
.hp-hit { cursor:crosshair }
.hb-tbl { margin-top:var(--s2) }
.hb-tbl td { position:relative }
.hb-bar { position:absolute; left:0; bottom:2px; height:2px; background:var(--chart-1); opacity:.35; border-radius:1px }
.hb-best { color:var(--ok); font-weight:600 }
.hb-empty { display:flex; align-items:center; gap:var(--s4); flex-wrap:wrap }

@media (max-width:1180px) {
  .dcards { grid-template-columns:1fr 1fr }
  .ktiles { grid-template-columns:1fr 1fr }
  .dash-2col { grid-template-columns:1fr }
}
@media (max-width:760px) {
  .dcards, .ktiles, .hb-grid { grid-template-columns:1fr }
  .dash-h1 { font-size:24px }
  .rq-row { flex-wrap:wrap; gap:8px }
  .rq-id { width:100%; }
  .rq-mid { flex-basis:100% }
  .rq-n { min-width:64px; text-align:left; flex-direction:row; align-items:baseline; gap:6px }
  .rq-act { min-width:0; width:100%; text-align:left }
}

/* ── competitor moves ─────────────────────────────────────────────────── */
.cm-row { display:flex; align-items:baseline; gap:9px; padding:9px 18px;
  border-bottom:1px solid var(--border); cursor:pointer }
.cm-row:last-child { border-bottom:0 }
.cm-row:hover { background:var(--surface-hover) }
.cm-mark { flex:0 0 auto; font-size:10px; line-height:1.4 }
.cm-mark.ok { color:var(--ok) } .cm-mark.danger { color:var(--danger) }
.cm-mark.warn { color:var(--warn) }
.cm-txt { flex:1 1 auto; font-size:var(--fs-13); color:var(--text-1); min-width:0 }

/* ── checkout funnel ──────────────────────────────────────────────────── */
.fn { display:flex; flex-direction:column; gap:7px; margin-top:var(--s2) }
.fn-step { display:grid; grid-template-columns:124px minmax(0,1fr) 62px 44px;
  align-items:center; gap:10px }
.fn-k { font-size:var(--fs-12); color:var(--text-2) }
.fn-bar { height:10px; border-radius:5px; background:var(--surface-3); overflow:hidden }
.fn-bar span { display:block; height:100%; border-radius:5px; background:var(--chart-1) }
.fn-bar span.ok { background:var(--ok) }
.fn-v { text-align:right; font-size:var(--fs-12); color:var(--text-1) }
.fn-p { text-align:right }

/* ── product type movement: one axis, zero in the middle ──────────────── */
.ty-tbl { margin-top:var(--s2) }
.ty-tbl td { vertical-align:middle }
.ty-c { width:34%; min-width:92px }
.ty-tbl td:first-child { white-space:normal }
.ty-zero { opacity:.9 }
.ty-ax { position:relative; height:12px }
.ty-zero { position:absolute; left:50%; top:0; bottom:0; width:1px; background:var(--border-strong) }
.ty-b { position:absolute; top:2px; height:8px; border-radius:2px }
.ty-b.up { background:var(--ok) } .ty-b.down { background:var(--danger) }

@media (max-width:760px) {
  .fn-step { grid-template-columns:96px minmax(0,1fr) 54px; gap:8px }
  .fn-p { display:none }
  .ty-c { width:34% }
}

/* ── chart tooltip ────────────────────────────────────────────────────────
   One element for every chart. Fixed so it is never clipped by a card, and
   pointer-events:none so it can sit over the point it describes. */
.ctip { position:fixed; z-index:120; pointer-events:none; opacity:0;
  transform:translateY(3px); transition:opacity .09s ease, transform .09s ease;
  background:var(--surface); border:1px solid var(--border-strong);
  border-radius:9px; padding:7px 10px; box-shadow:0 6px 20px rgba(0,0,0,.14);
  min-width:92px; max-width:220px }
.ctip.on { opacity:1; transform:translateY(0) }
.ct-k { font-size:10.5px; font-weight:600; letter-spacing:.07em;
  text-transform:uppercase; color:var(--text-3); white-space:nowrap }
.ct-v { font-size:16px; font-weight:700; color:var(--text-1); margin-top:1px; white-space:nowrap }
.ct-m { font-size:11.5px; color:var(--text-2); margin-top:2px; white-space:nowrap }
.hp-hit { cursor:pointer; outline:none }
.hp-hit:focus-visible { outline:2px solid var(--accent); outline-offset:1px }

/* the lost-at-checkout row, replacing the sentence that explained it */
.fn-lost { display:flex; align-items:baseline; gap:7px; margin-top:var(--s3);
  padding-top:var(--s3); border-top:1px solid var(--border); font-size:var(--fs-13) }
.fn-lost b { font-size:16px; color:var(--text-1) }

/* competitors, summarised: a count, then the one that moved most */
.cm-n { flex:0 0 auto; font-weight:700; font-size:15px; color:var(--text-1); min-width:20px }
