/* ============================================================
   Agent mode — presentation surface.

   Everything below is driven by story-scoped tokens so the mode
   works in BOTH themes. Contrast targets: body text ≥ 7:1 against
   the darkest point of the field, labels ≥ 4.5:1. A scrim sits
   under the text column so the drifting gradient can stay lively
   without ever competing with the words.
   ============================================================ */

body[data-page="story"] {
  --st-ink: #f8f7f2;
  --st-dim: #e4e2d8;          /* body copy — must clear 4.5:1 on the scrim */
  --st-faint: #a9a79e;        /* labels only */
  --st-line: rgba(255, 255, 255, 0.22);
  --st-line-soft: rgba(255, 255, 255, 0.12);
  --st-fill: rgba(255, 255, 255, 0.05);
  --st-panel: rgba(8, 8, 7, 0.90);
  --st-accent: #f0a184;       /* lightened so it passes on dark */
  --st-scrim: rgba(7, 7, 6, 0.90);
  --st-base: #0e0e0c;
  background: var(--st-base);
}

:root[data-theme="light"] body[data-page="story"] {
  --st-ink: #121210;
  --st-dim: #3a3931;
  --st-faint: #63615a;
  --st-line: rgba(20, 20, 15, 0.24);
  --st-line-soft: rgba(20, 20, 15, 0.13);
  --st-fill: rgba(20, 20, 15, 0.035);
  --st-panel: rgba(253, 252, 249, 0.92);
  --st-accent: #93331a;
  --st-scrim: rgba(251, 250, 246, 0.90);
  --st-base: #f7f6f1;
}

