/* Exception Desk: desk.css
   Token values copied in from design-system/tokens.css (never imported at runtime).
   This demo is self-contained under site/demos/exception-desk/ per hard constraint #2.

   ============================================================
   DIRECTION CONTRACT (plans/exception-desk-design-correction.md section 2,
   copied here verbatim per that spec's build instruction). Binding for every
   rule below. Where anything below conflicts with an older comment in this
   file, this contract wins.
   ============================================================

   THESIS: an operations console that shows its own nervous system: the agent
   working cases on the left of your eye, the plumbing firing on the right,
   one synchronized machine. Refuses: the dashboard-of-hairline-boxes this
   category always ships.

   OWN-WORLD: near-black console ground; ONE structural blue in four tints
   doing all structure; three state colors (working blue, resolved green,
   escalated amber) doing all status; ONE warm accent (amber) reserved for
   escalation moments and focus; isometric depth on the systems rail; mono
   tag-pills for every system label and ID; 16px floor for anything a visitor
   reads.

   STORY: a buyer watches a case, sees the exact systems it touched light up
   as it acts, and leaves believing "this connects to MY stack and I could
   watch it work."

   FIRST VIEWPORT: the intro card over a visibly alive console: the systems
   rail already standing on the right (idle state, softly breathing once),
   the guide rail left, the stage center. Not a black void.

   FORM: dimensional ops-console; the schematic is an isometric rail, not a
   node-and-wire graph.
   ============================================================ */

:root {
  /* ---- Core palette ----
     Design-correction elevation ladder (section 4.2): page ground (darkest) ->
     panel surface (one step up, 1px border) -> raised elements (cards, blocks,
     modals: one more step + stronger border). Dark mode used to set --bg and
     --surface to the identical rgb(0,0,0), which is the literal mechanism
     behind the founder's "lines from all sides" verdict: panels had no fill of
     their own, only a hairline distinguished them from the page. Three real
     steps fix that structurally, before any component rule below even runs. */
  --bg: #05070a;
  --surface: #0d1117;
  --surface-raised: #141a23;
  --surface-well: #080a0d;
  --fg: rgb(255, 255, 255);
  /* ---- Structural blue: ONE hue, four tints (baseten discipline, section 0.1
     of the design correction) ---- */
  --struct-1: #6aa8ff;
  --struct-2: #4d84d6;
  --struct-3: #33517f;
  --struct-4: #1c2c42;
  --accent: var(--struct-1);
  --accent-warm: #ffa53c;
  --accent-cyan: rgb(51, 194, 255);
  --shadow-card: 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-header: 0 1px 0 rgba(255, 255, 255, 0.04), 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-raised: 0 1px 0 rgba(255, 255, 255, 0.05), 0 12px 28px rgba(0, 0, 0, 0.5);
  --shadow-pop: 0 20px 50px rgba(0, 0, 0, 0.65);
  --scrim: rgba(0, 0, 0, 0.86);
  --scrim-soft: rgba(0, 0, 0, 0.6);
  --scrim-strong: rgba(0, 0, 0, 0.92);
  --hover-wash: rgba(255, 255, 255, 0.02);

  /* ---- White-with-alpha ladder ---- */
  --muted-93: rgba(255, 255, 255, 0.93);
  --muted-75: rgba(255, 255, 255, 0.75);
  --muted-70: rgba(255, 255, 255, 0.7);
  --hairline-20: rgba(255, 255, 255, 0.2);
  --border-10: rgba(255, 255, 255, 0.1);
  --border-06: rgba(255, 255, 255, 0.06);
  --border-05: rgba(255, 255, 255, 0.05);
  --muted: var(--muted-93);
  --hairline: var(--hairline-20);
  --border: var(--border-10);
  /* Raised elements (cards, iso blocks, the intro modal) get a visibly stronger
     border than a plain panel, per the elevation ladder: "one more step +
     slightly stronger border." */
  --border-raised: rgba(255, 255, 255, 0.16);

  /* ---- Accent tint ---- */
  --accent-tint: rgba(106, 168, 255, 0.10);
  --accent-tint-strong: rgba(106, 168, 255, 0.18);

  /* ---- State palette ----
     The desk used to be black, white and one blue, so a resolved case, an escalated
     case and one still being worked all looked identical: you had to read every card
     to know what had happened. These three colours are the whole legend.
     Blue = the agent is working it. Green = it closed it. Amber = it stopped and
     handed the call to a human. */
  --state-working: #6aa8ff;
  --state-working-tint: rgba(106, 168, 255, 0.12);
  --state-resolved: #4ade80;
  --state-resolved-tint: rgba(74, 222, 128, 0.12);
  --state-escalated: #ffa53c;
  --state-escalated-tint: rgba(255, 165, 60, 0.12);

  /* ---- Typography ---- */
  --font-display: "Clash Grotesk", "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-sans: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Bumped from 11/13. 50 of the 57 type-token uses in this file were xs or sm, so
     the whole desk was an 11-13px interface and read as unreadably small.

     The clamps below cap at 16-35px and the xs/sm steps are fixed, so every one of
     them saturates well before a 2560 or 3840 wide viewport. The three columns are
     percentages (26/44/30) and keep stretching, so on a 4K display the desk grew and
     the type did not: the same "unreadably small" complaint the bump above answered,
     one viewport class up. --ui-scale is the multiplier that makes the type follow the
     shell. At 1.0 (anything under 1680px) these resolve to exactly the values the
     laptop-width rendering was verified at, so nothing below 1680 moves.

     Design correction (baseten reference, section 0.1): "body floor 16px, 11px
     reserved for labels only." --text-sm and --text-base are now flat 16px
     floors, not clamps that could still land at 15: they carry every trace
     sentence, narration line, card sentence and prose paragraph in the desk.
     --text-xs stays the 12px label/tag-pill/timestamp/eyebrow size; it is never
     used for a sentence a visitor has to read for meaning (audited below). */
  --text-xs: calc(12px * var(--ui-scale));
  --text-sm: calc(16px * var(--ui-scale));
  --text-base: calc(16px * var(--ui-scale));
  --text-md: calc(clamp(18px, 0.19vw + 17.3px, 20px) * var(--ui-scale));
  --text-lg: calc(clamp(20px, 0.28vw + 18.9px, 23px) * var(--ui-scale));
  --text-xl: calc(clamp(22px, 0.38vw + 20.6px, 26px) * var(--ui-scale));
  --text-2xl: calc(clamp(26px, 0.47vw + 24.2px, 31px) * var(--ui-scale));
  --text-3xl: calc(clamp(30px, 0.66vw + 27.5px, 38px) * var(--ui-scale));
  /* New: the sim clock and other single "the number IS the message" readouts
     (foundry P6's KPI treatment, section 0.3 answer key). */
  --text-4xl: calc(clamp(34px, 0.9vw + 30px, 44px) * var(--ui-scale));
  /* Tight negative tracking on display sizes (baseten section 0.1: "-1.76 to
     -1.92px on headings reads sharp at scale"). Applied via a token so every
     heading-tier selector pulls the same value instead of hand-tuned ems. */
  --tracking-tight: -0.02em;

  /* ---- Spacing scale (4/8 base) ----
     Scaled by the same factor as the type. Bigger text inside chrome that stayed put
     would read as cramped, which is the failure mode the Factory OS correction calls
     out: the shell has to grow with the words it frames. Every padding, gap and inset
     in this file goes through these tokens, so scaling here scales the chrome. */
  --space-1: calc(4px * var(--ui-scale));
  --space-2: calc(8px * var(--ui-scale));
  --space-3: calc(12px * var(--ui-scale));
  --space-4: calc(16px * var(--ui-scale));
  --space-5: calc(20px * var(--ui-scale));
  --space-6: calc(24px * var(--ui-scale));
  --space-7: calc(32px * var(--ui-scale));
  --space-8: calc(40px * var(--ui-scale));

  /* ---- Border radii ---- */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-pill: 100px;

  /* ---- Motion ---- */
  --ease-out-expo: cubic-bezier(0.165, 0.84, 0.44, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast: 200ms;
  --dur-base: 500ms;

  /* ---- Viewport scale ----
     The multiplier behind every type and spacing token above, and the panel widths
     further down. Declared here at its 1.0 identity so the tokens resolve on any
     viewport; the steps below raise it. Unitless on purpose: it multiplies px values
     rather than being one, so a single variable moves type and chrome together. */
  --ui-scale: 1;

  /* The desk stops growing past this and centers. This is the real 4K fix: the three
     columns are percentages, so without a cap they balloon to ~1600px each on a 3840
     screen and the text looks tiny beside them. Capping the shell keeps the columns a
     reading width, which is why the scale ceiling above can stay gentle. Below this
     width the cap does nothing, so the reviewed laptop rendering is untouched. */
  --desk-max: 1900px;
}

/* Gentle ceiling of 1.15, not the 2.0 the Factory OS shell uses. That spec is for a
   full-bleed app; this desk is width-capped (--desk-max below) and centered, so the
   columns no longer balloon on a wide screen and the text no longer has to chase them.
   All the scale does now is a small bump for viewing distance on a physically large
   display. A 2.0 here read as a 2x zoom (a case card at 1603px with 32px body text),
   which is the "looks zoomed in" the founder caught. Below 1680 the scale stays 1.0,
   so the laptop rendering this desk was reviewed at is untouched. Stepped, not fluid,
   so the verification viewports are what actually ship. */
@media (min-width: 1680px) { :root { --ui-scale: 1.07; } }
@media (min-width: 2240px) { :root { --ui-scale: 1.15; } }

/* ---- Light theme ----
   This is a content-dense dashboard, and read in daylight the all-black surface made
   the three columns bleed into one another. In light the page is grey and the cards
   are white, so every panel and every case has a real edge.

   The state colours cannot carry over as-is: #6aa8ff / #4ade80 / #ffa53c are tuned
   for a black background and fall below readable contrast on white. Each gets a
   darker twin here, same meaning, same legend.

   Written once and applied from two places: the OS preference (for anyone who has not
   touched the toggle) and an explicit data-theme, which always wins. */
:root[data-theme="light"],
:root[data-theme="light"] body {
  color-scheme: light;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) { color-scheme: light; }
}

