/* Pack Desk — DWT warehouse and office UI.
   ------------------------------------------------------------------------
   Visual world: "Quiet instrument."

   The previous system ("Gate Board of a Water-Works Site") treated every card
   as an enamel sign: dark plate, inset keyline, sheen, heavy shadow. Signage is
   built to be read ONCE, at distance, in a glance. These screens are worked in
   — scanned, compared, returned to for minutes at a time. Twenty-six orders
   rendered as twenty-six signs is not emphasis, it is noise: measured on the
   bench PC, half of every queue row was empty and only 6 of 26 orders fit on
   screen. The one calm surface in the old build, the printed picking sheet,
   was also the best one. This system generalises the sheet, not the sign.

   The rules:
     1. The GROUND is quiet and the CONTENT is loud. Surfaces are white on a
        soft ground, separated by a hairline and a shadow you have to look for.
     2. Colour means something or it is absent. Teal is the product's own
        colour and carries chrome, navigation and the primary action. Green,
        amber and red are reserved for state and never used to decorate. Every
        state differs in BRIGHTNESS as well as hue — the old palette put "done"
        and "stopped" 1.13:1 apart in luminance, which is no difference at all
        to a colour-blind picker or to anyone under warehouse glare.
     3. One face, real weights. Overpass is a variable font: one file, the whole
        axis. Weight and size carry hierarchy; uppercase is for micro-labels
        only, never for names, products or prose.
     4. Two densities, one language. Same tokens everywhere; `.bench` trades
        density for reach.

   Use scenes:
     OFFICE (.office) — Jade, seated, a real monitor. Wants to see everything at
       once and find the exception fast. Targets 40px, base 15px, dense rows.
     BENCH (.bench) — Francis, Ryno, Lana. A shared PC at 1366x768, standing,
       industrial lighting, sometimes gloves, a printed sheet in one hand. One
       job per screen. Targets >=64px, base 17px. This was the one thing the old
       design measurably got right and it is kept.
   ------------------------------------------------------------------------ */

@import url('/fonts/fonts.css');

:root{
  /* ground and surfaces */
  --ground:#f3f5f4;
  --surface:#ffffff;
  --surface-sunk:#f7f9f8;
  --line:#e4e9e7;
  --line-firm:#d2dad7;

  /* ink */
  --ink:#16211f;
  --ink-2:#566663;
  --ink-3:#63746f;   /* 4.50:1 on the GROUND, its hardest background; was #7d8d89 at 3.17:1 there */

  /* the product's own colour — chrome, nav, primary action */
  --brand:#0b4f5c;
  --brand-hover:#0e5f6e;
  --brand-ink:#ffffff;
  --brand-tint:#e8f0f1;
  --brand-tint-firm:#cfe0e3;

  /* State. The WORD is the primary signal and always present; the tint and dot
     support it. The tints are stepped in luminance (0.88 -> 0.64) so idle and
     stop are 1.35:1 apart and readable as different without any colour at all.
     Adjacent pairs sit ~1.08:1 and are told apart by the word, not the tint —
     five states cannot all be separated by brightness inside a light palette,
     and pretending otherwise is how the old design ended up with "done" and
     "stopped" at 1.13:1 with nothing else to fall back on. */
  --ok:#14603d;        --ok-tint:#d2e7dc;    --ok-line:#a8ccba;
  --warn:#7a4705;      --warn-tint:#f1d6af;  --warn-line:#dcb277;
  --stop:#8f2617;      --stop-tint:#f1c8c2;  --stop-line:#dfa094;
  --idle:#4a5956;      --idle-tint:#f0f1f1;  --idle-line:#d2d7d6;

  /* radius */
  --r:12px; --r-sm:8px; --r-xs:5px; --r-pill:999px;

  /* depth: offset + soft blur, never a coloured halo */
  --shadow-1:0 1px 2px rgba(16,33,31,.05), 0 1px 3px rgba(16,33,31,.05);
  --shadow-2:0 2px 4px rgba(16,33,31,.04), 0 10px 24px rgba(16,33,31,.07);
  --shadow-pop:0 8px 12px rgba(16,33,31,.08), 0 24px 56px rgba(16,33,31,.16);

  /* type */
  --f:'Overpass',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:ui-monospace,SFMono-Regular,'SF Mono',Menlo,Consolas,monospace;

  /* density — overridden by .bench */
  --base:15px;
  --tap:40px;
  --pad:20px;
  --row:56px;
  --gap:16px;

  --ease:cubic-bezier(.2,.7,.3,1);
}

.bench{
  --base:17px;
  --tap:64px;
  --pad:24px;
  --row:76px;
  --gap:20px;
}

*{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  background:var(--ground);
  color:var(--ink);
  font-family:var(--f);
  font-size:var(--base);
  line-height:1.5;
  font-variant-numeric:tabular-nums;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* The surfaces we did not draw still belong to the design. */
::selection{background:var(--brand-tint-firm);color:var(--ink)}
:root{accent-color:var(--brand);caret-color:var(--brand)}
*{scrollbar-color:var(--line-firm) transparent;scrollbar-width:thin}
::-webkit-scrollbar{width:12px;height:12px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line-firm);border:3px solid var(--ground);border-radius:var(--r-pill)}
::-webkit-scrollbar-thumb:hover{background:var(--ink-3)}

:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--brand);
  outline-offset:2px;
  border-radius:var(--r-xs);
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

h1,h2,h3,p,ul,ol,figure{margin:0}
ul{list-style:none;padding:0}
a{color:inherit;text-decoration:none}

/* ==================================================================== shell */
/* Office: a persistent rail, so Jade always knows what is waiting and can get
   anywhere in one click. Bench: no rail — a picker has one job and needs the
   width; a single large "back to the queue" is the whole navigation model. */

.app{min-height:100vh}

.office .app{
  display:grid;
  grid-template-columns:236px minmax(0,1fr);
  align-items:start;
}

.side{
  position:sticky;top:0;height:100vh;
  display:flex;flex-direction:column;
  background:var(--surface);
  border-right:1px solid var(--line);
  padding:18px 12px 12px;
}
.bench .side{display:none}

.side-brand{
  display:flex;align-items:center;gap:10px;
  padding:4px 10px 18px;
}
.side-brand .mark{
  width:28px;height:28px;flex:none;border-radius:var(--r-xs);
  background:var(--brand);color:var(--brand-ink);
  font-size:11px;font-weight:800;letter-spacing:.06em;
  display:grid;place-items:center;
}
.side-brand .wordmark{font-size:15px;font-weight:700;letter-spacing:-.01em}
.side-brand .wordmark small{display:block;font-size:11px;font-weight:500;color:var(--ink-3);letter-spacing:0}

.side-nav{display:flex;flex-direction:column;gap:2px}
.nav-item{
  display:flex;align-items:center;gap:10px;
  min-height:38px;padding:0 10px;border-radius:var(--r-sm);
  color:var(--ink-2);font-size:14px;font-weight:500;
  transition:background .12s var(--ease),color .12s var(--ease);
}
.nav-item:hover{background:var(--surface-sunk);color:var(--ink)}
.nav-item.is-active{background:var(--brand-tint);color:var(--brand);font-weight:600}
/* Icons are drawn, one stroke weight, and used in nav, buttons and empty states
   alike — so the geometry lives here, not only inside .nav-item. */
.ico{
  width:18px;height:18px;flex:none;
  stroke:currentColor;fill:none;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
}
.nav-item .ico{opacity:.9}
.empty .art .ico{width:20px;height:20px}
.receipt .ico{width:20px;height:20px}
.flagdot .ico{width:13px;height:13px;stroke-width:2}
.nav-item .txt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-count{
  font-size:12px;font-weight:600;color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}
.nav-item.is-active .nav-count{color:var(--brand)}
.nav-count.is-alert{
  background:var(--stop);color:#fff;
  min-width:20px;height:20px;padding:0 6px;border-radius:var(--r-pill);
  display:grid;place-items:center;
}

.side-foot{margin-top:auto;padding-top:14px;border-top:1px solid var(--line)}
.side-user{
  display:flex;align-items:center;gap:10px;padding:8px 10px;
  color:inherit;text-decoration:none;border-radius:var(--r-sm);
  transition:background .12s var(--ease);
}
.side-user:hover,.side-user:focus-visible{background:var(--surface-sunk)}
.avatar{
  width:32px;height:32px;flex:none;border-radius:var(--r-pill);
  background:var(--brand-tint);color:var(--brand);
  display:grid;place-items:center;font-size:13px;font-weight:700;
  text-decoration:none;
}
/* On the bench the avatar IS the door to your own PIN — there is no rail to
   put a link in — so it has to be reachable by a gloved hand, not 32px. */
a.avatar{transition:box-shadow .12s var(--ease)}
a.avatar:hover,a.avatar:focus-visible{box-shadow:0 0 0 2px var(--brand)}
.bench a.avatar{width:var(--tap);height:var(--tap);font-size:17px}
.side-user .who{min-width:0;flex:1}
.side-user .nm{display:block;font-size:13px;font-weight:600;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-user .rl{display:block;font-size:11px;color:var(--ink-3);line-height:1.3}

/* Issuing somebody a PIN asks the admin to prove their own first — the session
   cookie alone is not enough for an operation that hands over an identity. */
.issueform{display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap}
.issueform label{display:flex;flex-direction:column;gap:4px;
  font-size:12px;font-weight:600;color:var(--ink-2)}
.issueform input{width:9ch;min-height:var(--tap);padding:0 10px;
  font:inherit;font-size:var(--base);letter-spacing:.12em;
  border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink)}
.issueform input:focus-visible{outline:2px solid var(--brand);outline-offset:1px}

/* ------------------------------------------------------------- bench header */
/* The bench gets no rail, so it gets one unmissable way back instead. */
.benchbar{
  display:none;
  /* Above the alert bar, not under it: this is the picker's only way back, and
     the alert appears exactly when they are mid-task. */
  position:sticky;top:0;z-index:25;
  align-items:center;gap:14px;
  padding:10px 18px;
  background:var(--surface);
  border-bottom:1px solid var(--line);
}
.bench .benchbar{display:flex}
.benchbar .mark{
  width:32px;height:32px;flex:none;border-radius:var(--r-xs);
  background:var(--brand);color:var(--brand-ink);
  font-size:12px;font-weight:800;letter-spacing:.06em;display:grid;place-items:center;
}
/* flex:1 + min-width:0 lets this collapse to a few pixels at phone width while
   the text keeps its own size, so "Pick #1378" was painted UNDER the 64px
   avatar circle — measured at 375px: a 4.9px title box, 33px of the order
   number lying beneath the avatar. Truncate rather than overlap; the order
   number is the one thing on that bar the picker needs to read. */