/* ---------- the field, shared by the overture and every chapter ---------- */
.st-bg {
  position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  background: radial-gradient(125% 95% at 50% 52%, #191914 0%, #0e0e0c 58%, #050504 100%);
}
:root[data-theme="light"] .st-bg {
  background: radial-gradient(125% 95% at 50% 52%, #fffefb 0%, #f5f4ee 58%, #ebeae3 100%);
}
.st-bg i { position: absolute; display: block; border-radius: 50%; filter: blur(80px); }
.st-bg i:nth-child(1) { width: 46vw; height: 46vw; left: 4%;  top: 8%;    background: rgba(180,71,43,.30);  animation: drift1 24s ease-in-out infinite alternate; }
.st-bg i:nth-child(2) { width: 42vw; height: 42vw; right: 2%; top: 28%;   background: rgba(63,109,140,.26); animation: drift2 28s ease-in-out infinite alternate; }
.st-bg i:nth-child(3) { width: 36vw; height: 36vw; left: 32%; bottom: -6%; background: rgba(74,124,89,.20); animation: drift3 32s ease-in-out infinite alternate; }
:root[data-theme="light"] .st-bg i:nth-child(1) { background: rgba(180,71,43,.16); }
:root[data-theme="light"] .st-bg i:nth-child(2) { background: rgba(63,109,140,.15); }
:root[data-theme="light"] .st-bg i:nth-child(3) { background: rgba(74,124,89,.12); }
@keyframes drift1 { to { transform: translate3d(9vw, 6vh, 0) scale(1.16); } }
@keyframes drift2 { to { transform: translate3d(-7vw, -8vh, 0) scale(1.1); } }
@keyframes drift3 { to { transform: translate3d(5vw, -5vh, 0) scale(1.2); } }
@media (prefers-reduced-motion: reduce) { .st-bg i { animation: none; } }

/* ---------- overture ---------- */
.ov {
  position: fixed; inset: 0; z-index: 200; overflow: hidden;
  background: radial-gradient(85% 70% at 42% 55%, var(--st-scrim) 0%, var(--st-base) 118%);
  display: flex; align-items: center; justify-content: center;
  transition: opacity .8s cubic-bezier(.4,0,.2,1), visibility .8s;
}
.ov.gone { opacity: 0; visibility: hidden; pointer-events: none; }
.ov-inner { position: relative; max-width: 720px; padding: 0 40px; text-align: left; }
.ov-k {
  display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .34em;
  text-transform: uppercase; color: var(--st-accent); margin-bottom: 26px;
  opacity: 0; animation: ov-in .9s .15s cubic-bezier(.16,1,.3,1) 1 forwards;
}
.ov-h { font-family: var(--serif); font-weight: 400; color: var(--st-ink); margin: 0;
        font-size: clamp(34px, 5.6vw, 66px); line-height: 1.04; letter-spacing: -.03em; }
.ov-h span { display: block; opacity: 0; animation: ov-up 1s cubic-bezier(.16,1,.3,1) 1 forwards; }
.ov-h span:nth-child(1) { animation-delay: .35s; }
.ov-h span:nth-child(2) { animation-delay: .5s; }
.ov-h span:nth-child(3) { animation-delay: .65s; }
.ov-p { color: var(--st-dim); font-size: 16px; line-height: 1.7; max-width: 52ch; margin: 26px 0 0;
        opacity: 0; animation: ov-in 1s .95s cubic-bezier(.16,1,.3,1) 1 forwards; }
.ov-meta { display: flex; gap: 26px; flex-wrap: wrap; margin: 28px 0 0;
           font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; color: var(--st-faint);
           opacity: 0; animation: ov-in 1s 1.15s cubic-bezier(.16,1,.3,1) 1 forwards; }
.ov-meta b { color: var(--st-ink); font-weight: 400; }
.ov-go {
  margin: 36px 0 0; font-family: var(--mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  background: none; border: 1px solid var(--st-line); color: var(--st-ink); padding: 14px 30px; cursor: pointer;
  opacity: 0; animation: ov-in 1s 1.35s cubic-bezier(.16,1,.3,1) 1 forwards;
  transition: background .25s, border-color .25s, color .25s, letter-spacing .25s;
}
.ov-go em { font-style: normal; color: var(--st-accent); margin-left: 6px; }
.ov-go:hover { background: var(--st-ink); color: var(--st-base); border-color: var(--st-ink); letter-spacing: .2em; }
/* Reuses .st-close's look; pins it to the overture's top-right corner and
   fades in with the rest of the intro (margin-left reset undoes the rail's
   flex push). Absolute against .ov, which is position:fixed. */
.ov-close {
  position: absolute; top: 20px; right: 20px; z-index: 210; margin-left: 0;
  opacity: 0; animation: ov-in 1s .6s cubic-bezier(.16,1,.3,1) 1 forwards;
}
@keyframes ov-in { to { opacity: 1; } }
@keyframes ov-up { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .ov-k, .ov-h span, .ov-p, .ov-meta, .ov-go, .ov-close { animation: none; opacity: 1; }
}

/* ---------- layout ---------- */
#story {
  display: grid; grid-template-columns: minmax(0, 1fr) 400px;
  height: calc(100vh - 58px); overflow: hidden;
  position: relative; z-index: 1; background: transparent;
  opacity: 1; transition: opacity .6s ease;
}
#story.veiled { opacity: 0; }
.st-main {
  display: flex; flex-direction: column; min-width: 0; position: relative;
  padding: clamp(18px, 3.2vh, 36px) clamp(24px, 4vw, 56px) clamp(14px, 2vh, 24px);
  overflow-y: auto;
  /* Readability scrim. Holds near-full opacity across the whole text column
     and only releases at the far edge, so the field still reads as a living
     background without ever sitting directly behind a glyph. */
  background: linear-gradient(100deg,
    var(--st-scrim) 0%, var(--st-scrim) 62%,
    color-mix(in srgb, var(--st-scrim) 55%, transparent) 82%, transparent 100%);
}
/* Above the overture (z 200), not under it — otherwise the intro scrim
   dims the nav to near-invisibility and the mode toggle looks broken. */
body[data-page="story"] .nav {
  position: sticky; top: 0; z-index: 300; background: var(--st-panel);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border-bottom-color: var(--st-line-soft);
}
body[data-page="story"] .nav-brand { color: var(--st-ink); }
body[data-page="story"] .nav-links a { color: var(--st-dim); }
body[data-page="story"] .nav-links a:hover, body[data-page="story"] .nav-cta:hover { color: var(--st-accent); }
body[data-page="story"] .sw { border-color: var(--st-line); }
body[data-page="story"] .sw button { color: var(--st-faint); }
body[data-page="story"] .sw button + button { border-left-color: var(--st-line); }
body[data-page="story"] .sw button[aria-pressed="true"] { background: var(--st-ink); color: var(--st-base); }
/* The ring's inset shows the button's own fill; on the story page that has
   to be the story base, not the classic paper. */
body[data-page="story"] .sw.grad-ring,
body[data-page="story"] .sw.grad-ring button { background: var(--st-base); }
body[data-page="story"] .sw.grad-ring button[aria-pressed="true"] { background: var(--st-ink); color: var(--st-base); }

/* ---------- chapter ---------- */
.st-head { max-width: 40ch; }
.st-n { font-family: var(--mono); font-size: 10px; letter-spacing: .3em; text-transform: uppercase; color: var(--st-accent); }
.st-head h2 {
  font-family: var(--serif); font-weight: 400; color: var(--st-ink);
  font-size: clamp(26px, min(4vw, 6.4vh), 46px); line-height: 1.06; letter-spacing: -.03em; margin: clamp(6px, 1.2vh, 14px) 0 0;
  animation: ov-up .85s cubic-bezier(.16,1,.3,1) 1 both;
}
.st-claim {
  font-size: clamp(14px, 1.9vh, 17px); line-height: 1.6; color: var(--st-dim); margin: clamp(8px, 1.6vh, 18px) 0 0; max-width: 62ch;
  animation: ov-in .9s .12s cubic-bezier(.16,1,.3,1) 1 both;
}
.st-claim em { color: var(--st-ink); font-style: italic; }

/* The prototype is a bordered card, so it needs real clearance or it reads
   as colliding with the claim above and the evidence chips below. 22px was
   the entire separation. fitViz() scales the card down if this ever leaves
   too little room, so generous padding costs legibility only in the rare
   case where a chapter genuinely doesn't fit. */
.st-viz { flex: 1; display: flex; align-items: center; justify-content: center; padding: clamp(20px, 4.5vh, 54px) 0; min-height: 0; overflow: hidden;
          animation: ov-in 1s .18s ease 1 both; }
.st-viz > div { width: 100%; max-width: 620px; }

.st-slot {
  border: 1px dashed var(--st-line); background: var(--st-fill); padding: 9px 13px;
  font-family: var(--mono); font-size: 10px; color: var(--st-dim); line-height: 1.5; margin-bottom: 10px;
  animation: ov-in .9s .24s ease 1 both;
}
.st-slot b { display: block; color: var(--st-faint); letter-spacing: .14em; text-transform: uppercase; font-size: 9px; font-weight: 400; margin-bottom: 4px; }

.st-belt { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 10px;
           animation: ov-in .9s .3s ease 1 both; }
.st-ev { display: flex; gap: 8px; flex-wrap: wrap; flex: 1; }
.st-ev span {
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--st-dim); border: 1px solid var(--st-line); padding: 5px 10px; background: var(--st-fill);
}
.st-replay {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--st-line); background: none; color: var(--st-dim);
  padding: 6px 12px; cursor: pointer; transition: .18s;
}
.st-replay:hover { border-color: var(--st-accent); color: var(--st-accent); }