:root[data-theme="light"] {
  --bg: #eceff3;
  --surface: #ffffff;
  /* White cannot go lighter, so "raised" in light mode is carried by
     --border-raised and --shadow-raised below, not a third fill tone; the
     recessed well goes the other direction, a step back toward the page. */
  --surface-raised: #ffffff;
  --surface-well: #f2f4f7;
  --fg: #0e1420;
  --struct-1: #1a63c9;
  --struct-2: #3f7fd1;
  --struct-3: #7fa6d9;
  --struct-4: #c3d4ea;
  --accent: var(--struct-1);
  --accent-warm: #b45309;
  --accent-cyan: #0e7490;

  --muted-93: rgba(14, 20, 32, 0.93);
  --muted-75: rgba(14, 20, 32, 0.70);
  --muted-70: rgba(14, 20, 32, 0.62);
  --hairline-20: rgba(14, 20, 32, 0.20);
  --border-10: rgba(14, 20, 32, 0.14);
  --border-06: rgba(14, 20, 32, 0.10);
  --border-05: rgba(14, 20, 32, 0.07);
  --border-raised: rgba(14, 20, 32, 0.24);

  --accent-tint: rgba(26, 99, 201, 0.08);
  --accent-tint-strong: rgba(26, 99, 201, 0.15);

  --state-working: #1a63c9;
  --state-working-tint: rgba(26, 99, 201, 0.10);
  --state-resolved: #15803d;
  --state-resolved-tint: rgba(21, 128, 61, 0.10);
  --state-escalated: #b45309;
  --state-escalated-tint: rgba(180, 83, 9, 0.10);

  --shadow-card: 0 1px 2px rgba(14, 20, 32, 0.06), 0 8px 24px rgba(14, 20, 32, 0.08);
  --shadow-header: 0 1px 0 rgba(14, 20, 32, 0.06), 0 8px 24px rgba(14, 20, 32, 0.06);
  --shadow-raised: 0 2px 4px rgba(14, 20, 32, 0.08), 0 12px 28px rgba(14, 20, 32, 0.10);
  --shadow-pop: 0 20px 50px rgba(14, 20, 32, 0.18);
  --scrim: rgba(14, 20, 32, 0.55);
  --scrim-soft: rgba(14, 20, 32, 0.40);
  --scrim-strong: rgba(14, 20, 32, 0.65);
  --hover-wash: rgba(14, 20, 32, 0.03);
}

/* Same values again for visitors on a light OS who have never touched the toggle.
   `:not([data-theme="dark"])` means an explicit dark choice still beats the OS. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]):not([data-theme="light"]) {
    --bg: #eceff3;
    --surface: #ffffff;
    --surface-raised: #ffffff;
    --surface-well: #f2f4f7;
    --fg: #0e1420;
    --struct-1: #1a63c9;
    --struct-2: #3f7fd1;
    --struct-3: #7fa6d9;
    --struct-4: #c3d4ea;
    --accent: var(--struct-1);
    --accent-warm: #b45309;
    --accent-cyan: #0e7490;

    --muted-93: rgba(14, 20, 32, 0.93);
    --muted-75: rgba(14, 20, 32, 0.70);
    --muted-70: rgba(14, 20, 32, 0.62);
    --hairline-20: rgba(14, 20, 32, 0.20);
    --border-10: rgba(14, 20, 32, 0.14);
    --border-06: rgba(14, 20, 32, 0.10);
    --border-05: rgba(14, 20, 32, 0.07);
    --border-raised: rgba(14, 20, 32, 0.24);

    --accent-tint: rgba(26, 99, 201, 0.08);
    --accent-tint-strong: rgba(26, 99, 201, 0.15);

    --state-working: #1a63c9;
    --state-working-tint: rgba(26, 99, 201, 0.10);
    --state-resolved: #15803d;
    --state-resolved-tint: rgba(21, 128, 61, 0.10);
    --state-escalated: #b45309;
    --state-escalated-tint: rgba(180, 83, 9, 0.10);

    --shadow-card: 0 1px 2px rgba(14, 20, 32, 0.06), 0 8px 24px rgba(14, 20, 32, 0.08);
    --shadow-header: 0 1px 0 rgba(14, 20, 32, 0.06), 0 8px 24px rgba(14, 20, 32, 0.06);
    --shadow-raised: 0 2px 4px rgba(14, 20, 32, 0.08), 0 12px 28px rgba(14, 20, 32, 0.10);
    --shadow-pop: 0 20px 50px rgba(14, 20, 32, 0.18);
    --scrim: rgba(14, 20, 32, 0.55);
    --scrim-soft: rgba(14, 20, 32, 0.40);
    --scrim-strong: rgba(14, 20, 32, 0.65);
    --hover-wash: rgba(14, 20, 32, 0.03);
  }
}

* { box-sizing: border-box; }

/* Author rules on overlay containers below set their own `display`, which beats
   the user-agent [hidden] rule at equal specificity. This restores `hidden`. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  /* True application shell (design-correction section 8, C1: "an OS occupies,
     a webpage scrolls"). height:100% on both, not min-height: the shell is a
     fixed box, not a page that grows to fit its content. */
  height: 100%;
}

body {
  height: 100vh;
  /* The document itself never scrolls; every scroll happens inside one of
     .desk-main's own columns (each already carries its own overflow-y:auto).
     This is what "no page scroll at the shell level" means structurally. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* The page background shows in the side margins once the desk hits --desk-max and
     centers, so the desk reads as one island on a wide screen instead of stretching
     edge to edge. */
  align-items: center;
}

/* The top-level strips (header, tabs, main) are direct flex children of body
   with no wrapper, so each carries the cap itself and they stay aligned.
   width 100% keeps them full-bleed below the cap (align-items: center would
   otherwise shrink them to content); max-width centers them above it. The
   footer used to be a fourth strip here; its content now lives inside the
   worklog panel's own internal scroll (C1), so it no longer needs this rule
   at the body level. */
.desk-header,
.narration-strip,
.desk-tabs,
.desk-main {
  width: 100%;
  max-width: var(--desk-max);
  flex: 0 0 auto;
}
/* .desk-main is the one flexible strip: it fills whatever height the fixed
   rows above it (header, narration, tabs) do not use, and min-height:0 lets
   its own grid children actually shrink to that space instead of forcing
   the flex column (and therefore the page) to grow past 100vh. */