.benchbar .title{font-size:16px;font-weight:700;flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.benchbar .title small{display:block;font-size:12px;font-weight:500;color:var(--ink-3)}

/* ================================================================ main area */
.main{min-width:0}

.topbar{
  display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;
  padding:26px var(--pad) 0;
  max-width:1480px;
}
.bench .topbar{padding-top:20px}
.topbar .heading{flex:1;min-width:0}
.topbar h1{font-size:22px;font-weight:700;letter-spacing:-.015em;line-height:1.2}
.bench .topbar h1{font-size:26px}
.topbar .lede{margin-top:4px;color:var(--ink-2);font-size:13px;
  display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.topbar .lede .sep{color:var(--line-firm)}
.bench .topbar .lede{font-size:15px}
.topbar-actions{display:flex;align-items:center;gap:8px}
.filter{margin:0}
.filter input{min-width:260px;min-height:38px}
/* Visually hidden, still read aloud. */
.vh{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
.qrow[hidden]{display:none!important}
.qgroup[hidden]{display:none!important}
.noresults{padding:28px 16px;text-align:center;color:var(--ink-2);font-size:13px}

/* A queue row is read left to right, so it has a comfortable maximum. Without a
   cap, a 1920px monitor puts the customer name and the status pill ~750px apart
   and re-creates on Jade's screen exactly the dead space this redesign removed
   from the bench. The page still fills the width; the reading column does not. */
.content{
  padding:18px var(--pad) 56px;
  display:flex;flex-direction:column;gap:var(--gap);
  max-width:1480px;
}
.content.narrow{max-width:760px}
.content.mid{max-width:1040px}

/* ==================================================================== cards */
.card{
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r);
  box-shadow:var(--shadow-1);
}
.card-head{padding:var(--pad) var(--pad) 0}
.card-head + .card-body{padding-top:12px}
.card-body{padding:var(--pad)}
.card-title{font-size:15px;font-weight:700;letter-spacing:-.01em}
.bench .card-title{font-size:17px}
.card-sub{margin-top:4px;color:var(--ink-2);font-size:13px;max-width:72ch}
.bench .card-sub{font-size:15px}
.card-foot{
  padding:14px var(--pad);border-top:1px solid var(--line);
  background:var(--surface-sunk);
  border-radius:0 0 var(--r) var(--r);
}

.grid{display:grid;gap:var(--gap)}
@media (min-width:900px){
  .grid.cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
  /* The stat row holds one tile per board group, and the number of groups is a
     product decision that changes. auto-fit keeps the row one row deep instead
     of leaving a single orphan tile under four others. */
  .grid.stats{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
  .grid.side-main{grid-template-columns:minmax(0,1fr) 320px}
}

/* ------------------------------------------------------------------- stats */
.stat{
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);padding:16px 18px;
  display:flex;flex-direction:column;gap:2px;
  min-width:0;
}
.stat-label{font-size:12px;color:var(--ink-2);font-weight:500}
.stat-value{font-size:26px;font-weight:700;letter-spacing:-.02em;line-height:1.15}
a.stat{transition:border-color .12s var(--ease),box-shadow .12s var(--ease)}
a.stat:hover{border-color:var(--brand-tint-firm);box-shadow:var(--shadow-1)}
.stat.is-empty .stat-value{color:var(--ink-3)}
.stat.is-alert{border-color:var(--stop-line);background:var(--stop-tint)}
.stat.is-alert .stat-value,.stat.is-alert .stat-label{color:var(--stop)}

/* ==================================================================== pills */
/* State, never decoration. Text + tint + a dot: three signals, so none of them
   has to work alone. */
.pill{
  display:inline-flex;align-items:center;gap:6px;
  padding:3px 9px 3px 7px;border-radius:var(--r-pill);
  font-size:12px;font-weight:600;line-height:1.45;white-space:nowrap;
  border:1px solid transparent;
}
.bench .pill{font-size:13px;padding:4px 11px 4px 9px}
.pill::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.pill--idle{background:var(--idle-tint);border-color:var(--idle-line);color:var(--idle)}
.pill--info{background:var(--brand-tint);border-color:var(--brand-tint-firm);color:var(--brand)}
.pill--ok{background:var(--ok-tint);border-color:var(--ok-line);color:var(--ok)}
.pill--warn{background:var(--warn-tint);border-color:var(--warn-line);color:var(--warn)}
.pill--stop{background:var(--stop-tint);border-color:var(--stop-line);color:var(--stop)}

/* =================================================================== queue */
.queue{display:flex;flex-direction:column;gap:22px}
.qgroup{min-width:0}
.qgroup-head{
  display:flex;align-items:baseline;gap:8px;
  padding:0 2px 8px;
}
.qgroup-head h2{font-size:13px;font-weight:700;letter-spacing:-.005em}
.qgroup-head .n{font-size:12px;color:var(--ink-3);font-weight:600}
.qgroup-head .hint{margin-left:auto;font-size:12px;color:var(--ink-3)}

.qlist{
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:var(--shadow-1);overflow:hidden;
}
.qrow{
  display:grid;
  grid-template-columns:132px minmax(0,1fr) 68px 104px 132px;
  align-items:center;gap:14px;
  min-height:var(--row);padding:8px 16px;
  border-bottom:1px solid var(--line);
  transition:background .12s var(--ease);
}
.qrow:last-child{border-bottom:0}
.qrow:hover{background:var(--surface-sunk)}
.qrow:focus-visible{outline-offset:-2px}
.q-ref{min-width:0}
.q-ref .num{font-size:15px;font-weight:700;letter-spacing:-.01em;display:block}
.bench .q-ref .num{font-size:17px}
.q-ref .so{font-size:11px;color:var(--ink-3);display:block;line-height:1.3}
.q-cust{min-width:0}
.q-cust .nm{display:block;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.q-cust .meta{font-size:12px;color:var(--ink-3);display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.q-age{font-size:13px;color:var(--ink-3);text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.q-prog{display:flex;flex-direction:column;gap:5px;min-width:0;justify-content:center}
.q-prog .n{font-size:12px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.q-status{justify-self:start}

/* The fill is scaled, not resized: animating width re-lays-out the row on every
   tick, and a picker ticks a row at a time. */
.bar{height:4px;border-radius:var(--r-pill);background:var(--line);overflow:hidden}
.bar>span{
  display:block;height:100%;width:100%;border-radius:inherit;background:var(--ok);
  transform-origin:left center;transform:scaleX(0);
  transition:transform .3s var(--ease);
}

.flagdot{
  display:inline-flex;align-items:center;gap:4px;
  color:var(--stop);font-weight:600;font-size:12px;
}

/* =============================================================== attention */
/* Severity is a real axis here: an uncertain Zoho write may have moved money;
   a missing address has not. The old build gave all three the same red. */
.att{display:flex;flex-direction:column}
.att-row{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:14px;align-items:start;
  padding:16px var(--pad);
  border-top:1px solid var(--line);
}
.att-row:first-child{border-top:0}
.att-body{min-width:0}
.att-title{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.att-title .ref{font-weight:700}
.att-note{margin-top:4px;color:var(--ink-2);font-size:13px;max-width:78ch}
.att-note code{
  font-family:var(--mono);font-size:12px;
  background:var(--surface-sunk);border:1px solid var(--line);
  border-radius:var(--r-xs);padding:1px 5px;
}
/* The engineer-facing detail stays available — this product never hides a
   problem — but it does not have to occupy the row by default. */
.tech{margin-top:6px}
.tech summary{
  cursor:pointer;font-size:12px;font-weight:600;color:var(--ink-2);
  list-style:none;display:inline-flex;align-items:center;gap:5px;
}
.tech summary::-webkit-details-marker{display:none}
.tech summary::before{content:'▸';font-size:10px;transition:transform .12s var(--ease)}
.tech[open] summary::before{transform:rotate(90deg)}
.tech summary:hover{color:var(--ink)}
.tech code{display:block;margin-top:6px;white-space:pre-wrap;word-break:break-word}

.att-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.att-actions form{margin:0}

/* ============================================================ pick surface */
.pickhead{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:var(--pad) var(--pad) 0;
}
.pickhead .count{font-size:15px;font-weight:700}
.bench .pickhead .count{font-size:17px}
.pickhead .bar{flex:1;min-width:120px}
.pickhead .bar.is-none{display:none}

.picklines{margin-top:14px;border-top:1px solid var(--line)}
.pickline{border-bottom:1px solid var(--line);display:flex;align-items:stretch}
.pickline:last-child{border-bottom:0}

.pickrow{
  flex:1;min-width:0;
  display:grid;grid-template-columns:auto 58px minmax(0,1fr) auto;
  align-items:center;gap:14px;
  min-height:var(--tap);
  padding:12px 16px;
  background:none;border:0;font:inherit;color:inherit;text-align:left;
  cursor:pointer;
  transition:background .12s var(--ease);
}
.pickrow:hover{background:var(--surface-sunk)}
.pickrow:disabled{opacity:.6;cursor:progress}

.tick{
  width:30px;height:30px;flex:none;border-radius:var(--r-sm);
  /* 3.1:1 against the card. The empty box is the thing a picker looks for. */
  border:2px solid #86938f;background:var(--surface);
  display:grid;place-items:center;
  color:transparent;font-size:17px;font-weight:800;line-height:1;
  transition:background .14s var(--ease),border-color .14s var(--ease),color .14s var(--ease);
}
.bench .tick{width:38px;height:38px;font-size:21px}

.qty{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15}
.qty .n{font-size:19px;font-weight:700;font-variant-numeric:tabular-nums}
.bench .qty .n{font-size:22px}
.qty small{font-size:11px;color:var(--ink-3);font-weight:500}

.pickrow .body{min-width:0;display:flex;flex-direction:column;gap:2px}
.sku{font-family:var(--mono);font-size:13px;font-weight:600;letter-spacing:-.01em}
.bench .sku{font-size:15px}
.pickrow .nm{color:var(--ink-2);font-size:13px;overflow:hidden;text-overflow:ellipsis}
.bench .pickrow .nm{font-size:15px}
.from{font-size:12px;color:var(--ink-3)}
.flagtag{
  align-self:flex-start;margin-top:3px;
  display:inline-block;padding:2px 8px;border-radius:var(--r-pill);
  background:var(--warn-tint);border:1px solid var(--warn-line);color:var(--warn);
  font-size:11px;font-weight:700;letter-spacing:.02em;
}
.flagnote{font-size:12px;color:var(--ink-2)}
.pickrow .by{font-size:12px;color:var(--ink-3);white-space:nowrap}

/* A closed record still reads clearly; it just stops looking pressable. */
.pickline.is-closed .pickrow{cursor:default}
.pickline.is-closed .pickrow:hover{background:none}
.pickline.is-closed.done .pickrow:hover{background:var(--ok-tint)}
.pickline.is-closed .issue-btn{color:var(--ink-3);cursor:default}
.pickline.is-closed .issue-btn:hover{background:none;color:var(--ink-3)}
.pickrow:disabled{opacity:1}

.pickline.done{background:var(--ok-tint)}
.pickline.done .tick{background:var(--ok);border-color:var(--ok);color:#fff}
.pickline.done .sku{color:var(--ok)}
.pickline.done .pickrow:hover{background:#dcece4}

/* The exception is an exception. The old build gave "Problem" a 129x123px
   target on every row — the same weight as picking itself, five times over on a
   five-line order. It stays reachable and stays quiet. */
.issue-btn{
  flex:none;align-self:stretch;
  padding:0 16px;
  border:0;border-left:1px solid var(--line);
  background:none;color:var(--ink-3);
  font:inherit;font-size:13px;font-weight:500;
  cursor:pointer;
  transition:background .12s var(--ease),color .12s var(--ease);
}
.issue-btn:hover{background:var(--stop-tint);color:var(--stop)}
.bench .issue-btn{padding:0 22px;font-size:15px}

.gate{display:flex;flex-direction:column;gap:10px;align-items:stretch}

/* ==================================================================== boxes */
.boxrow{
  display:grid;
  grid-template-columns:34px repeat(4,minmax(74px,1fr)) auto;
  gap:10px;align-items:end;
  padding:14px 0;border-bottom:1px solid var(--line);
}
.boxrow:last-of-type{border-bottom:0}
.boxrow .seq{
  width:26px;height:26px;border-radius:var(--r-pill);
  background:var(--brand-tint);color:var(--brand);
  display:grid;place-items:center;font-size:12px;font-weight:700;
  margin-bottom:7px;
}
.preset-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}

/* The carton form is a boxrow with a name in front of the three dimensions.
   It lives in a class, not an inline style: an inline grid-template-columns
   outranks the breakpoint below and ran the form off the side of a phone. */
.cartonrow{
  border:0;padding:0;
  grid-template-columns:minmax(120px,1.4fr) repeat(3,minmax(74px,1fr)) auto;
}

/* The three PIN boxes plus the button. Same rule as .cartonrow: the columns
   live in a class so the phone breakpoint can outrank them. */
.pinrow{
  border:0;padding:0;
  grid-template-columns:repeat(3,minmax(94px,1fr)) auto;
}
.pinrow input{font-family:var(--mono);letter-spacing:.18em}

/* A PIN shown exactly once, to be copied onto paper by somebody standing up.
   It is the one number in Pack Desk that cannot be looked up again, so it is
   the one number allowed to be this loud. */
.card--handover{border-color:var(--brand);box-shadow:var(--shadow-2)}
.pincode{
  font-family:var(--mono);font-weight:700;
  font-size:44px;letter-spacing:.22em;line-height:1.1;
  color:var(--brand);
  background:var(--brand-tint);
  border-radius:var(--r-sm);
  padding:18px 22px;margin:0 0 14px;
  text-align:center;
  /* Selectable on purpose: the office copies it into a message to the bench. */
  user-select:all;
}

/* ==================================================================== rates */
.rate{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  gap:16px;align-items:center;
  padding:14px 16px;border:1px solid var(--line);border-radius:var(--r-sm);
  cursor:pointer;
  transition:border-color .12s var(--ease),background .12s var(--ease);
}
.rate + .rate{margin-top:10px}
.rate:hover{background:var(--surface-sunk)}
.rate:has(input:checked){border-color:var(--brand);background:var(--brand-tint);box-shadow:inset 0 0 0 1px var(--brand)}
.rate input{margin:0;width:18px;height:18px;flex:none}
.rate-who{min-width:0}
.rate-who .prov{font-weight:600}
.rate-who .svc{color:var(--ink-2);font-size:13px}
.rate-who .meta{color:var(--ink-3);font-size:12px}
.rate-price{font-size:19px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;text-align:right}

table.data{width:100%;border-collapse:collapse;font-size:13px}
table.data th{
  text-align:left;font-size:11px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-3);
  padding:0 10px 8px;border-bottom:1px solid var(--line);
}
table.data td{padding:10px;border-bottom:1px solid var(--line);vertical-align:top}
table.data tr:last-child td{border-bottom:0}
table.data .right{text-align:right}

.note{
  border:1px solid var(--line);background:var(--surface-sunk);
  border-radius:var(--r-sm);padding:12px 14px;font-size:13px;color:var(--ink-2);
}
.note strong{color:var(--ink)}
.note--warn{background:var(--warn-tint);border-color:var(--warn-line);color:var(--warn)}
.note--warn strong{color:var(--warn)}
.note--ok{background:var(--ok-tint);border-color:var(--ok-line);color:var(--ok)}
.note--ok strong{color:var(--ok)}
.note--stop{background:var(--stop-tint);border-color:var(--stop-line);color:var(--stop)}
.note--stop strong{color:var(--stop)}

/* =================================================================== forms */
label{display:block;font-size:13px;font-weight:600;margin-bottom:5px}
.bench label{font-size:15px}
.hint{font-weight:400;color:var(--ink-3);font-size:12px}

input[type=text],input[type=password],input[type=number],input[type=search],select,textarea{
  width:100%;
  min-height:var(--tap);
  padding:9px 12px;
  background:var(--surface);
  border:1px solid #86938f;   /* 3.2:1 on a card, 3.0:1 on a sunk panel */
  border-radius:var(--r-sm);
  color:var(--ink);
  font:inherit;
  transition:border-color .12s var(--ease),box-shadow .12s var(--ease);
}
.bench input[type=number]{font-size:19px;font-weight:600}
input:hover,select:hover,textarea:hover{border-color:var(--ink-3)}
input:focus,select:focus,textarea:focus{
  border-color:var(--brand);
  box-shadow:0 0 0 3px var(--brand-tint);
  outline:none;
}
textarea{min-height:92px;resize:vertical;line-height:1.5}
::placeholder{color:var(--ink-3);opacity:1}

.field{margin-bottom:16px}
.field:last-child{margin-bottom:0}

.choices{display:flex;flex-wrap:wrap;gap:8px}
.choice{
  position:relative;margin:0;font-weight:500;
  display:flex;align-items:center;gap:9px;
  min-height:var(--tap);padding:8px 14px;
  border:1px solid var(--line-firm);border-radius:var(--r-sm);
  background:var(--surface);cursor:pointer;
  transition:border-color .12s var(--ease),background .12s var(--ease);
}
.choice:hover{border-color:var(--ink-3);background:var(--surface-sunk)}
.choice input{margin:0;width:17px;height:17px;flex:none}
.choice:has(input:checked){border-color:var(--brand);background:var(--brand-tint);color:var(--brand);font-weight:600}
.choice .rl{color:var(--ink-3);font-weight:500;font-size:12px}
.choice:has(input:checked) .rl{color:var(--brand)}

/* ================================================================= buttons */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:var(--tap);padding:0 18px;
  border-radius:var(--r-sm);border:1px solid transparent;
  background:var(--brand);color:var(--brand-ink);
  font:inherit;font-weight:600;font-size:14px;
  cursor:pointer;white-space:nowrap;
  transition:background .12s var(--ease),border-color .12s var(--ease),color .12s var(--ease);
}
.bench .btn{font-size:16px;padding:0 24px}
.btn:hover{background:var(--brand-hover)}
.btn:disabled{background:var(--line);color:var(--ink-3);cursor:not-allowed;border-color:var(--line)}

.btn--ghost{background:var(--surface);color:var(--ink);border-color:var(--line-firm)}
.btn--ghost:hover{background:var(--surface-sunk);border-color:var(--ink-3)}
.btn--quiet{background:transparent;color:var(--ink-2);border-color:transparent}
.btn--quiet:hover{background:var(--surface-sunk);color:var(--ink)}
.btn--danger{background:var(--surface);color:var(--stop);border-color:var(--stop-line)}
.btn--danger:hover{background:var(--stop-tint)}
.btn--sm{min-height:34px;padding:0 12px;font-size:13px}
.bench .btn--sm{min-height:44px;font-size:14px}
.btn--wide{width:100%}
.btn--lg{min-height:calc(var(--tap) + 8px);font-size:16px;padding:0 26px}
.bench .btn--lg{min-height:72px;font-size:19px}

/* =================================================================== empty */
.empty{
  display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:44px 24px;text-align:center;
}
.empty .art{
  width:44px;height:44px;border-radius:var(--r-pill);
  background:var(--surface-sunk);border:1px solid var(--line);
  display:grid;place-items:center;color:var(--ink-3);margin-bottom:4px;
}
.empty h3{font-size:15px;font-weight:700}
.empty p{color:var(--ink-2);font-size:13px;max-width:46ch}

/* ================================================================ alert bar */
.alert-bar{
  position:sticky;top:0;z-index:15;
  display:flex;align-items:center;gap:12px;
  padding:10px 18px;
  background:var(--brand);color:var(--brand-ink);
  font-size:14px;font-weight:500;
}
.alert-bar .btn{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.28);color:#fff}
.alert-bar .btn:hover{background:rgba(255,255,255,.26)}

.bench .alert-bar{top:52px}

/* ================================================================= receipt */
.receipt{
  border:1px solid var(--ok-line);background:var(--ok-tint);
  border-radius:var(--r);padding:16px var(--pad);
  display:flex;gap:12px;align-items:flex-start;
}
.receipt .ico{color:var(--ok);flex:none;margin-top:1px}
.receipt h3{font-size:15px;font-weight:700;color:var(--ok)}
.receipt p{font-size:13px;color:var(--ink-2);margin-top:2px}

/* ================================================================== dialog */
dialog{
  border:0;padding:0;border-radius:var(--r);
  box-shadow:var(--shadow-pop);
  background:var(--surface);color:var(--ink);
  width:min(560px,calc(100vw - 32px));
  max-height:calc(100vh - 48px);
}
dialog::backdrop{background:rgba(16,33,31,.42);backdrop-filter:blur(2px)}
.dialog-head{padding:var(--pad);border-bottom:1px solid var(--line)}
.dialog-head h2{font-size:16px;font-weight:700}
.dialog-head .line{margin-top:6px;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.dialog-head .nm{color:var(--ink-2);font-size:13px}
.dialog-body{padding:var(--pad);overflow:auto}
.dialog-foot{
  display:flex;justify-content:flex-end;gap:8px;
  padding:14px var(--pad);border-top:1px solid var(--line);
  background:var(--surface-sunk);border-radius:0 0 var(--r) var(--r);
}

/* ================================================================== sign on */
.signon{
  min-height:100vh;display:grid;place-items:center;padding:24px;
}
.signon-card{
  width:min(620px,100%);
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:var(--shadow-2);overflow:hidden;
}
.signon-head{padding:26px var(--pad) 0;text-align:center}
.signon-head .mark{
  width:40px;height:40px;border-radius:var(--r-sm);margin:0 auto 12px;
  background:var(--brand);color:var(--brand-ink);
  display:grid;place-items:center;font-size:13px;font-weight:800;letter-spacing:.06em;
}
.signon-head h1{font-size:19px;font-weight:700}
.signon-head p{margin-top:5px;color:var(--ink-2);font-size:13px}

/* The staff grid. The old build put the name and a bordered role badge on one
   line inside a fixed box: "Jade . OFFICE" overflowed its own edge and the
   separator dangled onto a second line. Here each person is a column — an
   initial, a name, a role — and nothing can collide. */
.people{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:10px}
.person{
  margin:0;display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:14px 10px;min-height:106px;
  border:1px solid var(--line-firm);border-radius:var(--r-sm);
  background:var(--surface);cursor:pointer;text-align:center;
  transition:border-color .12s var(--ease),background .12s var(--ease);
}
.person:hover{border-color:var(--ink-3);background:var(--surface-sunk)}
.person input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
.person .avatar{width:36px;height:36px;font-size:14px}
.person .nm{font-size:14px;font-weight:600;line-height:1.25;word-break:break-word}
.person .rl{font-size:11px;color:var(--ink-3);line-height:1.2}
.person:has(input:checked){
  border-color:var(--brand);background:var(--brand-tint);
  box-shadow:inset 0 0 0 1px var(--brand);
}
.person:has(input:checked) .avatar{background:var(--brand);color:var(--brand-ink)}
.person:has(input:checked) .nm{color:var(--brand)}

/* Every "which one is selected" highlight above uses :has(), which the bench PC
   only understands on a reasonably current browser (Chrome 105+, Safari 15.4+,
   Firefox 121+). If it does not, the card highlights silently do nothing and a
   picker cannot see who they signed on as — so where :has() is missing, the
   native radio comes back and carries the job itself. Belt and braces, no JS,
   and nothing changes on a browser that supports it. */
@supports not selector(:has(*)) {
  .person input,
  .choice input,
  .rate input{
    position:static;opacity:1;width:18px;height:18px;
    clip-path:none;pointer-events:auto;
  }
  .person{flex-direction:row;justify-content:flex-start;text-align:left;gap:10px;min-height:var(--tap)}
  .person .avatar{width:28px;height:28px;font-size:12px}
}

.pinfield input{
  font-family:var(--mono);font-size:24px;font-weight:600;
  letter-spacing:.5em;text-indent:.5em;text-align:center;
  min-height:58px;
}

/* ============================================================ print sheet */
/* The sheet was the best surface in the old build and its logic is unchanged:
   black on white, a real table, a box to tick and a box to initial. What it
   gains is the screen finally agreeing with it. */
.sheet{max-width:none;color:#000;background:#fff}
.sheet-head{
  display:flex;justify-content:space-between;gap:24px;align-items:flex-start;
  padding-bottom:12px;border-bottom:2px solid #000;
}
.sheet-head .num{font-size:28px;font-weight:800;letter-spacing:-.02em}
.sheet-head .so{font-size:13px;margin-top:2px}
.sheet-head .printed{font-size:11px;color:#444;margin-top:8px}
.sheet-head .to{text-align:right;font-size:12px;max-width:44ch}
.sheet-head .to strong{font-size:14px;display:block;margin-bottom:2px}
table.sheet-table{width:100%;border-collapse:collapse;margin-top:14px;font-size:13px}
table.sheet-table th{
  text-align:left;font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  border-bottom:1px solid #000;padding:0 8px 6px;font-weight:700;
}
table.sheet-table td{padding:10px 8px;border-bottom:1px solid #d5d5d5;vertical-align:top}
.sheet-table .flagline{font-size:11px;margin-top:2px}
table.sheet-table .tickbox{width:22px;height:22px;border:1.5px solid #000;border-radius:3px;display:block}
table.sheet-table .initial{width:64px;height:26px;border:1px solid #000;border-radius:3px;display:block}
table.sheet-table .q{font-size:17px;font-weight:700}
table.sheet-table .sku{font-family:var(--mono);font-weight:700;font-size:13px}
table.sheet-table .sub{font-size:11px;color:#555}
.sheet-foot{margin-top:14px;font-size:12px;display:flex;justify-content:space-between;gap:20px}

@media print{
  :root{--pad:0}
  body{background:#fff;font-size:11pt}

  /* Paper is not a screen: px sizes that read well at arm's length on a monitor
     come out 19-38% smaller in print. The sheet is sized in points so the
     picker holding it gets the same legibility the screen promised. */
  table.sheet-table{font-size:10.5pt}
  table.sheet-table th{font-size:7.5pt}
  table.sheet-table .q{font-size:13pt}
  table.sheet-table .sku{font-size:10.5pt}
  table.sheet-table .sub{font-size:8pt;color:#333}
  table.sheet-table .flagline{font-size:8.5pt;color:#000}
  .sheet-head .num{font-size:22pt}
  .sheet-head .so{font-size:10pt}
  .sheet-head .printed{font-size:8pt;color:#333}
  .sheet-head .to{font-size:9.5pt}
  .sheet-head .to strong{font-size:11pt}
  .sheet-foot{font-size:9pt}
  /* A reprint stamp has to survive a glance across a bench. */
  .sheet-head .printed strong{font-size:10pt}
  .side,.benchbar,.alert-bar,.noprint,.topbar-actions{display:none!important}
  .office .app{display:block}
  .content{padding:0;gap:0}
  .card{border:0;box-shadow:none}
  .sheet-head{padding-bottom:10px}
  table.sheet-table td{padding:9px 8px}
  a[href]::after{content:''}
}

/* =============================================================== responsive */
@media (max-width:900px){
  .office .app{grid-template-columns:1fr}
  /* The rail lies down. Everything in it stays on one line and nothing
     shrinks — a clipped "Attention" is worse than a scrollbar. */
  .side{
    position:sticky;top:0;z-index:30;height:auto;
    flex-direction:row;align-items:center;flex-wrap:nowrap;
    border-right:0;border-bottom:1px solid var(--line);
    padding:8px 12px;gap:10px;overflow-x:auto;overscroll-behavior-x:contain;
  }
  /* The product name is on the page heading and the tab title already. On a
     phone that width is better spent keeping "Attention" on screen. */
  .side-brand{padding:0;flex:none}
  .side-brand .wordmark{display:none}
  .side-nav{flex-direction:row;gap:6px;flex:none}
  .nav-item{white-space:nowrap;flex:none;min-height:34px;padding:0 8px;gap:7px;font-size:13px}
  .side-foot{
    margin:0 0 0 auto;padding:0 0 0 10px;border:0;border-left:1px solid var(--line);
    flex:none;display:flex;align-items:center;gap:6px;
  }
  /* The 64px gloved-hand target is for the 1366x768 bench PC, which never
     reaches this breakpoint. On a phone it is a large part of the reason the
     title has no room at all, and nobody picks an order on a phone wearing
     gloves. 44px still clears the touch-target minimum. */
  .bench a.avatar{width:44px;height:44px;font-size:15px}
  /* The benchbar title repeats the page's own <h1> two lines below it. At
     375px the back button and Sign off take 224 of the 339 usable pixels, so
     keeping it meant painting "Pick #1378" under the avatar circle — and once
     that is stopped, showing "P…", a duplicate abbreviated into uselessness.
     Drop it here and give the space to whatever follows. */
  .benchbar .title{display:none}
  .benchbar .title + *{margin-left:auto}

  .side-user{padding:0;flex:none}
  .side-user .who{display:none}
  .side-foot .nav-item .txt{display:none}
  .side-foot .nav-item{padding:0 10px}

  .qrow{
    grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:'ref status' 'cust prog';
    gap:6px 12px;padding:12px 14px;
  }
  .q-ref{grid-area:ref}
  .q-cust{grid-area:cust}
  .q-status{grid-area:status;justify-self:end}
  .q-prog{grid-area:prog;align-items:flex-end}
  .q-age{display:none}

  .att-row{grid-template-columns:minmax(0,1fr)}
  .att-actions{justify-content:flex-start}

  .pickrow{grid-template-columns:auto 48px minmax(0,1fr);gap:12px}
  .pickrow .by{display:none}
  .boxrow{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .boxrow .seq{grid-column:1/-1;margin:0}
  .cartonrow{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .cartonrow > label:first-child,
  .cartonrow > button{grid-column:1/-1}
  .pinrow{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .pinrow > label:first-child,
  .pinrow > button{grid-column:1/-1}
  .pincode{font-size:34px;letter-spacing:.16em;padding:14px}
  .rate{grid-template-columns:auto minmax(0,1fr);gap:12px}
  .rate-price{grid-column:2;text-align:left}
  .sheet-head{flex-direction:column;gap:10px}
  .sheet-head .to{text-align:left}
}