/* ---------- rail ---------- */
.st-rail {
  border-left: 1px solid var(--st-line-soft);
  background: var(--st-panel); backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
}
/* The chat surface itself (head, body, lines, chips, input, note) lives in
   styles.css and is shared with the docked agent on classic pages. Only the
   --st-* token values at the top of this file differ here. */

/* ---------- lo-fi UI prototypes ----------
   Wireframe fidelity on purpose: enough interface to demonstrate the
   decision, not enough to be mistaken for a shipped screen. Colour is
   semantic only — allow/ask/deny, good/warn/bad — never decorative. */
.ui-wrap { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 660px; }
.ui-tabs { display: flex; gap: 0; border: 1px solid var(--st-line); width: fit-content; }
.ui-tabs button {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  background: none; border: 0; color: var(--st-faint); padding: 8px 13px; cursor: pointer; transition: .18s;
}
.ui-tabs button + button { border-left: 1px solid var(--st-line); }
.ui-tabs button:hover { color: var(--st-ink); }
.ui-tabs button[aria-pressed="true"] { background: var(--st-ink); color: var(--st-base); }

.ui-stage { display: flex; flex-direction: column; gap: 12px; }
.ui-stage.swap { animation: ui-in .34s cubic-bezier(.16,1,.3,1) 1 both; }
@keyframes ui-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.ui { border: 1px solid var(--st-line); background: var(--st-fill); }
.ui.phone { max-width: 300px; }
.ui-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 13px; border-bottom: 1px solid var(--st-line-soft);
  font-family: var(--mono); font-size: 10.5px; color: var(--st-dim);
}
.ui-bar b { font-weight: 400; color: var(--st-ink); }
.ui-body { padding: 14px 13px; display: flex; flex-direction: column; gap: 9px; }
.ui-body.tight { gap: 7px; }
.ui-foot { display: flex; gap: 8px; padding: 11px 13px; border-top: 1px solid var(--st-line-soft); flex-wrap: wrap; }

/* Grey bars stand in for copy that isn't the point of the exhibit. */
.ui-line { height: 7px; background: var(--st-line); }
.ui-line.w80 { width: 80%; } .ui-line.w70 { width: 70%; }
.ui-line.w60 { width: 60%; } .ui-line.w55 { width: 55%; } .ui-line.w40 { width: 40%; }

.ui-note { margin: 3px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--st-dim); }
.ui-k { font-family: var(--mono); font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--st-faint); }
.ui-btn {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em;
  border: 1px solid var(--st-line); background: none; color: var(--st-dim);
  padding: 7px 12px; cursor: pointer; transition: .18s;
}
.ui-btn:hover { border-color: var(--st-accent); color: var(--st-accent); }
.ui-btn.primary { background: var(--st-ink); color: var(--st-base); border-color: var(--st-ink); }
.ui-btn.ghost { border-color: transparent; color: var(--st-faint); }