.desk-main { flex: 1 1 auto; min-height: 0; }
/* The intro / drawer / manual overlays are position: fixed full-screen modals and are
   deliberately NOT in the list above: they cover the whole viewport, not the capped
   desk. */

/* ---- Header strip ---- */

/* Real status bar (design correction section 4.1), a three-column grid so the
   clock sits genuinely centered rather than wherever flexbox happens to land
   it once the side groups are uneven widths. */
.desk-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--hairline);
  position: sticky;
  top: 0;
  background: var(--surface);
  box-shadow: var(--shadow-header);
  z-index: 10;
}

.desk-header__left {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.desk-header__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}

.desk-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-75);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
}

.desk-header__controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  justify-self: end;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* The sim clock: large mono with a shift label, per section 4.1. Centered in
   its own grid column so it reads as chrome furniture, not a stray number. */
.desk-header__clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: center;
  line-height: 1;
}
.desk-header__clock-time {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--fg);
}
.desk-header__clock-label {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-70);
}
@media (max-width: 640px) {
  /* A three-column grid with a centered clock has nowhere to shrink to on a
     phone-width header; the clock is a nice-to-have on the status bar and
     the shift is always readable on every card, so it steps aside first. */
  .desk-header { grid-template-columns: 1fr auto; }
  .desk-header__clock { display: none; }
}

.desk-btn {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  /* The end card's primary CTA is an <a>, not a <button>, so without this it
     carries the browser's default underline and reads as a text link sitting in
     a box next to the un-underlined Replay button. */
  text-decoration: none;
  transition: border-color var(--dur-base) var(--ease-out-expo), background var(--dur-base) var(--ease-out-expo);
}

.desk-btn:hover { border-color: var(--hairline); }
.desk-btn:disabled { opacity: 0.35; cursor: not-allowed; }

/* Status-bar controls (design correction section 4.1: "designed controls, not
   browser-default-looking buttons"). Filled, not transparent-outline, so they
   read as real product chrome sitting on the bar rather than text with a box
   drawn around it. */
.desk-btn--console {
  background: var(--surface-raised);
  border-color: var(--border-raised);
  box-shadow: var(--shadow-raised);
}
.desk-btn--console:hover {
  border-color: var(--struct-2);
  background: var(--surface-well);
}

.desk-btn--danger { border-color: rgba(255, 90, 90, 0.3); color: rgb(255, 140, 140); }

.desk-btn--primary {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--accent);
}
.desk-btn--primary:hover { background: var(--accent-tint-strong); }

.desk-speed-group { display: flex; align-items: center; gap: var(--space-1); }

/* Names the control group, so "1x / 2x / 4x" is not left to the visitor to decode. */
.desk-ctrl-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin-right: var(--space-1);
}

/* Icon + word, so the theme button says what pressing it does. */
.desk-btn--icon { display: inline-flex; align-items: center; gap: var(--space-2); }
.desk-btn__icon { display: inline-flex; }

.desk-btn--speed.is-active {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--accent);
}

/* Tertiary link under the two intro buttons. */
.intro-card__tourlink {
  display: inline-block;
  margin-top: var(--space-4);
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--muted-70);
  text-decoration: underline;
  cursor: pointer;
}
.intro-card__tourlink:hover { color: var(--fg); }

/* ---- Guided tour panel ----
   Lives in the left column, in the layout. It used to be a popup docked across the
   bottom of the viewport, which meant it sat on top of the cards it was describing and
   had to chase them as they grew (artifact text types out, actions reveal on timers),
   so the page jumped up and down and you could not follow what was happening. A column
   cannot be covered and never has to scroll anything, which deleted a whole class of
   bug along with it. */
.guide {
  border: 1px solid var(--state-working);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: var(--space-5);
  /* True application shell (design-correction section 8, C1): the page never
     scrolls, so position:sticky had nothing left to stick against (it was a
     page-scroll-era mechanic: "sticks as the page scrolls"). #guide now
     behaves exactly like every other grid cell in .desk-main: default
     align-self:stretch fills its row exactly (previously overridden to
     align-self:start + an approximated max-height, which is what let it
     render 12px taller than its actual cell and overflow the shell), and
     it scrolls internally the same way a .desk-panel does. */
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

/* ---- The spotlight ----
   Until the visitor has picked a case there is nothing to see in the worklog and nothing
   in the ledger, so both are frosted back and made untouchable. That leaves exactly one
   live thing on the screen, and no question about where to start. The frost lifts the
   moment they pick, and never comes back. */
body.awaiting-pick .desk-panel--worklog,
body.awaiting-pick .desk-panel--systems,
body.awaiting-pick .desk-panel--inbound,
body.awaiting-pick .narration-strip {
  filter: blur(4px) saturate(0.5);
  opacity: 0.35;
  pointer-events: none;
  user-select: none;
}

.desk-panel--worklog,
.desk-panel--systems,
.desk-panel--inbound,
.narration-strip {
  transition: filter var(--dur-base) var(--ease-out-expo),
              opacity var(--dur-base) var(--ease-out-expo);
}

/* And the one thing they CAN touch says so. */
body.awaiting-pick #guide {
  border-color: var(--state-working);
  box-shadow: 0 0 0 1px var(--state-working), 0 0 44px var(--state-working-tint);
  animation: guideBeacon 2.4s ease-in-out infinite;
}
@keyframes guideBeacon {
  0%, 100% { box-shadow: 0 0 0 1px var(--state-working), 0 0 24px var(--state-working-tint); }
  50%      { box-shadow: 0 0 0 1px var(--state-working), 0 0 56px var(--state-working-tint); }
}

.guide-prompt {
  margin: var(--space-4) 0 0;
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--state-working-tint);
  color: var(--state-working);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.45;
}

@media (prefers-reduced-motion: reduce) {
  body.awaiting-pick #guide { animation: none; }
  .desk-panel--worklog,
  .desk-panel--systems,
  .desk-panel--inbound,
  .narration-strip { transition: none; }
}

.guide-list {
  list-style: none;
  margin: var(--space-4) 0;
  padding: 0 2px 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.guide-case {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  width: 100%;
  padding: var(--space-3);
  /* A filled row, not bare text on the panel void (elevation rule, section
     4.2): the row is its own small surface, one step off the guide panel. */
  background: var(--surface-well);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border); /* impeccable-disable-line side-tab: spec-mandated state stripe / active accent bar, design-correction section 4.3-4.4 */
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out-expo), border-color var(--dur-fast) var(--ease-out-expo);
}
.guide-case:hover:not([disabled]) { background: var(--state-working-tint); border-color: var(--state-working); }
.guide-case:focus-visible { outline: 2px solid var(--state-working); outline-offset: 2px; }

.guide-case__label {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--fg);
}
.guide-case__blurb {
  font-size: var(--text-xs);
  line-height: 1.45;
  color: var(--muted-70);
}

/* Group headers. Fourteen flat rows is a wall; grouped, the list answers "which one
   should I click?" without the visitor having to read every row. */
