/* ============================================================
   THE BOARD — five drivers, fifteen loads. Hand-built against the
   Proprietary Algorithm. Section-scoped layout and skin for
   #dispatch-board on the Dispatch page.

   Load order: page style -> nivio-v3-compat.css -> nivio-v3.css -> factors.css
   -> board.css. Every selector is prefixed .tw- and every colour reads a
   --nv- token with a literal fallback, so the component is correct with or
   without the site stylesheets present.

   Signal discipline (v3 p24): before the solve, Signal is the solve button.
   After it, the button hides and Signal moves to the solved board and the
   delta band — one solved state, read as one thing. Nothing else in the
   section carries it. The hand panel is deliberately all-neutral.
   ============================================================ */

.tw{padding:96px 0;background:var(--nv-carbon,#171918);color:var(--nv-text,#F2F0E9)}
.tw *,.tw *::before,.tw *::after{box-sizing:border-box}
.tw [hidden]{display:none !important}

/* ---- head ---- */
.tw-head{display:flex;flex-direction:column;gap:18px}
.tw-k{font-family:var(--nv-font-mono,"Geist Mono",ui-monospace,monospace);
  font-weight:500;font-size:.6875rem;line-height:1.4;letter-spacing:.12em;
  text-transform:uppercase;color:var(--nv-steel,#9EA29F)}
.tw-head h2 .sig{color:var(--nv-signal,#D7E84A)}
/* the client set these line breaks; below 900 the lines are let go to wrap
   on their own rather than forced into a shape the width cannot hold. */
@media(max-width:900px){ .tw-head h2 br.brk{display:none} }
/* This header and #fx's are the two the client asked to run larger than the v3
   h2 step; the partner band stays on 2.375rem. 2.75rem is the largest size that
   holds both headlines to three rows or fewer at every width from 768 up —
   measured: 44px gives 2/2 rows at 1440 and 1200, 2/2 at 1024, 3/3 at 900 and
   768; 46px puts #fx onto a fourth row at 768. Below 768 the v3 mobile step
   (1.6875rem) still applies, so the bump is guarded to 769 and up.
   text-wrap:balance is off because the line breaks here are set deliberately
   with <br class="brk">. */
.tw-head h2{margin:0;font-weight:600;line-height:1.15;letter-spacing:-.02em;
  color:var(--nv-text,#F2F0E9);max-width:none}
@media(min-width:769px){ .tw-head h2{font-size:2.75rem} }
.tw-head p{margin:0;font-size:1.0625rem;line-height:1.6;
  color:var(--nv-steel,#9EA29F);max-width:64ch;text-wrap:pretty}
.tw-head b{color:var(--nv-text,#F2F0E9);font-weight:600}


/* ---- challenge bar: the whole instruction in one line -------------------- */
.tw-challenge{margin-top:36px;padding-bottom:13px;
  border-bottom:1px solid var(--nv-fog,#C8C6BE)}
.tw-challenge .ch-top{display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;margin-bottom:8px}
.tw-challenge .ck{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--nv-steel,#9EA29F)}
.tw-challenge .cc{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  color:var(--nv-steel,#9EA29F);font-variant-numeric:tabular-nums}
/* Steel, not Bone — this line is instruction, not headline, and reading it at
   full Bone gave it the same weight as the h2 two rows above. It now matches the
   intro paragraph exactly: Steel body, Bone bold, so the emphasis inside it
   (the trillion figure) is the only thing that carries full contrast. */
.tw-challenge .cl{margin:0;font-size:.9375rem;line-height:1.45;
  color:var(--nv-steel,#9EA29F);max-width:118ch}
.tw-challenge .cl b{color:var(--nv-text,#F2F0E9);font-weight:600}

/* ---- open loads: one full-width rack above both boards ------------------- */
.tw-open{margin-top:18px;padding:14px 16px 16px;
  border:1px solid var(--nv-border,rgba(242,240,233,.10));
  border-radius:var(--nv-radius,4px)}
.tw-open-k{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--nv-steel,#9EA29F);margin-bottom:11px}
.tw-open.is-empty{padding:11px 16px}
.tw-open.is-empty .tw-open-k{margin-bottom:0}

/* ---- two boards ---- */
.tw-boards{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-top:18px;align-items:stretch}
.tw-panel{border:1px solid var(--nv-border,rgba(242,240,233,.10));
  border-radius:var(--nv-radius,4px);display:flex;flex-direction:column;min-width:0}
/* the algorithm's side sits on graphite from the start, so the two boards read
   as two different places before a single number has been written into it */
.tw-panel.tw-alg{background:var(--nv-graphite,#222523)}

.tw-phead{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 16px;border-bottom:1px solid var(--nv-border,rgba(242,240,233,.10))}
.tw-phead .nm{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;color:var(--nv-fog,#C8C6BE)}
.tw-panel.is-solved .tw-phead .nm{color:var(--nv-signal,#D7E84A)}
.tw-clock{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  color:var(--nv-steel,#9EA29F);font-variant-numeric:tabular-nums}

/* ---- open loads tray ---- */
.tw-tray{padding:14px 16px 16px;border-bottom:1px solid var(--nv-border,rgba(242,240,233,.10))}
.tw-tray-k{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--nv-steel,#9EA29F);margin-bottom:11px}
.tw-tray-chips{display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start}
.tw-open .tw-tray-chips{gap:6px}
.tw-tray.is-empty .tw-tray-chips{min-height:0}
.tw-tray-empty{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  color:var(--nv-steel,#9EA29F);padding:2px 0}

/* ---- chips ---- */
.tw-open .tw-chip{padding:6px 9px;gap:2px}
.tw-chip{display:flex;flex-direction:column;gap:3px;text-align:left;
  font-family:var(--nv-font-mono,"Geist Mono",monospace);
  border:1px solid var(--nv-slate,#3A3D3B);border-radius:var(--nv-radius-sm,3px);
  background:transparent;color:var(--nv-text,#F2F0E9);padding:7px 9px;cursor:grab;
  transition:border-color var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1)),
             background var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1))}
.tw-chip .id{font-size:.6875rem;font-weight:500;letter-spacing:.02em}
.tw-chip .ln{font-size:.6875rem;letter-spacing:.04em;color:var(--nv-steel,#9EA29F);white-space:nowrap}
.tw-chip .rg{font-weight:500;color:var(--nv-fog,#C8C6BE)}
.tw-chip:hover{border-color:var(--nv-steel,#9EA29F)}
.tw-chip:focus-visible{outline:2px solid var(--nv-signal,#D7E84A);outline-offset:2px}
.tw-chip[aria-pressed="true"]{border-color:var(--nv-fog,#C8C6BE);background:rgba(242,240,233,.07)}
.tw-chip.is-dragging{opacity:.4}

.tw-slot .tw-chip{flex-direction:row;align-items:baseline;gap:6px;width:100%;min-width:0;
  overflow:hidden;cursor:pointer;border-color:var(--nv-slate,#3A3D3B);padding:6px 7px 6px 8px}
.tw-slot{min-width:0}
.tw-slot .tw-chip .id{flex:none}
.tw-slot .tw-chip .ln{display:none}
/* the slot is narrow by construction, so the lane is always the short form —
   an ellipsised "Nort…" tells a dispatcher nothing. Full lane on hover and in
   the open rack. */
.tw-slot .tw-chip .lane{font-size:.625rem;letter-spacing:.03em;font-weight:500;
  color:var(--nv-fog,#C8C6BE);white-space:nowrap;flex:none;margin-left:auto}

/* remove control — the click target is the whole chip, the × just says so */
.tw-slot .tw-chip .x{font-size:.8125rem;line-height:1;color:var(--nv-steel,#9EA29F);
  padding-left:2px;flex:none}
.tw-slot .tw-chip:hover .x{color:var(--nv-critical-d,#FF7A5C)}
.tw-slot .tw-chip:hover{border-color:var(--nv-critical-d,#FF7A5C)}

/* the rack lights up as a target when an assigned load is dragged back */
.tw-open.is-target{border-color:var(--nv-signal,#D7E84A);background:rgba(215,232,74,.05)}
.tw-drag-assigned .tw-open-k::after{content:" — drop here to unassign";
  color:var(--nv-fog,#C8C6BE)}

.tw-panel.is-solved .tw-slot .tw-chip{border-color:rgba(215,232,74,.55);
  background:rgba(215,232,74,.10);color:var(--nv-signal,#D7E84A)}
.tw-panel.is-solved .tw-slot .tw-chip .hr,
.tw-panel.is-solved .tw-slot .tw-chip .lane{color:rgba(215,232,74,.62)}
.tw-panel.is-solved .tw-slot .tw-chip{cursor:default}
.tw-panel.is-solved .tw-slot .tw-chip .x{display:none}

/* ---- run receipt ---- */
.tw-receipt{padding:14px 16px 16px;border-bottom:1px solid var(--nv-border,rgba(242,240,233,.10));
  display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.tw-receipt .l{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;color:var(--nv-steel,#9EA29F)}
.tw-receipt .v{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.8125rem;
  letter-spacing:.02em;font-variant-numeric:tabular-nums;color:var(--nv-fog,#C8C6BE);margin-top:8px}

/* ---- driver rows ---- */
.tw-drivers{padding:2px 0}
.tw-drow{display:grid;grid-template-columns:132px 88px 1fr;gap:12px;align-items:center;
  padding:8px 14px;border-bottom:1px solid var(--nv-border,rgba(242,240,233,.10));
  transition:background var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1))}
.tw-drow:last-child{border-bottom:0}
.tw-drow.is-target{background:rgba(242,240,233,.05)}
.tw-drow:focus-visible{outline:2px solid var(--nv-signal,#D7E84A);outline-offset:-2px}
.tw-dmeta{min-width:0}
.tw-dmeta .u{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  font-weight:500;letter-spacing:.04em;color:var(--nv-text,#F2F0E9);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tw-dmeta .y{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.625rem;
  letter-spacing:.02em;color:var(--nv-steel,#9EA29F);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* hours meter — the reason a dispatcher can reason about this board at all */
.tw-hrs{display:flex;flex-direction:column;gap:4px;min-width:0}
.tw-hbar{position:relative;height:3px;background:var(--nv-slate,#3A3D3B);
  border-radius:2px;overflow:hidden}
.tw-hbar i{position:absolute;inset:0 auto 0 0;background:var(--nv-fog,#C8C6BE);
  transition:width var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1))}
.tw-hnum{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.625rem;
  color:var(--nv-steel,#9EA29F);font-variant-numeric:tabular-nums;white-space:nowrap}
.tw-drow.illegal .tw-hbar i{background:var(--nv-critical-d,#FF7A5C)}
.tw-drow.illegal .tw-hnum{color:var(--nv-critical-d,#FF7A5C)}
.tw-panel.is-solved .tw-hbar i{background:rgba(215,232,74,.75)}

.tw-slots{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;min-width:0}
.tw-slot{min-height:30px;display:flex;align-items:stretch;
  border:1px dashed var(--nv-slate,#3A3D3B);border-radius:var(--nv-radius-sm,3px)}
.tw-slot.filled{border-style:solid;border-color:transparent;padding:0}

.tw-drow.illegal .tw-dmeta .y{color:var(--nv-critical-d,#FF7A5C)}
.tw-drow.illegal .tw-slot .tw-chip{border-color:rgba(255,122,92,.55);
  background:rgba(255,122,92,.08);color:var(--nv-critical-d,#FF7A5C)}

/* ---- footer stats ---- */
.tw-stats{margin-top:auto;display:grid;grid-template-columns:repeat(3,1fr);
  border-top:1px solid var(--nv-fog,#C8C6BE)}
.tw-stat{padding:16px;border-right:1px solid var(--nv-border,rgba(242,240,233,.10))}
.tw-stat:last-child{border-right:0}
.tw-stat .l{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;color:var(--nv-steel,#9EA29F)}
.tw-stat .v{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:clamp(1.125rem,2.1vw,1.625rem);line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;margin-top:10px;color:var(--nv-text,#F2F0E9)}
.tw-panel.is-solved .tw-stat .v{color:var(--nv-signal,#D7E84A)}
.tw-stat .f{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  color:var(--nv-steel,#9EA29F);margin-top:6px;min-height:1em}
.tw-stat.warn .v,.tw-stat.warn .f{color:var(--nv-critical-d,#FF7A5C)}

/* While a load is in hand, the algorithm's side reads as closed rather than
   as a target that rejects you — one honest affordance instead of a red X. */
.tw-dragging .tw-alg,.tw-dragging .tw-alg *{cursor:not-allowed}
.tw-dragging .tw-alg{opacity:.55;transition:opacity var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1))}
.tw-dragging .tw-open{border-color:var(--nv-fog,#C8C6BE)}

/* Before the solve the algorithm's panel shows the same five drivers with empty
   slots, so the two boards mirror each other and the answer fills in rather than
   appearing out of an empty box. */
.tw-drow.ghost{opacity:.45}
.tw-drow.ghost .tw-slot{border-style:dashed}

/* ---- solve control ---- */
.tw-solve{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:18px;padding:28px 20px;text-align:center}
.tw-solve p{margin:0;max-width:34ch}
/* nivio-v3-compat pins every /logos/v3/ image to the 20.5px nav size; this one is a
   feature placement, so it needs a higher-specificity override. */
.tw-solve img.tw-logo{height:30px !important;width:auto !important;display:block}
.tw-solve p{margin:0;font-size:.875rem;line-height:1.6;color:var(--nv-steel,#9EA29F)}
.tw-btn{display:inline-flex;align-items:center;gap:9px;font-family:inherit;
  font-size:.875rem;font-weight:600;padding:12px 18px;
  border:1px solid var(--nv-signal,#D7E84A);border-radius:var(--nv-radius-sm,3px);
  background:var(--nv-signal,#D7E84A);color:var(--nv-carbon,#171918);cursor:pointer;
  transition:background var(--nv-fast,120ms) var(--nv-ease,cubic-bezier(.2,0,0,1))}
.tw-btn:hover{background:var(--nv-signal-hov,#C3D53C);border-color:var(--nv-signal-hov,#C3D53C)}
.tw-btn:focus-visible{outline:2px solid var(--nv-signal,#D7E84A);outline-offset:3px}
.tw-btn[disabled]{background:transparent;color:var(--nv-steel,#9EA29F);
  border-color:var(--nv-slate,#3A3D3B);cursor:default}

/* ---- the comparison band: what the whole section is for ---- */
.tw-delta{margin-top:26px;border:1px solid var(--nv-border,rgba(242,240,233,.10));
  border-left:2px solid var(--nv-signal,#D7E84A);border-radius:var(--nv-radius,4px);
  background:var(--nv-graphite,#222523);padding:22px 24px;
  display:grid;grid-template-columns:1.35fr 1fr 1fr 1fr;gap:24px;align-items:center}
.tw-delta .hd{font-size:.9375rem;line-height:1.55;color:var(--nv-steel,#9EA29F)}
/* The lead sentence is a block; emphasis inside the running paragraph is not.
   Both used to be <b>, so every highlighted figure broke onto its own line. */
.tw-delta .hd .tw-lead{display:block;color:var(--nv-text,#F2F0E9);font-weight:600;
  font-size:1.0625rem;margin-bottom:5px}
.tw-delta .hd b{color:var(--nv-text,#F2F0E9);font-weight:600}
.tw-dcell .l{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;color:var(--nv-steel,#9EA29F)}
.tw-dcell .v{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-weight:500;
  font-size:clamp(1.25rem,2.3vw,1.75rem);line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;margin-top:9px;color:var(--nv-signal,#D7E84A)}
.tw-dcell .f{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.6875rem;
  color:var(--nv-steel,#9EA29F);margin-top:6px}

.tw-verdicts{margin-top:26px;display:grid;grid-template-columns:1fr 1fr;gap:24px}
.tw-verdict{border-left:2px solid var(--nv-slate,#3A3D3B);padding:2px 0 2px 16px;
  font-size:.875rem;line-height:1.65;color:var(--nv-steel,#9EA29F)}
.tw-verdict.on{border-left-color:var(--nv-fog,#C8C6BE)}
.tw-verdict b{color:var(--nv-text,#F2F0E9);font-weight:600}
.tw-verdict:empty{display:none}

.tw-fine{margin-top:20px;font-family:var(--nv-font-mono,"Geist Mono",monospace);
  font-size:.6875rem;letter-spacing:.04em;line-height:1.6;
  color:var(--nv-steel,#9EA29F);max-width:82ch}
.tw-fine:empty{display:none;margin:0}
.tw-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

@media(max-width:1100px){
  .tw-delta{grid-template-columns:1fr 1fr 1fr;row-gap:22px}
  .tw-delta .hd{grid-column:1 / -1}
}
@media(max-width:1280px){
  /* two panels side by side leave the slots too narrow for the long lane and a
     full driver column at once — shrink the meta and give the loads the room. */
  .tw-drow{grid-template-columns:100px 66px 1fr;gap:10px;padding:8px 12px}
}
@media(max-width:900px){
  .tw{padding:64px 0}
  .tw-boards{grid-template-columns:1fr}
  .tw-verdicts{grid-template-columns:1fr;gap:18px}
  .tw-drow{grid-template-columns:104px 78px 1fr;gap:9px;padding:8px 12px}
  .tw-open,.tw-phead,.tw-stat,.tw-solve,.tw-receipt{padding-left:12px;padding-right:12px}
  .tw-delta{padding:18px 16px;gap:18px}
}
@media(max-width:560px){
  .tw-delta{grid-template-columns:1fr 1fr}
  .tw-drow{grid-template-columns:1fr 1fr;gap:8px 10px;row-gap:8px}
  .tw-drow .tw-slots{grid-column:1 / -1}
  .tw-challenge .cl{font-size:.875rem}

  /* ---- 2-column compact open-loads tray (tweak-only, see board-room review) ---- */
  .tw-tray-chips{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .tw-open .tw-chip{min-height:44px;justify-content:center}

  /* ---- compact assigned slots: one line, no empty second line ---- */
  .tw-slot{min-height:44px}
  .tw-slot .tw-chip{min-height:44px}
}
@media(prefers-reduced-motion:reduce){
  .tw-chip,.tw-drow,.tw-hbar i{transition:none}
}

/* ---------------------------------------------------------------
   DEEP TEAL ON BONE — client trial, ahead of any brand decision.

   Signal is 1.19:1 on Bone, so light grounds have always used a
   substitute. That substitute is Signal Moss, --nv-signal-moss
   (6.11:1 on Bone, 6.96:1 on white). Overriding the token here
   rather than at each call site means
   every Bone ground on the site moves together — the partner band, the
   factors section, and the Bone #modules on the other five pages.

   Carbon grounds are untouched: Signal Moss is 2.54:1 on Carbon and would
   be unreadable there. Signal stays the dark-ground accent.

   This block is deliberately in the last-loaded stylesheet so it wins
   over nivio-v3-compat and nivio-v3. If the trial is adopted, the value belongs
   in nivio-v3.css and this block comes out.
   --------------------------------------------------------------- */
:root{ --signal-ink-bone:#41630F; }

/* ===========================================================================
   THREE-ROW HEADLINE, AND AIR BETWEEN THE THREE OPENING BLOCKS
   The client's read was that the headline, the paragraph and the challenge
   arrived as one heavy mass. Three changes, in order of how much they do:
     1. the headline steps up to the v3 H1 size and takes three rows, so it
        reads as a statement rather than a paragraph set large;
     2. the gap between the three blocks roughly doubles;
     3. the challenge gets its own surface — a tinted panel with a hairline —
        so it reads as the instruction it is, not as a third paragraph.
   The size is guarded by measurement, not preference: 3.5rem holds three rows
   down to 1240, below which the raised 2.75rem step takes over and below 769
   the v3 mobile step governs.
   =========================================================================== */
@media(min-width:1240px){ .tw-head h2{font-size:3.5rem;line-height:1.09} }
.tw-head{gap:26px}
@media(min-width:1240px){ .tw-head{gap:30px} }
/* The measure is set so the client's paragraph lands on three rows at desktop
   without going past the v3 ceiling of 75 characters. Measured, not guessed. */
.tw-head p{font-size:1.125rem;line-height:1.62;max-width:72ch}

/* the challenge as its own surface */
.tw-challenge{margin-top:44px;padding:20px 24px 18px;border:1px solid rgba(242,240,233,.14);
  border-left:2px solid var(--nv-signal,#D7E84A);border-radius:var(--nv-radius,4px);
  background:rgba(242,240,233,.030)}
.tw-challenge .ch-top{margin-bottom:10px}
.tw-challenge .cl{max-width:104ch}
@media(max-width:768px){ .tw-challenge{margin-top:32px;padding:16px 18px 15px} }

/* ---- the solve reveal ----------------------------------------------------
   A driver waiting for its loads sits back; a chip that has just landed gets
   one pulse of Signal and settles. Both are decoration on a state the board
   already knows, so both are switched off under prefers-reduced-motion and
   the end state is written immediately instead. */
#tw-alg .tw-drow.is-waiting .tw-dmeta,
#tw-alg .tw-drow.is-waiting .tw-hrs{opacity:.45;transition:opacity 220ms ease}
#tw-alg .tw-drow .tw-dmeta,
#tw-alg .tw-drow .tw-hrs{transition:opacity 220ms ease}

@keyframes tw-land{
  0%  {opacity:0;transform:translateY(-5px) scale(.97);
       box-shadow:0 0 0 0 rgba(215,232,74,.55), 0 0 16px 3px rgba(215,232,74,.45)}
  55% {opacity:1;transform:none;
       box-shadow:0 0 0 1px rgba(215,232,74,.65), 0 0 14px 2px rgba(215,232,74,.30)}
  100%{opacity:1;transform:none;
       box-shadow:0 0 0 0 rgba(215,232,74,0), 0 0 0 0 rgba(215,232,74,0)}
}
#tw-alg .tw-chip.just-landed{animation:tw-land 620ms cubic-bezier(.2,0,0,1) both}
#tw-alg.is-solved .tw-slot.filled{transition:background 220ms ease}

@media(prefers-reduced-motion:reduce){
  #tw-alg .tw-chip.just-landed{animation:none}
  #tw-alg .tw-drow.is-waiting .tw-dmeta,
  #tw-alg .tw-drow.is-waiting .tw-hrs{opacity:1}
}

/* ---- the solved panel ----------------------------------------------------
   CLIENT REQUEST, AND A DOCUMENTED EXCEPTION TO V3.
   Brand Standards v3 §Layout/Surfaces reads: "No drop shadows anywhere — not on
   cards, not on modals, not on the logo. Depth comes from a change in surface
   value, not from a shadow." A glow is a shadow by another name, so this is
   outside the standard as written.

   The argument for an exception, if brand wants to grant one: it is not
   decoration and it is not depth. It is a state — the panel glows only once the
   solver has run, it is scoped to one element, and it goes out entirely under
   prefers-reduced-motion. That is the same shape of exception Signal Moss got.

   TO FALL BACK TO THE ON-SYSTEM TREATMENT: delete the box-shadow line below.
   The Signal border and the surface step alone still mark the panel clearly. */
.tw-panel.tw-alg{transition:border-color 420ms cubic-bezier(.2,0,0,1),
                            box-shadow 520ms cubic-bezier(.2,0,0,1)}
.tw-panel.tw-alg.is-solved{
  border-color:rgba(215,232,74,.42);
  box-shadow:0 0 0 1px rgba(215,232,74,.16), 0 0 46px -6px rgba(215,232,74,.38);
}
@media(prefers-reduced-motion:reduce){
  .tw-panel.tw-alg{transition:none}
  .tw-panel.tw-alg.is-solved{box-shadow:0 0 0 1px rgba(215,232,74,.13)}
}

/* reset board — subtle control in the By-hand panel head */
.tw-phead-r{display:inline-flex;align-items:center;gap:12px}
.tw-reset{appearance:none;cursor:pointer;background:transparent;
  border:1px solid var(--nv-line,rgba(242,240,233,.20));color:var(--nv-steel,#9EA29F);
  font:inherit;font-size:.6875rem;font-weight:500;letter-spacing:.06em;text-transform:uppercase;
  padding:4px 10px;border-radius:3px;line-height:1;transition:color 120ms,border-color 120ms}
.tw-reset:hover{color:var(--nv-bone,#F2F0E9);border-color:rgba(242,240,233,.42)}
.tw-reset:focus-visible{outline:2px solid var(--nv-signal,#D7E84A);outline-offset:2px}
.tw-reset[hidden]{display:none}

/* ---- driver-picker sheet: assign without scrolling, <=900px ----------
   z-index stays under .lead's 200 so the sheet can never sit on top of the
   lead modal (NST close_truth review, grill_decision edge_case). */
.tw-sheet-backdrop{position:fixed;inset:0;z-index:150;background:rgba(10,11,10,.55)}
.tw-sheet-backdrop[hidden]{display:none}
.tw-sheet{position:fixed;left:0;right:0;bottom:0;z-index:151;
  background:var(--nv-carbon,#171918);color:var(--nv-text,#F2F0E9);
  border-top:1px solid var(--nv-border,rgba(242,240,233,.14));
  border-radius:12px 12px 0 0;padding:16px 16px calc(16px + env(safe-area-inset-bottom,0px));
  max-height:72vh;overflow-y:auto}
.tw-sheet[hidden]{display:none}
.tw-sheet-head{font-weight:600;font-size:1rem;margin-bottom:12px}
.tw-sheet-list{display:flex;flex-direction:column;gap:8px}
.tw-sheet-row{appearance:none;width:100%;min-height:44px;display:flex;align-items:center;gap:10px;
  text-align:left;font:inherit;padding:10px 12px;cursor:pointer;
  background:transparent;color:var(--nv-text,#F2F0E9);
  border:1px solid var(--nv-border,rgba(242,240,233,.14));border-radius:var(--nv-radius,4px)}
.tw-sheet-row:hover{border-color:var(--nv-signal,#D7E84A)}
.tw-sheet-row:focus-visible{outline:2px solid var(--nv-signal,#D7E84A);outline-offset:2px}
.tw-sheet-row[disabled]{opacity:.45;cursor:not-allowed}
.tw-sheet-row .nm{font-weight:600;flex:1 1 auto;min-width:0}
.tw-sheet-row .rk{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.75rem;
  color:var(--nv-steel,#9EA29F)}
.tw-sheet-row .hrs{font-family:var(--nv-font-mono,"Geist Mono",monospace);font-size:.75rem;
  color:var(--nv-steel,#9EA29F);white-space:nowrap}
.tw-sheet-row .why{flex-basis:100%;font-size:.75rem;color:var(--nv-critical-d,#FF7A5C)}
.tw-sheet-cancel{appearance:none;width:100%;min-height:44px;margin-top:12px;cursor:pointer;
  background:transparent;color:var(--nv-steel,#9EA29F);font:inherit;
  border:1px solid var(--nv-border,rgba(242,240,233,.14));border-radius:var(--nv-radius,4px)}
.tw-sheet-cancel:hover{color:var(--nv-bone,#F2F0E9);border-color:rgba(242,240,233,.42)}

/* the tray chip that opened the sheet stays visibly picked while the sheet is
   open — Signal, not Fog, since Fog is the desktop pick-up state and this is
   a distinct in-progress-assignment state the sheet itself represents. */
.tw-sheet-open .tw-chip[aria-pressed="true"]{border-color:var(--nv-signal,#D7E84A);
  background:rgba(215,232,74,.10)}

/* ===========================================================================
   SECTION HEIGHT, <=560PX — #dispatch-board was 2,294px at 390 (22% off
   NLW.MOBILE.1's opening 2,934px, short of the required 30%/<=2,050px). The
   driver-row header (name, rack, hours) goes to one line so the slots row is
   the only second line a driver costs, and the rhythm between every block
   tightens to the v3 mobile step. This block is deliberately last in the
   file so it wins over the <=900px and <=768px blocks above for the same
   selectors at this width; nothing here touches 561px and up. Both boards
   share driverRow(), so the solved panel gets the same compact row for free. */
@media(max-width:560px){
  .tw{padding:44px 0}
  .tw-head{gap:18px}
  .tw-challenge{margin-top:22px;padding:13px 14px 12px}
  .tw-open{margin-top:10px;padding:11px 13px 12px}
  .tw-open-k{margin-bottom:8px}
  .tw-tray{padding:11px 13px 12px}
  .tw-tray-k{margin-bottom:8px}
  .tw-phead{padding:10px 13px}
  .tw-receipt{padding:11px 13px 12px;gap:10px}
  .tw-stat{padding:11px}
  .tw-solve{padding:18px 16px;gap:13px}
  .tw-delta{margin-top:16px;padding:14px 13px;gap:14px}
  .tw-verdicts{margin-top:16px;gap:14px}
  .tw-fine{margin-top:13px}

  /* driver-row header on one line: name, rack and hours together, so the
     slots row below (already 3-up, see .tw-slots) is the only line a driver
     adds height for — not a second stacked line of its own meta. */
  .tw-drow{padding:6px 12px;gap:6px 10px;row-gap:6px}
  .tw-dmeta{display:flex;align-items:baseline;gap:6px;min-width:0}
  .tw-dmeta .u,.tw-dmeta .y{margin-top:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .tw-hrs{flex-direction:row;align-items:center;gap:7px}
  .tw-hbar{flex:0 0 28px;width:28px}
  .tw-hnum{flex:none}
}