.ui-chip {
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
  padding: 3px 7px; border: 1px solid currentColor;
}
.ui-chip.good { color: var(--sig-good); }
.ui-chip.warn { color: var(--sig-warn); }
.ui-chip.bad  { color: var(--sig-bad); }
.ui-chip.info { color: var(--sig-info); }

.ui-perm {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 7px 0; border-bottom: 1px dashed var(--st-line-soft);
  font-size: 12.5px; color: var(--st-dim);
}
.ui-perm:last-child { border-bottom: 0; }
/* Rows that differ from the previous identity announce themselves, so the
   switch reads as a change rather than a redraw of the same table. */
.ui-perm.changed { animation: perm-flip .55s cubic-bezier(.16,1,.3,1) both; }
@keyframes perm-flip {
  0%   { background: color-mix(in srgb, var(--st-accent) 26%, transparent); transform: translateX(4px); }
  100% { background: transparent; transform: none; }
}
/* A single number that always differs: how much the agent can do unattended. */
.ui-reach {
  display: flex; align-items: center; gap: 12px; padding: 9px 13px;
  border-bottom: 1px solid var(--st-line-soft);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--st-faint);
}
.ui-reach-bar { flex: 1; height: 6px; background: var(--st-fill); display: block; }
.ui-reach-bar i {
  display: block; height: 100%; width: var(--w);
  transition: width .5s cubic-bezier(.16,1,.3,1);
}
.ui-reach b { color: var(--st-ink); font-weight: 400; white-space: nowrap; }
.sk-good { background: var(--sig-good); }
.sk-warn { background: var(--sig-warn); }
.sk-bad  { background: var(--sig-bad); }
@media (prefers-reduced-motion: reduce) {
  .ui-perm.changed { animation: none; }
  .ui-reach-bar i { transition: none; }
}

.ui-grp { display: flex; flex-direction: column; gap: 5px; margin-bottom: 4px; }
.ui-fact {
  font-size: 12px; line-height: 1.45; padding: 6px 9px;
  border-left: 2px solid var(--st-line); color: var(--st-dim); background: var(--st-fill);
}
.ui-fact.good  { border-left-color: var(--sig-good); }
.ui-fact.warn  { border-left-color: var(--sig-warn); }
.ui-fact.info  { border-left-color: var(--sig-info); }
/* Struck through — this variant means "ruled out", so it's only correct
   where elimination is the point. Use .soft for merely secondary text. */
.ui-fact.muted { color: var(--st-faint); text-decoration: line-through; text-decoration-color: var(--st-line); }
.ui-fact.soft { color: var(--st-faint); }
.ui-fact b { color: var(--st-ink); font-weight: 400; }

.ui-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 7px; }
.ui-tiles span { height: 42px; border: 1px solid var(--st-line); background: var(--st-fill); }
.ui-wave { display: flex; align-items: center; gap: 4px; height: 34px; }
.ui-wave i { flex: 1; background: var(--sig-info); animation: ui-wv 1.1s ease-in-out infinite; }
.ui-wave i:nth-child(odd) { animation-delay: .16s; }
.ui-wave i:nth-child(3n) { animation-delay: .32s; }
@keyframes ui-wv { 0%, 100% { height: 22%; } 50% { height: 100%; } }
.ui-bub {
  font-size: 12px; line-height: 1.45; padding: 7px 10px; max-width: 88%;
  border: 1px solid var(--st-line); color: var(--st-dim);
}
.ui-bub.me { margin-left: auto; background: var(--st-fill); color: var(--st-ink); }

/* Tooling chapter: a stand-in design frame, the schema, the render. */
.ui-frame {
  border: 1px dashed var(--st-line); padding: 12px; display: flex;
  flex-direction: column; gap: 8px;
}
.ui-frame.live { border-style: solid; border-color: var(--sig-good); }
.ui-btnrow { display: flex; gap: 7px; margin-top: 2px; }
.ui-btnrow span { width: 62px; height: 20px; border: 1px solid var(--st-line); display: block; }
.ui-btnrow span.on { background: var(--st-ink); border-color: var(--st-ink); }
.ui-code {
  margin: 0; padding: 12px; overflow-x: auto;
  border-left: 2px solid var(--sig-info); background: var(--st-fill);
  font-family: var(--mono); font-size: 11px; line-height: 1.6; color: var(--st-dim);
  white-space: pre;
}

.ui-cap {
  margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--st-dim);
  padding-left: 12px; border-left: 1px solid var(--st-accent); max-width: 76ch;
}

@media (prefers-reduced-motion: reduce) {
  .ui-stage.swap { animation: none; }
  .ui-wave i { animation: none; height: 60%; }
}