.guide-group {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-5) 0 var(--space-2);
}
.guide-group:first-child { margin-top: 0; }
.guide-group__title {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
  font-weight: 600;
}
.guide-group__count {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: var(--border-10);
  color: var(--muted-70);
}
.guide-group__note {
  flex: 1 1 100%;
  font-size: var(--text-xs);
  line-height: 1.4;
  color: var(--muted-70);
}
.guide-group__cases {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The group already says what these cases are, so the per-row tags are gone.
   "decide" used to sit at amber at rest, which put two warm-accent rows on
   screen simultaneously in the picker (this group always has 2+ members):
   the design correction reserves the warm accent for actual escalation
   moments (section 4, banned list: "more than one warm-accent element at
   rest per viewport"). A picker row is not yet an escalation, just a
   category, so it gets the structural tint instead; the row still earns
   full amber once it actually lands in the escalated state below. */
.guide-group__cases .guide-case[data-group="race"] { border-left-color: var(--state-working); }
.guide-group__cases .guide-case[data-group="decide"] { border-left-color: var(--struct-2); }

.guide-case__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
}
.guide-case__time {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  flex: 0 0 auto;
}
/* .guide-case__tags / __tag / __tag--decide lived here and were deleted 2026-07-17.
   Nothing in desk.js or index.html ever rendered them: the case list carries its
   grouping in the group headings, which is where the 2026-07-15 pass put it. They
   surfaced during the --ui-scale work as one of two rules declaring a raw 10px, and
   the only reason to keep them would have been to scale text nobody can see. */

/* The case the visitor is in right now. */
.guide-case[data-state="current"] {
  border-left-color: var(--state-working);
  background: var(--state-working-tint);
}
/* Watched already. A tick, not a lock: this is a demo, and a visitor who has seen a case
   should be able to see it again. Locking the row behind the tick just told them they
   had used it up. */
.guide-case[data-state="done"] { border-left-color: var(--state-resolved); }
.guide-case[data-state="done"] .guide-case__label::after {
  content: " \2713";
  color: var(--state-resolved);
}

/* Both choices, on the card, next to each other, so the comparison reads as a comparison.
   .desk-btn--manual is full-width on its own, which shoved the by-hand button onto its
   own line and broke the pairing, so inside the pair they share the row instead. */
.case-card__choose { display: flex; gap: var(--space-2); align-items: stretch; }
.case-card__choose .desk-btn { width: auto; flex: 1 1 0; margin: 0; }
@media (max-width: 900px) {
  .case-card__choose { flex-direction: column; }
}

/* The tour's controls on the card. Separated from the case content by a rule, so it
   reads as "what do I do now" rather than as more of the agent's output. */
.case-card__guided:not(:empty) {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

/* The step commentary now sits in the worklog column, directly above the card it is
   describing, so it reads as the voice explaining the agent rather than a note pinned to
   the menu on the other side of the screen. */
.guide-step {
  flex: 0 0 auto;
  border: 1px solid var(--state-working);
  border-left: 3px solid var(--state-working); /* impeccable-disable-line side-tab: spec-mandated state stripe / active accent bar, design-correction section 4.3-4.4 */
  border-radius: var(--radius-md);
  background: var(--state-working-tint);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-4);
}
.guide__run { flex: 0 0 auto; }
.guide-step__n {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--state-working);
  margin: 0 0 var(--space-2);
}
.guide-step__title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  margin: 0 0 var(--space-2);
  color: var(--fg);
}
.guide-step__body {
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--muted-75);
  margin: 0 0 var(--space-4);
}
.guide-step__next { width: 100%; }
.guide__run { width: 100%; }


/* ---- Three-panel layout ---- */

.desk-main {
  flex: 1;
  display: grid;
  grid-template-columns: 26% 44% 30%;
  /* Two rows so the guide can sit on top of the left column with Inbound beneath it,
     while the worklog and the ledger run the full height alongside. */
  grid-template-rows: auto 1fr;
  gap: 1px;
  background: var(--border-06);
  min-height: 0;
}

/* When the visitor picks "just run the shift" the guide is [hidden], so row 1 has no
   item in it and the `auto` track collapses to zero on its own. Inbound then fills the
   column and the layout is byte-for-byte the old three-panel desk. */
.desk-main > #guide { grid-column: 1; grid-row: 1; }
.desk-panel--inbound { grid-column: 1; grid-row: 2; }
.desk-panel--worklog { grid-column: 2; grid-row: 1 / -1; }
.desk-panel--systems  { grid-column: 3; grid-row: 1 / -1; }

/* During the tour the guide owns the left column and Inbound steps aside. Sharing the
   column just squeezed Inbound down to a sliver, and the whole complaint being answered
   here is that too much was happening at once: while we are teaching one case, three
   panels is one fewer thing to track than four. Inbound comes straight back the moment
   the shift runs. */
@media (min-width: 900px) {
  body.guided .desk-main { grid-template-rows: 1fr; }
  body.guided .desk-main > #guide { grid-row: 1; }
  body.guided .desk-panel--inbound { display: none; }
}

/* ---- One case at a time ----
   The worklog is an append-only feed, which is right while the night is playing: the
   cases pile up and that IS the point. But the tour is the opposite job. You are
   studying one case, and appending it below the ones already handled meant the page had
   to scroll down to find it and it was unclear which card you had just clicked on.
   During the tour the worklog shows the case you picked and nothing else. The others
   are not lost: they carry a green check in the guide and they are counted in the
   ledger. The full feed comes back the moment the shift runs. */
body.guided .case-card { display: none; }
body.guided .case-card.is-focus { display: block; }

.desk-panel {
  background: var(--surface);
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: var(--space-5);
  overflow-y: auto;
}

.desk-panel__title {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin: 0 0 var(--space-4);
}

.desk-panel__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  flex: 1;
}

.desk-panel__live {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--hairline);
}

.desk-panel__caption {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: calc(var(--space-4) * -1 + 2px) 0 var(--space-4);
}

/* ---- Orientation layer: intro card ---- */

.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: var(--scrim);
  backdrop-filter: blur(6px);
}

.intro-card {
  /* Measure scales with the type it holds. A fixed 560px box around 2x text would set
     a much narrower line and undo the legibility the scale just bought. */
  max-width: calc(560px * var(--ui-scale));
  width: 100%;
  /* Raised (elevation ladder, section 4.2): the modal is one step ABOVE a
     plain panel with a stronger border, not the same --surface fill as the
     page behind the scrim. */
  border: 1px solid var(--border-raised);
  border-radius: var(--radius-lg);
  padding: var(--space-8) var(--space-7);
  background: var(--surface-raised);
  box-shadow: var(--shadow-raised);
  text-align: center;
}

.intro-card__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  color: var(--accent-cyan);
  margin: 0 0 var(--space-4);
}

.intro-card__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-4);
}

.intro-card__body {
  font-size: var(--text-md);
  color: var(--muted-75);
  margin: 0 0 var(--space-6);
  line-height: 1.5;
}

.intro-card__systems-line {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: calc(var(--space-6) * -1 + var(--space-2)) 0 var(--space-6);
  line-height: 1.5;
}

.intro-card__note {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: var(--space-5) 0 var(--space-2);
}

.intro-card__countdown {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  margin: 0;
}

/* ---- Narration strip ---- */

/* The narration is the only plain-English account of what the agent just did, and it
   was 13px mono at 75% white: the one line that explains the demo was the easiest
   thing on screen to miss. Give it a left accent rule, real size, and full contrast. */
.narration-strip {
  border-bottom: 1px solid var(--hairline);
  border-left: 3px solid var(--state-working); /* impeccable-disable-line side-tab: spec-mandated state stripe / active accent bar, design-correction section 4.3-4.4 */
  padding: var(--space-3) var(--space-6);
  background: linear-gradient(90deg, var(--state-working-tint), transparent 55%);
}

.narration-strip__text {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--fg);
}

/* ---- Mobile tabs (hidden on desktop, shown under 900px) ---- */

.desk-tabs {
  display: none;
}

.desk-tab {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-70);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
}

.desk-tab.is-active {
  color: var(--fg);
  border-bottom-color: var(--accent);
}

.tab-badge {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: transparent;
  margin-left: var(--space-1);
  vertical-align: middle;
}

.tab-badge.is-pulsing {
  background: rgb(255, 160, 60);
  animation: badge-pulse 1.1s var(--ease-in-out) infinite;
}

@keyframes badge-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(1.4); }
}

/* ---- Channel identity ---- */

.ch-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: var(--space-1);
  background: var(--muted-70);
}
.ch-dot[data-channel="email"] { background: var(--accent-cyan); }
.ch-dot[data-channel="sms"] { background: rgb(140, 220, 140); }
.ch-dot[data-channel="edi"] { background: var(--accent); }
.ch-dot[data-channel="tms"] { background: rgb(255, 190, 90); }

/* ---- Inbound feed items ---- */

.inbound-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  width: 100%;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  /* A nested row needs its own fill distinct from the panel it sits in
     (elevation rule); --surface alone matched the panel exactly, so the
     only thing marking the row's edge was its hairline border. */
  background: var(--surface-well);
  color: var(--fg);
  cursor: pointer;
  transition: border-color var(--dur-base) var(--ease-out-expo);
}
.inbound-item:hover { border-color: var(--hairline); background: var(--hover-wash); }
.inbound-item.is-hidden { display: none; }

.inbound-item__head {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  display: flex;
  align-items: center;
}

.inbound-item__subject {
  font-size: var(--text-sm);
  font-weight: 600;
}

.inbound-item__preview {
  font-size: var(--text-sm);
  color: var(--muted-75);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.desk-earlier-btn {
  align-self: center;
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-75);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
}
.desk-earlier-btn:hover { border-color: var(--hairline); }

/* ---- Case cards (worklog) ---- */

.case-card {
  /* Raised, per the elevation ladder: a card is one step up from the panel
     it sits in, with a visibly stronger border, not the same fill as its
     surroundings distinguished only by a hairline. */
  border: 1px solid var(--border-raised);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-raised);
  box-shadow: var(--shadow-raised);
  transition: border-color var(--dur-base) var(--ease-out-expo), box-shadow var(--dur-base) var(--ease-out-expo),
    transform var(--dur-base) var(--ease-out-expo);
  cursor: pointer;
}

.case-card:hover {
  border-color: var(--struct-2);
  box-shadow: var(--shadow-card), var(--shadow-raised);
  transform: translateY(-1px);
}

.case-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- State colour on the card itself ----
   A 3px left stripe carries the state, so you can parse the whole worklog without
   reading a word: blue is being worked, green closed itself, amber needs a human. */
.case-card {
  border-left: 3px solid var(--border); /* impeccable-disable-line side-tab: spec-mandated state stripe / active accent bar, design-correction section 4.3-4.4 */
}
.case-card[data-phase="detected"],
.case-card[data-phase="classified"],
.case-card[data-phase="acting"] {
  border-left-color: var(--state-working);
  background: linear-gradient(90deg, var(--state-working-tint), transparent 40%);
}
.case-card[data-phase="resolved"] { border-left-color: var(--state-resolved); }
.case-card[data-phase="escalated"] {
  border-color: rgba(255, 165, 60, 0.35);
  border-left-color: var(--state-escalated);
  background: linear-gradient(90deg, var(--state-escalated-tint), transparent 40%);
}

/* Settled cases recede so the eye lands on the one the agent is working now. They
   come back to full strength on hover, since they are still worth opening. */
.case-card[data-collapsed="1"] { opacity: 0.62; }
.case-card[data-collapsed="1"]:hover,
.case-card[data-collapsed="1"]:focus-visible { opacity: 1; }

.case-card--live {
  border-color: var(--accent-cyan);
}

.case-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  color: var(--muted-70);
  margin-bottom: var(--space-3);
}

/* Mono tag-pill (baseten grammar, section 0.1): every system label and ID in
   this desk uses the same pill, never a bare mono word. */
.case-card__id {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--struct-1);
  border: 1px solid var(--struct-3);
  border-radius: var(--radius-sm);
  padding: 2px var(--space-2);
  background: var(--surface-well);
}

.case-card__channel { display: flex; align-items: center; }
.case-card__phase-badge { margin-left: auto; }

/* Filled, not a faint outline. The old badge was a 1px 10%-alpha border, which read
   as grey at every phase, so resolved and escalated looked the same. */
.case-card__phase-badge {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
  padding: 3px var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}
.case-card[data-phase="detected"] .case-card__phase-badge,
.case-card[data-phase="classified"] .case-card__phase-badge,
.case-card[data-phase="acting"] .case-card__phase-badge {
  border-color: var(--state-working);
  background: var(--state-working-tint);
  color: var(--state-working);
}
.case-card[data-phase="resolved"] .case-card__phase-badge {
  border-color: var(--state-resolved);
  background: var(--state-resolved-tint);
  color: var(--state-resolved);
}
.case-card[data-phase="escalated"] .case-card__phase-badge {
  border-color: var(--state-escalated);
  background: var(--state-escalated-tint);
  color: var(--state-escalated);
}

/* ---- Agent progress tracker ----
   Design correction section 4.3: "the four-step tracker as a designed
   component (filled progress, not text)." Rebuilt as four segments that FILL
   solid as the agent reaches them, not a dotted timeline with a connecting
   hairline; the dot element is repurposed as the fill bar itself so desk.js's
   existing data-state wiring needs no changes. */
.case-track {
  list-style: none;
  display: flex;
  gap: 3px;
  margin: 0 0 var(--space-4);
  padding: 0;
}
.case-track__step {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1;
  min-width: 0;
}
.case-track__dot {
  display: block;
  width: 100%;
  height: 4px;
  border-radius: var(--radius-sm);
  background: var(--border-raised);
  transition: background var(--dur-base) var(--ease-out-expo), box-shadow var(--dur-base) var(--ease-out-expo);
}
.case-track__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted-70);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--dur-base) var(--ease-out-expo);
}

/* Steps the agent has already passed: filled, full strength. */
.case-track__step[data-state="done"] .case-track__dot { background: var(--struct-1); }
.case-track__step[data-state="done"] .case-track__label { color: var(--muted-75); }
/* The step it is in right now: filled and it pulses so the eye finds it. */
.case-track__step[data-state="current"] .case-track__dot {
  background: var(--struct-1);
  box-shadow: 0 0 0 3px var(--state-working-tint);
  animation: trackPulse 1.4s ease-in-out infinite;
}
.case-track__step[data-state="current"] .case-track__label { color: var(--struct-1); font-weight: 600; }
@keyframes trackPulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--state-working-tint); }
  50%      { box-shadow: 0 0 0 5px var(--state-working-tint); }
}

/* Once the case lands, the whole rail takes the outcome colour so a closed case and
   an escalated one are distinguishable across the room. */
.case-track[data-outcome="resolved"] .case-track__step[data-state="done"] .case-track__dot,
.case-track[data-outcome="resolved"] .case-track__step[data-state="current"] .case-track__dot {
  background: var(--state-resolved);
}
.case-track[data-outcome="resolved"] .case-track__step[data-state="current"] .case-track__label { color: var(--state-resolved); }
.case-track[data-outcome="escalated"] .case-track__step[data-state="done"] .case-track__dot,
.case-track[data-outcome="escalated"] .case-track__step[data-state="current"] .case-track__dot {
  background: var(--state-escalated);
}
.case-track[data-outcome="escalated"] .case-track__step[data-state="current"] .case-track__label { color: var(--state-escalated); }
/* A landed case is not "in progress": stop the pulse. */
.case-track[data-outcome] .case-track__step[data-state="current"] .case-track__dot { animation: none; }

/* On a phone the four labels squeeze to ~33px each and ellipsis into "Det…", "Cla…".
   Drop them and let the dots carry the progress: the phase badge in the card header
   is already colour-coded and names the phase, so nothing is lost. */
@media (max-width: 900px) {
  .case-track__label { display: none; }
  .case-track__step { flex: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .case-track__step[data-state="current"] .case-track__dot { animation: none; }
}

.case-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-2);
}

.case-card__reasoning {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: 0 0 var(--space-2);
}

.case-card__policy {
  font-size: var(--text-sm);
  color: var(--muted-75);
  margin: 0 0 var(--space-2);
}

.case-card__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
}

/* Recessed well, one step DOWN from the card surface (design correction
   section 4.3): every artifact the agent produces sits in its own sunken
   mono block, not a bare line floating in the card's whitespace. */
.case-card__action {
  min-height: 2.4em;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-well);
  border: 1px solid var(--border-06);
  border-left: 3px solid var(--border); /* impeccable-disable-line side-tab: spec-mandated state stripe / active accent bar, design-correction section 4.3-4.4 */
  border-radius: var(--radius-sm);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out-expo), border-color var(--dur-base) var(--ease-out-expo);
}
.case-card__action.is-revealed { opacity: 1; border-left-color: var(--struct-1); }

.case-card__action-label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  color: var(--accent-cyan);
  margin-bottom: var(--space-1);
}

.case-card__action-artifact {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--muted-75);
}

.case-card__decision { margin: 0 0 var(--space-2); }

.case-card__consequence {
  font-size: var(--text-sm);
  color: var(--muted-75);
  border-top: 1px solid var(--border-06);
  padding-top: var(--space-2);
}

.case-card__cost-delta {
  font-family: var(--font-mono);
  color: var(--accent-cyan);
}

.case-card__choices {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-2) 0;
}

.desk-btn--choice {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--accent);
}

.case-card__keep-watching {
  display: inline-block;
  font-size: var(--text-xs);
  color: var(--muted-70);
  text-decoration: underline;
}

.case-card__waiting {
  font-size: var(--text-sm);
  color: rgb(255, 180, 100);
  margin: 0 0 var(--space-1);
}