/* ---------- transport ---------- */
.st-foot { display: flex; align-items: center; gap: 18px; padding-top: clamp(8px, 1.4vh, 16px); border-top: 1px solid var(--st-line-soft); }
.st-dots { display: flex; gap: 6px; flex: 1; }
.st-dots button { background: none; border: 0; padding: 6px 2px; cursor: pointer; }
.st-dots span { display: block; width: 28px; height: 2px; background: var(--st-line); transition: .25s; }
.st-dots button[aria-current="true"] span { background: var(--st-accent); }
.st-nav button {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--st-line); background: none; color: var(--st-dim); padding: 8px 15px; cursor: pointer; transition: .18s;
}
.st-nav button:hover:not(:disabled) { border-color: var(--st-accent); color: var(--st-accent); }
.st-nav button:disabled { opacity: .32; cursor: default; }
/* The exit reads as the end of something, not as another step. */
.st-nav button.is-exit {
  background: var(--st-ink); color: var(--st-base); border-color: var(--st-ink);
}
.st-nav button.is-exit:hover { background: var(--st-accent); border-color: var(--st-accent); color: var(--st-base); }

/* ============================================================
   Chapter visuals — token-driven so both themes hold up
   ============================================================ */
.v-lane-k, .v-row-k, .v-step-k, .v-mode-k, .v-orb em { color: var(--st-dim); }
.v-track, .v-scope span { background: var(--st-line); }
.v-reach, .v-dev, .v-bub { border-color: var(--st-line); }
.v-node, .v-orb span { border-color: var(--st-line); }
.v-human { border-color: var(--st-ink); }

/* 01 — autonomy */
.v-auton { display: flex; flex-direction: column; gap: 26px; }
.v-lane { display: grid; grid-template-columns: 96px 1fr 22px; gap: 16px; align-items: center; }
.v-lane-k { font-family: var(--mono); font-size: 10.5px; text-align: right; }
.v-track { position: relative; height: 2px; }
.v-gate { position: absolute; top: -11px; left: 62%; width: 2px; height: 24px; }
.v-gate.solid { background: var(--sig-bad); }
.v-gate.dashed { background: repeating-linear-gradient(180deg, var(--sig-warn) 0 4px, transparent 4px 8px); }
.v-gate.open { background: var(--sig-good); opacity: .45; }
.v-pip { position: absolute; top: -4px; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--sig-info); }
.v-human { width: 10px; height: 10px; border: 1px solid; border-radius: 50%; }
.v-human.off { opacity: .25; }
.play .v-lane[data-lane="0"] .v-pip { animation: pip-stop 2.8s cubic-bezier(.16,1,.3,1) 1 forwards; }
.play .v-lane[data-lane="1"] .v-pip { animation: pip-pause 2.8s cubic-bezier(.16,1,.3,1) 1 forwards; }
.play .v-lane[data-lane="2"] .v-pip { animation: pip-through 2.8s cubic-bezier(.16,1,.3,1) 1 forwards; }
@keyframes pip-stop { 0% { left: 0; } 50% { left: 60%; } 72% { left: 60%; opacity: 1; } 100% { left: 60%; opacity: .3; } }
@keyframes pip-pause { 0% { left: 0; } 42% { left: 60%; } 70% { left: 60%; } 100% { left: calc(100% - 10px); } }
@keyframes pip-through { 0% { left: 0; } 100% { left: calc(100% - 10px); } }

/* 02 — rbac */
.v-rbac { display: flex; flex-direction: column; gap: 18px; }
.v-row { display: grid; grid-template-columns: 130px 1fr; gap: 16px; align-items: center; }
.v-row-k { font-family: var(--mono); font-size: 10.5px; text-align: right; }
.v-reach { height: 16px; border: 1px dashed; position: relative; }
.v-reach i { position: absolute; inset: 0 auto 0 0; width: 0; background: currentColor; opacity: .45; }
.play .v-reach i { animation: reach 1.9s cubic-bezier(.16,1,.3,1) 1 forwards; }
.play .v-row[data-i="1"] .v-reach i { animation-delay: .28s; }
.play .v-row[data-i="2"] .v-reach i { animation-delay: .56s; }
@keyframes reach { from { width: 0; } to { width: var(--w); } }
.v-scope { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; margin-top: 6px; }
.v-scope span { height: 4px; }

/* 03 — trace */
.v-trace { display: flex; flex-direction: column; position: relative; }
.v-step { display: grid; grid-template-columns: 22px 1fr; gap: 14px; align-items: center; padding: 11px 0; position: relative; }
.v-step::after { content: ""; position: absolute; left: 10px; top: 28px; bottom: -6px; width: 1px; background: var(--st-line); }
.v-step:last-of-type::after { display: none; }
.v-node { width: 11px; height: 11px; border: 1px solid; border-radius: 50%; justify-self: center; }
.v-step-k { font-family: var(--mono); font-size: 11px; color: var(--st-faint); }
.play .v-step .v-node { animation: node-on .5s ease 1 forwards; }
.play .v-step .v-step-k { animation: key-on .5s ease 1 forwards; }
.play .v-step[data-i="1"] .v-node, .play .v-step[data-i="1"] .v-step-k { animation-delay: .4s; }
.play .v-step[data-i="2"] .v-node, .play .v-step[data-i="2"] .v-step-k { animation-delay: .8s; }
.play .v-step[data-i="3"] .v-node, .play .v-step[data-i="3"] .v-step-k { animation-delay: 1.2s; }
.play .v-step[data-i="4"] .v-node, .play .v-step[data-i="4"] .v-step-k { animation-delay: 1.6s; }
@keyframes node-on { to { background: var(--sig-info); border-color: var(--sig-info); } }
@keyframes key-on { to { color: var(--st-ink); } }
.v-stop {
  position: absolute; right: 0; top: 0; font-family: var(--mono); font-size: 10px;
  letter-spacing: .12em; text-transform: uppercase; border: 1px solid var(--sig-bad);
  color: var(--sig-bad); background: none; padding: 6px 12px; cursor: default;
}

/* 04 — memory */
.v-mem { display: flex; justify-content: center; }
.v-cycle { position: relative; width: 250px; height: 250px; }
.v-ring { position: absolute; inset: 0; width: 100%; height: 100%; }
.v-ring circle { fill: none; stroke: var(--st-line); stroke-width: 1; stroke-dasharray: 3 5; }
.v-orb { position: absolute; width: 96px; margin-left: -48px; text-align: center; }
.v-orb span { display: block; width: 13px; height: 13px; border: 1px solid; border-radius: 50%; margin: 0 auto 7px; }
.v-orb em { font-family: var(--mono); font-size: 10px; font-style: normal; letter-spacing: .05em; }
.v-orb[data-i="0"] { left: 50%; top: 4px; }
.v-orb[data-i="1"] { left: 92%; top: 44%; }
.v-orb[data-i="2"] { left: 50%; top: 82%; }
.v-orb[data-i="3"] { left: 8%; top: 44%; }
.play .v-orb span { animation: orb .55s ease 1 forwards; }
.play .v-orb em { animation: orb-k .55s ease 1 forwards; }
.play .v-orb[data-i="1"] span, .play .v-orb[data-i="1"] em { animation-delay: .5s; }
.play .v-orb[data-i="2"] span, .play .v-orb[data-i="2"] em { animation-delay: 1s; }
.play .v-orb[data-i="3"] span, .play .v-orb[data-i="3"] em { animation-delay: 1.5s; }
@keyframes orb { to { background: var(--sig-good); border-color: var(--sig-good); } }
@keyframes orb-k { to { color: var(--st-ink); } }