.case-card__scored-note {
  /* Sentence, not a data value: mono is for tag-pills, timestamps, and IDs
     only (foundry P6 hierarchy rule). Promoted off the xs floor since a
     visitor reads this to trust the ledger math, per the 16px reading rule. */
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: var(--space-1) 0 0;
}

.case-card__manual-cta:empty { display: none; }

.desk-btn--manual {
  width: 100%;
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
  margin: var(--space-1) 0 var(--space-2);
}

.case-card__meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  margin: 0;
}

.case-card__live-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  color: var(--accent-cyan);
  border: 1px solid var(--accent-cyan);
  border-radius: var(--radius-pill);
  padding: 2px var(--space-2);
  margin-bottom: var(--space-2);
}

/* ---- Collapsed worklog cards (passive path, after 8 sim-minutes) ---- */

.case-card__collapsed { display: none; }

.case-card[data-collapsed="1"]:not(.is-expanded) .case-card__full { display: none; }
.case-card[data-collapsed="1"]:not(.is-expanded) .case-card__collapsed {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  font-size: var(--text-sm);
  cursor: pointer;
}
.case-card[data-collapsed="1"].is-expanded .case-card__collapsed { display: none; }

.case-card__collapsed-type { font-weight: 600; }
/* This chip only ever coloured the escalated case, so every RESOLVED row in the
   worklog rendered plain grey and a closed case looked the same as anything else. */
.case-card__collapsed-chip {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  color: var(--muted-70);
}
.case-card__collapsed-chip[data-outcome="resolved"] {
  color: var(--state-resolved);
  background: var(--state-resolved-tint);
}
.case-card__collapsed-chip[data-outcome="escalated"] {
  color: var(--state-escalated);
  background: var(--state-escalated-tint);
}
.case-card__collapsed-minutes {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-cyan);
  margin-left: auto;
}

/* ---- Connected systems: the isometric rail ----
   (plans/exception-desk-design-correction.md section 3, replaces the ring
   entirely.) A vertical agent spine at the column's inner (left) edge; eight
   isometric system blocks stacked in scenario.systems order to its right;
   every wire a short horizontal run from spine to block, so a crossing is
   structurally impossible. Iso primitives are plain CSS: each is three
   clip-path rhombi (top/left/right) forming a hexagon outline, the standard
   flat-shaded isometric-cube construction, not real 3D transforms: cheaper,
   and it matches the baseten reference's own flat-fill iso grammar (a flat
   projection, not a rotatable scene). */

.systems-honesty {
  /* Deferred from D1 (this lives inside the rail's own panel chrome): a
     caption is exempt from nothing by the 16px rule, only tag-pills,
     timestamps and eyebrows are; "styled as a proper caption" means muted
     color and a rule beneath it, not a smaller size. */
  font-size: var(--text-sm);
  color: var(--muted-70);
  line-height: 1.5;
  margin: 0 0 var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border-06);
}

.systems-schematic {
  width: 100%;
  margin: 0 0 var(--space-4);
}

.rail {
  position: relative;
  /* Wide enough that a wire touched three times in one case (the busiest
     route in the logistics scenario) still spreads three route-chips
     without overlapping (gate 4/6.4: numbered chips "all visible at once"). */
  padding-left: 64px;
}

.rail__spine-line {
  position: absolute;
  left: 15px;
  top: 26px;
  bottom: 4px;
  width: 2px;
  background: var(--struct-3);
}

.rail__agent {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  transform: translateX(-64px);
  padding-left: 64px;
}
.rail__agent-dot {
  position: absolute;
  left: 9px;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--struct-1);
  box-shadow: 0 0 0 4px var(--accent-tint);
  transition: box-shadow var(--dur-fast) var(--ease-out-expo);
}
.rail__agent.is-live .rail__agent-dot { box-shadow: 0 0 0 7px var(--accent-tint-strong); }
.rail__agent-label {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-md);
  letter-spacing: var(--tracking-tight);
  color: var(--fg);
}
.rail__agent-caption {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted-70);
}

.rail__blocks {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.rail-block {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 56px;
}

/* The short horizontal run from the spine to this block: the wire is never
   longer than the fixed gutter below, so it can never cross another wire. */
.rail-block__wire {
  position: absolute;
  left: -64px;
  top: 50%;
  width: 56px;
  height: 2px;
  background: var(--struct-3);
  transform: translateY(-50%);
  transition: background var(--dur-fast) var(--ease-out-expo), opacity var(--dur-fast) var(--ease-out-expo);
}
.rail-block__wire.is-live { background: var(--accent-cyan); }
.rail-block__wire.is-route { background: var(--struct-1); height: 3px; }
.rail-block__wire.is-route.is-live { background: var(--accent-cyan); }
.systems-schematic.has-focus .rail-block__wire:not(.is-route) { opacity: 0.25; }
.systems-schematic.has-focus .rail-block:not(.is-route) .rail-block__iso { opacity: 0.4; }

.rail-block__wire-dot {
  position: absolute;
  left: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--accent-cyan);
  box-shadow: 0 0 8px var(--accent-cyan);
  opacity: 0;
  pointer-events: none;
}

/* Numbered mono chip riding the wire, case-focus mode: all visible at once,
   in trace order, never a step-through. */
.route-chip {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: calc(16px * var(--ui-scale));
  height: calc(16px * var(--ui-scale));
  border-radius: 50%;
  background: var(--struct-1);
  color: #04101f;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--ui-scale));
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 2px var(--surface);
  z-index: 2;
}

/* ---- Iso primitives: three clip-path rhombi = one hexagon outline ---- */

.rail-block__iso {
  position: relative;
  flex: 0 0 auto;
  width: 34px;
  height: 38px;
  transition: opacity var(--dur-base) var(--ease-out-expo);
}
.rail-block__face { position: absolute; inset: 0; }

/* CUBE (system of record: TMS, Dock scheduling, Billing & AP). Top lit,
   left mid, right shadowed: the standard iso-cube shading order. */
.rail-block__iso[data-primitive="cube"] .rail-block__face--top {
  clip-path: polygon(50% 0%, 100% 25%, 50% 50%, 0% 25%);
  background: var(--struct-2);
}
.rail-block__iso[data-primitive="cube"] .rail-block__face--left {
  clip-path: polygon(0% 25%, 50% 50%, 50% 100%, 0% 75%);
  background: var(--struct-3);
}
.rail-block__iso[data-primitive="cube"] .rail-block__face--right {
  clip-path: polygon(50% 50%, 100% 25%, 100% 75%, 50% 100%);
  background: var(--struct-4);
}

/* TRAY (Ops email, Phone & SMS): the same hexagon dissection, squashed flat
   so it reads as a shallow open tray rather than a full cube. */
.rail-block__iso[data-primitive="tray"] { height: 22px; align-self: center; }
.rail-block__iso[data-primitive="tray"] .rail-block__face--top {
  clip-path: polygon(50% 0%, 100% 25%, 50% 50%, 0% 25%);
  background: var(--struct-2);
}
.rail-block__iso[data-primitive="tray"] .rail-block__face--left {
  clip-path: polygon(0% 25%, 50% 50%, 50% 100%, 0% 75%);
  background: var(--struct-3);
}
.rail-block__iso[data-primitive="tray"] .rail-block__face--right {
  clip-path: polygon(50% 50%, 100% 25%, 100% 75%, 50% 100%);
  background: var(--struct-4);
}

/* CYLINDER (EDI feed, Telematics): a feed/stream, stacked-disc read. Only
   top + left faces are used (right face hidden): an ellipse cap over a
   rounded body. */
.rail-block__iso[data-primitive="cylinder"] .rail-block__face--top {
  inset: 0 0 62% 0;
  border-radius: 50%;
  background: var(--struct-2);
  clip-path: none;
}
.rail-block__iso[data-primitive="cylinder"] .rail-block__face--left {
  inset: 22% 8% 0 8%;
  border-radius: 0 0 50% 50% / 0 0 30% 30%;
  background: var(--struct-3);
  clip-path: none;
}
.rail-block__iso[data-primitive="cylinder"] .rail-block__face--right { display: none; }

/* HUMAN (your on-call team): the one block resting on the warm accent, per
   the direction contract ("the ONLY block using the warm accent as its
   resting border"). Head + shoulders, only top + left faces used. */
.rail-block__iso[data-primitive="human"] .rail-block__face--top {
  inset: 0 25% 58% 25%;
  border-radius: 50%;
  background: var(--accent-warm);
  clip-path: none;
}
.rail-block__iso[data-primitive="human"] .rail-block__face--left {
  inset: 44% 10% 0 10%;
  border-radius: 10px 10px 0 0;
  background: var(--accent-warm);
  opacity: 0.75;
  clip-path: polygon(15% 100%, 85% 100%, 100% 0%, 0% 0%);
}
.rail-block__iso[data-primitive="human"] .rail-block__face--right { display: none; }

/* ---- The flat info face beside each block ---- */

.rail-block__info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.rail-block__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.rail-block__name {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rail-block__status-dot {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border-raised);
  transition: background var(--dur-base) var(--ease-out-expo);
}
.rail-block__status-dot.is-active { background: var(--state-resolved); }
.rail-block__pill {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--ui-scale));
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--struct-1);
  border: 1px solid var(--struct-3);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
  background: var(--surface-well);
}
.rail-block__activity {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--ui-scale));
  color: var(--muted-70);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Block-level flash (ambient touch) and route highlight (case focus). */
.rail-block.is-live .rail-block__iso { filter: brightness(1.3); }
.rail-block.is-route .rail-block__name { color: var(--struct-1); }
.rail-block[data-system="team"] { border-left: 2px solid var(--accent-warm); padding-left: var(--space-2); border-radius: var(--radius-sm); } /* impeccable-disable-line side-tab: spec-mandated, design-correction section 3 ("the ONLY block using the warm accent as its resting border") */

@media (max-width: 900px) {
  .rail { padding-left: 48px; }
  .rail__spine-line { left: 11px; }
  .rail__agent { transform: translateX(-48px); padding-left: 48px; }
  .rail__agent-dot { left: 7px; }
  .rail-block__wire { left: -48px; width: 40px; }
  .rail-block__iso { width: 28px; height: 32px; }
}

/* ---- Connected systems: self-locating route sentences (design-correction
   section 8, C2: "the numbers explain themselves; the detached legend dies")
   ----
   Replaces the old panel-bottom #systems-legend entirely. Each trace
   sentence renders inside the block it describes, in that block's activity
   slot, prefixed by the same number that sits on its wire. A block on the
   route hides its ambient one-line activity/descriptor and shows this stack
   instead; clearSystemsFocus reverses it. */

.rail-block.is-route .rail-block__activity { display: none; }

.rail-block__route-sentences {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: 2px;
}

.rail-block__route-sentence {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  margin: 0;
  padding: 3px 4px;
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease-out-expo);
}
/* The instant this sentence's action fires during real playback (same-frame
   rule, unchanged): a brief highlight, "lighting in sequence as it plays". */
.rail-block__route-sentence.is-live { background: var(--accent-tint-strong); }

.rail-block__route-n {
  flex: 0 0 auto;
  width: calc(16px * var(--ui-scale));
  height: calc(16px * var(--ui-scale));
  margin-top: 3px;
  border-radius: 50%;
  background: var(--struct-1);
  color: #04101f;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--ui-scale));
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Reading copy, not a label: the 16px floor applies (design-correction
   section 4.5). This is the same trace sentence that used to sit in the
   legend at --text-sm; only its home moved. */
.rail-block__route-text {
  font-size: var(--text-sm);
  line-height: 1.4;
  color: var(--fg);
}

/* ---- Shift ledger (compacted to a strip beneath the schematic, spec section 1:
   "its numbers matter at the end; the schematic matters during") ---- */

.systems-ledger-strip {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--hairline);
}

.systems-ledger-strip__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin: 0 0 var(--space-3);
}

.ledger-strip__body {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}

.ledger-strip__body .ledger-row {
  flex: 1 1 auto;
  min-width: 84px;
  border-bottom: none;
  padding: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.ledger-strip__body .ledger-row span { font-size: var(--text-xs); }
.ledger-strip__body .ledger-row strong { font-size: var(--text-lg); }

/* ---- Ledger ---- */

.ledger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-06);
  font-size: var(--text-sm);
}

.ledger-row span { color: var(--muted-70); }
.ledger-row strong { font-family: var(--font-mono); font-size: var(--text-xl); font-weight: 600; color: var(--fg); }
/* The ledger totals carry the same legend as the cards, so "Resolved 12 / Escalated 2"
   is readable at a glance instead of two identical white numbers. */
#ledger-resolved { color: var(--state-resolved); }
#ledger-escalated { color: var(--state-escalated); }

/* ---- Escalation queue ---- */

.escalation-queue {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--hairline);
}

.escalation-queue__title {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin: 0 0 var(--space-3);
}

.escalation-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-well);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-2);
  cursor: pointer;
  font-size: var(--text-sm);
}
.escalation-row:hover { border-color: var(--accent-warm); }

.escalation-row__status {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
.escalation-row__status--pending { color: rgb(255, 180, 100); }
.escalation-row__status--decided { color: rgb(140, 230, 160); }
.escalation-row__status--waiting { color: var(--muted-70); }

/* ---- Detail drawer ---- */

.drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: flex;
  justify-content: flex-end;
  background: var(--scrim-soft);
}

.drawer {
  position: relative;
  width: min(calc(480px * var(--ui-scale)), 100%);
  height: 100%;
  background: var(--surface);
  border-left: 1px solid var(--hairline);
  padding: var(--space-7) var(--space-6);
  overflow-y: auto;
}

.drawer__close {
  position: sticky;
  top: 0;
  float: right;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-size: var(--text-lg);
  line-height: 1;
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
}

.drawer__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  margin: 0 0 var(--space-2);
}

.drawer__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  margin: 0 0 var(--space-3);
}

.drawer__narration {
  font-size: var(--text-sm);
  color: var(--accent-cyan);
  margin: 0 0 var(--space-5);
}

.drawer__section {
  border-top: 1px solid var(--border-06);
  padding: var(--space-4) 0;
}
.drawer__section h3 {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin: 0 0 var(--space-2);
}

.drawer__mono {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-75);
  margin: 0 0 var(--space-1);
}

.drawer__body-text {
  font-size: var(--text-sm);
  color: var(--muted-93);
  line-height: 1.55;
  white-space: pre-line;
  margin: 0;
}

.drawer__artifact {
  border: 1px solid var(--border-06);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  margin-bottom: var(--space-2);
}

/* ---- Manual-comparison overlay ---- */

.manual-overlay {
  position: fixed;
  inset: 0;
  z-index: 180;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: var(--scrim);
}

.manual-overlay__panel {
  position: relative;
  width: min(calc(520px * var(--ui-scale)), 100%);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
}

.manual-overlay__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  margin: 0 0 var(--space-2);
}

.manual-overlay__note {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: 0 0 var(--space-4);
}

.manual-overlay__steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.manual-step {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  background: var(--surface);
  color: var(--fg);
  cursor: pointer;
}
.manual-step[data-state="done"] { border-color: rgba(120, 220, 150, 0.4); color: var(--muted-70); }
.manual-step[data-state="done"] .manual-step__label::before { content: "✓ "; color: rgb(140, 230, 160); }
.manual-step[data-state="locked"] { opacity: 0.4; cursor: not-allowed; }
.manual-step[data-state="next"] { border-color: var(--accent); }
.manual-step__minutes {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-70);
  flex-shrink: 0;
}

.manual-overlay__timer {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--muted-75);
  margin: 0 0 var(--space-3);
}

.manual-overlay__finish {
  font-size: var(--text-sm);
  color: var(--muted-93);
  border-top: 1px solid var(--hairline);
  padding-top: var(--space-4);
  line-height: 1.6;
}
.manual-overlay__finish .desk-btn { margin-left: var(--space-2); }

/* ---- End card ---- */

.end-card {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: var(--scrim-strong);
}

.desk-panel--worklog { position: relative; }

.end-card__panel {
  max-width: calc(480px * var(--ui-scale));
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: var(--space-7);
  background: var(--surface);
  text-align: center;
}

.end-card__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  margin: 0 0 var(--space-3);
}

/* White-label mode: partner firm name on the end card (plan section 5). */
.end-card__brand-note {
  font-size: var(--text-sm);
  color: var(--accent);
  margin: 0 0 var(--space-3);
}

.end-card__body {
  font-size: var(--text-md);
  color: var(--muted-75);
  margin: 0 0 var(--space-4);
  line-height: 1.5;
}