/* 05 — access */
.v-access { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.v-mode { display: flex; flex-direction: column; align-items: center; gap: 12px; opacity: .34; }
.v-dev { width: 100%; height: 142px; border: 1px dashed; display: flex; flex-direction: column;
         align-items: center; justify-content: center; gap: 8px; padding: 14px; }
.v-mode-k { font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.play .v-mode { animation: mode-on .5s ease 1 forwards; }
.play .v-mode[data-i="1"] { animation-delay: .55s; }
.play .v-mode[data-i="2"] { animation-delay: 1.1s; }
@keyframes mode-on { to { opacity: 1; } }
.v-bar { width: 70%; height: 10px; background: var(--st-fill); border: 1px solid var(--st-line); }
.v-bar.sm { width: 46%; height: 6px; }
.v-wave { display: flex; align-items: flex-end; gap: 4px; height: 46px; }
.v-wave i { width: 4px; background: var(--st-dim); }
.v-wave i:nth-child(1) { height: 16px; } .v-wave i:nth-child(2) { height: 34px; }
.v-wave i:nth-child(3) { height: 46px; } .v-wave i:nth-child(4) { height: 26px; }
.v-wave i:nth-child(5) { height: 38px; }
.v-bub { width: 60%; height: 12px; border: 1px dashed; align-self: flex-start; }
.v-bub.me { align-self: flex-end; width: 42%; background: var(--st-fill); border-style: solid; }

@media (prefers-reduced-motion: reduce) {
  .play .v-pip, .play .v-reach i, .play .v-node, .play .v-step-k,
  .play .v-orb span, .play .v-orb em, .play .v-mode { animation: none !important; }
  .v-reach i { width: var(--w); }
  .v-mode { opacity: 1; }
  .v-node { background: var(--sig-info); border-color: var(--sig-info); }
  .v-orb span { background: var(--sig-good); border-color: var(--sig-good); }
}

@media (max-width: 940px) {
  #story { grid-template-columns: 1fr; height: auto; overflow: visible; }
  .st-main { padding: 26px 24px 20px; overflow: visible;
             background: linear-gradient(180deg, var(--st-scrim) 0%, var(--st-scrim) 78%, transparent 100%); }
  .st-rail { border-left: 0; border-top: 1px solid var(--st-line-soft); height: 60vh; }
  .v-access { grid-template-columns: 1fr; }
  .v-cycle { width: 210px; height: 210px; }
}

/* The chapter is rendered into a plain wrapper div, which was content-sized
   — so `.st-viz { flex: 1 }` had no free space to absorb and the transport
   drifted up to 95px between chapters. Making the wrapper a growing flex
   column pins the belt and footer to the bottom of the stage. */
.st-main > [data-stage] {
  flex: 1; display: flex; flex-direction: column; min-height: 0;
}

/* The media placeholder is the first thing to go: it describes a
   screenshot that isn't there, while a working prototype sits directly
   above it. Raised from 860px because at 900px-tall laptops it was
   costing the prototype enough room to force the fitViz scale floor —
   trading a legible card for a line of placeholder text. */
@media (max-height: 1000px) {
  .st-slot { display: none; }
}

/* Chapter prototypes are sized against the stage, not the page — a slide
   that scrolls has stopped being a slide. The upper bounds are generous
   because the card routinely sits ~300px short of its slot: it was
   reading as cramped while surrounded by unused space. */
.st-viz .ui-wrap { gap: clamp(8px, 1.4vh, 16px); max-width: 720px; }
.st-viz .ui-body { padding: clamp(11px, 2vh, 20px) clamp(13px, 1.6vw, 20px); gap: clamp(7px, 1.5vh, 14px); }
.st-viz .ui-body.tight { gap: clamp(6px, 1.3vh, 12px); }
.st-viz .ui-foot { padding: clamp(9px, 1.6vh, 15px) clamp(13px, 1.6vw, 20px); }
.st-viz .ui-bar { padding: clamp(9px, 1.6vh, 14px) clamp(13px, 1.6vw, 20px); }
/* Rows carry a title, a severity tag and a reason — 8px of vertical
   padding put three lines of content in the space of one. */
.st-viz .pb-line { padding: clamp(8px, 1.3vh, 13px) 0; }
.st-viz .ui-perm { padding: clamp(7px, 1.2vh, 12px) 0; }
.st-viz .ui-cap { font-size: clamp(11px, 1.5vh, 12.5px); line-height: 1.5; }
.st-viz .ui-fact { padding: clamp(4px, .8vh, 6px) 9px; }
.st-viz .ui-code { font-size: clamp(9.5px, 1.3vh, 11px); padding: clamp(8px, 1.4vh, 12px); }

/* ---------- project walkthrough prototypes ---------- */
.ui-mono { font-family: var(--mono); font-size: 11px; color: var(--st-dim); }
.ui-perm .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 8px; vertical-align: 1px; }
.dot.high { background: var(--sig-good); }
.dot.med  { background: var(--sig-warn); }
.dot.low  { background: var(--sig-bad); }
.ui-perm.dropped { opacity: .45; }
.ui-perm.dropped .ui-mono { text-decoration: line-through; }
/* Where a proposed field came from — carried on the row itself, because
   provenance you have to look up isn't provenance. */
.ui-src {
  display: block; margin-left: 15px; font-style: normal;
  font-family: var(--mono); font-size: 9px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--st-faint);
}
/* Severity on a failed playbook rule — the flags are ordered by it, so it
   has to be readable at a glance rather than inferred from position. */
.ui-sev {
  display: inline-block; margin-left: 8px; font-family: var(--mono);
  font-size: 8.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 1px 5px; border: 1px solid currentColor; vertical-align: 1px;
}
.ui-sev.high { color: var(--sig-bad); }
.ui-sev.low { color: var(--sig-warn); }

/* The two governance settings, shown as the switches they are. */
.gv-set { display: flex; gap: 1px; background: var(--st-line-soft); border: 1px solid var(--st-line-soft); }
.gv-set > div {
  flex: 1; background: var(--st-fill); padding: 10px 13px;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.gv-set span {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--st-faint);
}
.gv-set b { font-weight: 400; font-size: 14px; color: var(--st-faint); }
.gv-set b.on { color: var(--sig-good); }

.pb-line { display: grid; grid-template-columns: 9px 1fr; gap: 11px; padding: 8px 0; align-items: start; }
.pb-line + .pb-line { border-top: 1px dashed var(--st-line-soft); }
.pb-line i { width: 7px; height: 7px; border-radius: 50%; background: var(--st-line); margin-top: 5px; }
.pb-line.ok i { background: var(--sig-good); }
.pb-line.no i { background: var(--sig-bad); }
.pb-line b { font-weight: 400; color: var(--st-ink); font-size: 12.5px; }
.pb-line p { margin: 3px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--st-dim); }

.ui-note { font-size: 12px; line-height: 1.55; color: var(--st-dim); }
.ui-note.big { font-size: 13px; }
.ui-note b { color: var(--st-ink); font-weight: 400; }
.ui-note code { font-family: var(--mono); font-size: 11px; color: var(--st-ink); }

/* Frictionary heatmap viz — a page area with friction markers. In the
   "actually" state, two markers sit off the bottom edge and dim, which
   is exactly the bug the chapter is about. overflow:hidden clips them so
   they read as "drawn nowhere". */
.fr-hm { position: relative; height: 150px; overflow: hidden;
  border: 1px solid var(--st-line); background: var(--st-fill);
  background-image: repeating-linear-gradient(var(--st-line-soft) 0 1px, transparent 1px 26px); }
.fr-mk { position: absolute; width: 18px; height: 18px; margin: -9px 0 0 -9px; border-radius: 50%;
  transition: top .5s cubic-bezier(.16,1,.3,1), opacity .4s; }
.fr-mk.on { background: color-mix(in srgb, var(--sig-bad) 30%, transparent);
  border: 1px solid var(--sig-bad); box-shadow: 0 0 0 5px color-mix(in srgb, var(--sig-bad) 10%, transparent); }
.fr-mk.off { background: none; border: 1px dashed var(--st-faint); opacity: .4; }
@media (prefers-reduced-motion: reduce) { .fr-mk { transition: none; } }
.ui-list { margin: 6px 0 0; padding-left: 17px; }
.ui-list li { font-size: 11.5px; line-height: 1.7; color: var(--st-dim); }
.ui-verdict { margin-bottom: 4px; }

/* Boundary — the one step that used to leave M365. */
.bd-row { display: flex; align-items: center; margin-bottom: 12px; }
.bd-step { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 7px; position: relative; }
.bd-step::before { content: ""; position: absolute; top: 5px; left: -50%; width: 100%; height: 1px; background: var(--st-line); }
.bd-step:first-child::before { display: none; }
.bd-step i { width: 11px; height: 11px; border-radius: 50%; z-index: 1; border: 2px solid var(--sig-good); background: var(--st-base); }
.bd-step.out i { border-color: var(--sig-bad); border-style: dashed; }
.bd-step span { font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; color: var(--st-dim); }
.bd-step.out span { color: var(--sig-bad); }

/* Handoff — a named person versus a reference number. */
.hd-person { display: flex; gap: 12px; align-items: flex-start; }
.hd-face { width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: linear-gradient(140deg, var(--sig-info), var(--st-line)); border: 1px solid var(--st-line); }
.hd-person b { font-size: 13px; color: var(--st-ink); font-weight: 400; }
.hd-spin { display: flex; justify-content: center; padding: 14px 0; }
.hd-spin i { width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid var(--st-line); border-top-color: var(--st-faint); animation: hd-turn 1s linear infinite; }
@keyframes hd-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .hd-spin i { animation: none; } }

/* Orientation card — plain statements, one per line, no ornament. */
.cx-row { display: grid; grid-template-columns: 7px 1fr; gap: 12px; align-items: start; padding: 7px 0; }
.cx-row + .cx-row { border-top: 1px dashed var(--st-line-soft); }
.cx-row i { width: 5px; height: 5px; border-radius: 50%; background: var(--st-accent); margin-top: 7px; }
.cx-row span { font-size: 13px; line-height: 1.5; color: var(--st-dim); }

/* Queue / weeks / funnel — proportional bars where the shape is the point. */
.wk-row { display: grid; grid-template-columns: minmax(120px, 1.2fr) 2fr 42px; gap: 12px; align-items: center; padding: 5px 0; }
.wk-k { font-size: 12.5px; color: var(--st-ink); }
.wk-k.dim { color: var(--st-faint); }
.wk-track { height: 10px; background: var(--st-fill); display: block; }
.wk-track i { display: block; height: 100%; width: var(--w); animation: wk-grow .5s cubic-bezier(.16,1,.3,1) both; }
.wk-flat  { background: var(--st-line); }
.wk-work  { background: var(--sig-info); }
.wk-queue { background: var(--sig-bad); }
.wk-d { font-family: var(--mono); font-size: 10.5px; color: var(--st-dim); text-align: right; }
@keyframes wk-grow { from { transform: scaleX(0); transform-origin: left; } }
@media (prefers-reduced-motion: reduce) { .wk-track i { animation: none; } }

/* Postcard — verification by delivery, as three numbered beats. */
.pc-flow { display: flex; flex-direction: column; gap: 9px; margin-bottom: 10px; }
.pc-step { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: center; }
.pc-step i {
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--sig-good); color: var(--sig-good);
  font-family: var(--mono); font-size: 10px; font-style: normal;
}
.pc-step span { font-size: 12.5px; line-height: 1.45; color: var(--st-dim); }