.end-card__replay-copy {
  font-size: var(--text-sm);
  color: var(--muted-70);
  margin: 0 0 var(--space-5);
}

.end-card__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.end-card__secondary {
  font-size: var(--text-sm);
  color: var(--muted-75);
  text-decoration: underline;
}

/* ---- Footer skeleton ---- */

.desk-footer {
  border-top: 1px solid var(--hairline);
  padding: var(--space-5) var(--space-6);
  font-size: var(--text-sm);
  color: var(--muted-70);
}

.desk-footer__selftest {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-75);
  margin: 0 0 var(--space-2);
}

.desk-footer__note { margin: 0; }

/* White-label mode: the one quiet disclosure line in branded mode (plan section 5). */
.desk-footer__white-label-note { margin: var(--space-2) 0 0; }

/* Default view: the product signature. Same slot and same treatment as the white-label
   note above, and never rendered at the same time as it. */
.desk-footer__signature { margin: var(--space-2) 0 0; }

/* ---- Guided tour (spotlight walkthrough) ---- */

.tour-spotlight {
  position: fixed;
  z-index: 300;
  border-radius: var(--radius-md);
  border: 1px solid var(--accent-cyan);
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.8), 0 0 0 3px var(--accent-tint-strong);
  pointer-events: none;
  transition: top var(--dur-base) var(--ease-out-expo), left var(--dur-base) var(--ease-out-expo),
    width var(--dur-base) var(--ease-out-expo), height var(--dur-base) var(--ease-out-expo);
}

.tour-bubble {
  position: fixed;
  z-index: 301;
  width: min(calc(320px * var(--ui-scale)), calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-pop);
}

.tour-bubble__title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  margin: 0 0 var(--space-2);
}

.tour-bubble__text {
  font-size: var(--text-sm);
  color: var(--muted-75);
  line-height: 1.5;
  margin: 0 0 var(--space-4);
}

.tour-bubble__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.tour-dots {
  display: flex;
  gap: 6px;
}

.tour-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
}
.tour-dot.is-active { background: var(--accent-cyan); }

.tour-bubble__actions {
  display: flex;
  gap: var(--space-2);
}

/* Mobile: tour bubble becomes a bottom sheet (plan section 3). */
.tour-bubble--sheet {
  top: auto !important;
  left: 0 !important;
  right: 0;
  bottom: 0;
  width: 100%;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-bottom: none;
}

/* ---- Contextual first-time tooltips ---- */

.contextual-tooltip {
  position: fixed;
  z-index: 250;
  max-width: calc(260px * var(--ui-scale));
  font-size: var(--text-sm);
  color: var(--muted-93);
  background: var(--surface);
  border: 1px solid var(--accent-cyan);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-pop);
  line-height: 1.4;
}

/* ---- Header tour link ---- */

.desk-header__tour-link {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-70);
  background: transparent;
  border: none;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  padding: 0;
}
.desk-header__tour-link:hover { color: var(--muted-93); }

/* ---- Intro card: dual actions ---- */

.intro-card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-2);
}

/* ---- Footer: how this maps to a real deployment ---- */

/* Collapsed by default. Three paragraphs of prose under the desk looked like part of the
   app, so visitors sat waiting for something to happen in it. Now the desk ends where the
   desk ends, and the answer is one click away. */
.desk-footer__deployment {
  margin: 0 var(--space-6) var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--hairline);
}

.desk-footer__deployment-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-70);
  margin: 0;
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease-out-expo);
}
.desk-footer__deployment-title::-webkit-details-marker { display: none; }
.desk-footer__deployment-title:hover { color: var(--fg); }
/* A disclosure caret, so it reads as expandable rather than as a dead heading. */
.desk-footer__deployment-title::before {
  content: "";
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform var(--dur-fast) var(--ease-out-expo);
}
.desk-footer__deployment[open] .desk-footer__deployment-title::before { transform: rotate(90deg); }

/* Three columns across the full width, echoing the desk's own three panels, so the copy
   uses the space instead of floating in a narrow strip with dead gutters on both sides.
   The three paragraphs are three distinct ideas (what swaps, what does not, how you buy
   it), so each becomes a headed column. */
.desk-footer__deployment-body {
  margin-top: var(--space-5);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-7);
}

.deploy-col__head {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--state-working);
  margin: 0 0 var(--space-3);
}
.deploy-col p {
  font-size: var(--text-sm);
  color: var(--muted-75);
  line-height: 1.6;
  margin: 0 0 var(--space-3);
}
.deploy-col p:last-child { margin-bottom: 0; }

.deploy-col__links { display: flex; flex-direction: column; gap: var(--space-2); }
.desk-footer__deployment a {
  color: var(--accent-cyan);
  text-decoration: none;
  font-weight: 600;
}
.desk-footer__deployment a:hover { color: var(--fg); }

@media (max-width: 900px) {
  .desk-footer__deployment-body { grid-template-columns: 1fr; gap: var(--space-5); }
}

/* ---- Density step-down below 1536px (design-correction section 8, C1) ----
   The founder's "zoomed in" finding: at laptop widths the intro card or the
   active case card plus the next one below it did not fit the fold. Padding
   steps down one notch and headings step down one type-tier; card COPY
   (reasoning, policy, action text) stays exactly at the 16px floor, per the
   rule's own wording ("card copy stays at the 16px floor"). */
@media (max-width: 1535.98px) {
  .case-card { padding: var(--space-3) var(--space-4); }
  .case-card__title { font-size: var(--text-md); }
  .intro-card { padding: var(--space-6) var(--space-5); }
  .intro-card__title { font-size: var(--text-xl); }
}

/* ---- Responsive (<900px): tabs, full-screen sheets, stacked choices ---- */

@media (max-width: 899.98px) {
  .desk-main {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    /* Mobile has one visible "column" at a time (the guide stacked above
       whichever tab is active), not three side by side, so the 100vh shell's
       "each column scrolls internally" collapses to: .desk-main itself is
       that one scrolling region. Individual .desk-panel overflow is inert
       here (mobile panels have no bounded height of their own to overflow
       against), which is fine: one scroll container, not nested ones. */
    overflow-y: auto;
  }
  /* Stack: the guide sits above whichever tab is showing, so it stays with you when you
     switch to the worklog to watch the case it just told you to watch. */
  .desk-main > #guide,
  .desk-panel--inbound,
  .desk-panel--worklog,
  .desk-panel--systems { grid-column: 1; grid-row: auto; }
  /* The desktop rule above makes .guide `position: sticky` so it can float within
     its own tall grid column while the worklog scrolls beside it. On mobile there
     is no side-by-side column: the guide is a full-width block stacked ABOVE
     whichever tab is active, in normal flow. Sticky here does something worse than
     nothing: a sticky element paints after (visually on top of) the static tab
     panel below it regardless of DOM order, so as the page scrolls the guide's
     opaque card grid hangs over the active panel and shows that panel's content
     bleeding through its own gaps. Harmless-looking with the short Worklog panel,
     it became a real bug once the taller Connected Systems panel shipped: node
     labels and legend text rendered visually interleaved with the case list.
     Reverting to normal flow here is a true stack, matching the comment above. */
  .guide { margin: 0; border-radius: 0; border-left: 0; border-right: 0; border-top: 0; position: static; max-height: none; }
  .desk-panel {
    display: none;
    border-bottom: 1px solid var(--border-06);
  }
  .desk-panel.is-active-panel {
    display: flex;
  }
  .desk-header {
    padding: var(--space-3) var(--space-4);
    position: sticky;
    top: 0;
  }
  .desk-tabs {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--surface);
    border-bottom: 1px solid var(--hairline);
  }
  .drawer {
    width: 100%;
  }
  .manual-overlay__panel {
    width: 100%;
    max-height: 100vh;
    height: 100%;
    border-radius: 0;
  }
  .case-card__choices {
    flex-direction: column;
  }
  .desk-btn--choice {
    width: 100%;
    text-align: center;
  }
  .end-card {
    position: fixed;
  }
  /* The schematic's own tab, per spec section 1 ("its own tab (label: 'Systems')").
     Rail-specific mobile overrides (spine gutter, wire length, block size)
     live with the rail's own CSS above; nothing extra needed here now that
     it is a vertical list, not a ring that had to shrink to fit. */
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
