/* ==========================================================================
   GraphABI: Semantic Pulse
   Two graph languages, in deliberate opposition:
   - the ambient field is organic, continuous and never resolves;
   - every product surface is precise, deterministic, and stops.
   ========================================================================== */

:root {
  color-scheme: light dark;

  /* Light theme is designed, not inverted. */
  --bg:              #FBFCFD;
  --bg-sunk:         #F1F4F8;
  --surface:         #FFFFFF;
  --surface-2:       #F5F8FA;
  --surface-code:    #F7F9FB;
  --border:          #E3E8EF;
  --border-strong:   #CBD5E1;
  --text:            #0B0F14;
  --muted:           #4C5866;
  --subtle:          #5D6B7A;
  --primary:         #6D28D9;
  --primary-hover:   #5B21B6;
  --on-primary:      #FFFFFF;
  --pulse:           #7C3AED;
  --pass:            #15803D;
  --fail:            #DC2626;
  --unknown:         #B45309;
  --edge:            #A3B0C0;
  --code:            #1E293B;

  /* Status colours split by role. Strokes, rails and marks only have to
     clear 3:1 as non-text UI; anything set as small text has to clear 4.5:1
     on every surface it can land on, including the status tints. */
  --pass-text:       #136B33;
  --fail-text:       #C81E1E;
  --unknown-text:    #9A4708;

  --tint-pulse:      rgba(124, 58, 237, .07);
  --tint-pass:       rgba(21, 128, 61, .08);
  --tint-fail:       rgba(220, 38, 38, .06);
  --edge-pulse:      rgba(124, 58, 237, .35);
  --edge-pass:       rgba(21, 128, 61, .35);
  --edge-fail:       rgba(220, 38, 38, .35);
  --header-bg:       rgba(251, 252, 253, .78);
  --shadow-card:     0 1px 2px rgba(11, 15, 20, .04), 0 8px 24px -12px rgba(11, 15, 20, .10);
  --shadow-lift:     0 1px 2px rgba(11, 15, 20, .05), 0 18px 48px -20px rgba(11, 15, 20, .22);
  --shadow-modal:    0 32px 80px -24px rgba(11, 15, 20, .32);
  --field-alpha:     .82;

  /* 8px spacing system. --s0 is the only half-step, for optical alignment. */
  --s0: 4px;  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 32px;
  --s5: 40px; --s6: 48px; --s7: 64px; --s8: 80px; --s9: 96px;
  --s10: 128px; --s11: 160px; --s12: 192px;

  --sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: "SFMono-Regular", "Cascadia Code", "Roboto Mono", ui-monospace, monospace;

  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);
  --t-fast: 220ms;
  --t-mid: 320ms;
  --t-slow: 500ms;

  /* Where a stopped pulse rests on an edge, as a fraction of edge length.
     The cut sits at 50%, so the pulse must always come to rest short of it. */
  --break-stop: .34;

  --radius: 12px;
  --radius-sm: 8px;
  --radius-lg: 16px;
  --gutter: var(--s6);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg:            #0B0F14;
    --bg-sunk:       #080B0F;
    --surface:       #111820;
    --surface-2:     #18212C;
    --surface-code:  #0D131A;
    --border:        #222E3C;
    --border-strong: #33414F;
    --text:          #F8FAFC;
    --muted:         #97A5B6;
    --subtle:        #8695A6;
    --primary:       #8B5CF6;
    --primary-hover: #A78BFA;
    --on-primary:    #0B0F14;
    --pulse:         #A78BFA;
    --pass:          #22C55E;
    --fail:          #EF4444;
    --unknown:       #F59E0B;
    --edge:          #46556A;
    --code:          #D5DDE8;

    --pass-text:     #22C55E;
    --fail-text:     #F87171;
    --unknown-text:  #F59E0B;

    --tint-pulse:    rgba(167, 139, 250, .10);
    --tint-pass:     rgba(34, 197, 94, .10);
    --tint-fail:     rgba(239, 68, 68, .08);
    --edge-pulse:    rgba(167, 139, 250, .45);
    --edge-pass:     rgba(34, 197, 94, .40);
    --edge-fail:     rgba(239, 68, 68, .42);
    --header-bg:     rgba(11, 15, 20, .72);
    --shadow-card:   0 1px 0 rgba(255, 255, 255, .02) inset, 0 12px 32px -18px rgba(0, 0, 0, .8);
    --shadow-lift:   0 1px 0 rgba(255, 255, 255, .03) inset, 0 24px 60px -24px rgba(0, 0, 0, .9);
    --shadow-modal:  0 40px 96px -28px rgba(0, 0, 0, .85);
    --field-alpha:   1;
  }
}

/* --------------------------------------------------------------- base --- */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--s9);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.65 var(--sans);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; height: auto }
svg { display: block }
a { color: inherit; text-decoration: none }
button, a { -webkit-tap-highlight-color: transparent }
button { font: inherit }

:focus-visible {
  outline: 2px solid var(--pulse);
  outline-offset: 3px;
  border-radius: 3px;
}

.skip-link {
  position: fixed;
  top: var(--s2);
  left: var(--s2);
  z-index: 200;
  display: grid;
  place-items: center;
  min-height: 44px;
  padding: 0 var(--s2);
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: var(--on-primary);
  font-weight: 650;
  transform: translateY(-200%);
  transition: transform var(--t-fast) var(--ease);
}
.skip-link:focus { transform: none }

.shell {
  position: relative;
  width: min(1200px, 100% - (var(--gutter) * 2));
  margin-inline: auto;
}

.sr-only {
  position: absolute !important;
  width: 1px !important; height: 1px !important;
  padding: 0 !important; margin: -1px !important;
  overflow: hidden !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* -------------------------------------------------------- typography --- */

h1, h2, h3, p, ol, ul, figure, pre { margin: 0 }
h1, h2, h3 { font-weight: 640; text-wrap: balance }

h1 {
  font-size: clamp(2.125rem, 7.6vw, 6.5rem);
  line-height: .93;
  letter-spacing: -.042em;
}
h1 .line { display: block }
h1 em { font-style: normal; color: var(--fail) }

h2 {
  font-size: clamp(2rem, 4.4vw, 3.5rem);
  line-height: 1.04;
  letter-spacing: -.034em;
}

.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s1);
  margin-bottom: var(--s3);
  color: var(--pulse);
  font-size: .6875rem;
  font-weight: 650;
  letter-spacing: .13em;
  text-transform: uppercase;
}
/* The eyebrow bullet is a graph node: sections are nodes on one traversal. */
.eyebrow i {
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--pulse);
  box-shadow: 0 0 0 4px var(--tint-pulse);
}

.hero-lede, .cta-lede {
  color: var(--muted);
  font-size: clamp(1.0625rem, 1.5vw, 1.3125rem);
  line-height: 1.6;
  text-wrap: pretty;
}

code, pre, .mono { font-family: var(--mono); font-variant-ligatures: none }

/* -------------------------------------------------------- the field --- */

.field {
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  opacity: var(--field-alpha);
  pointer-events: none;
  /* Density falls away from the top so the field never fights body copy. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 42%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.28) 100%);
          mask-image: linear-gradient(180deg, #000 0%, #000 42%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.28) 100%);
}

.field-veil {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(58% 58% at 30% 30%, var(--bg) 0%, var(--bg) 38%, transparent 78%),
    radial-gradient(120% 70% at 50% 0%, transparent 40%, var(--bg) 100%),
    radial-gradient(80% 50% at 12% 22%, var(--tint-pulse), transparent 70%);
}

.site-header, main, .site-footer { position: relative; z-index: 1 }

/* ----------------------------------------------------------- header --- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-mid) var(--ease), background var(--t-mid) var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--border);
  background: var(--header-bg);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
          backdrop-filter: saturate(180%) blur(12px);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 72px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  min-height: 44px;
  margin-left: -2px;
}
.brand-word {
  font-size: 1.125rem;
  font-weight: 650;
  letter-spacing: -.028em;
}
.brand-mark { display: block; flex: 0 0 auto }
.brand-mark svg { overflow: visible }

/* One mark, theme-aware, no second asset and no font dependency. */
.m-live        { fill: var(--pulse) }
.m-dead        { fill: var(--edge) }
.m-live-stroke { fill: none; stroke: var(--pulse); stroke-width: 4; stroke-linecap: round }
.m-dead-stroke { fill: none; stroke: var(--edge);  stroke-width: 4; stroke-linecap: round }
.m-cut         { fill: none; stroke: var(--fail);  stroke-width: 3.5; stroke-linecap: round }

/* The mark's live segment carries a pulse when the brand is hovered. */
.brand .m-live-stroke {
  stroke-dasharray: 5 9;
  stroke-dashoffset: 0;
}
.brand:hover .m-live-stroke,
.brand:focus-visible .m-live-stroke {
  animation: mark-flow 900ms var(--ease-io) infinite;
}
@keyframes mark-flow { to { stroke-dashoffset: -14 } }

.nav-links { display: flex; align-items: center; gap: var(--s0) }
.nav-links a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--s2);
  color: var(--muted);
  font-size: .875rem;
  font-weight: 550;
  transition: color var(--t-fast) var(--ease);
}
.nav-links a:hover { color: var(--text) }

/* Hovering a link completes an edge underneath it. */
.nav-links a:not(.nav-github) span { position: relative }
.nav-links a:not(.nav-github) span::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -6px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--pulse);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-mid) var(--ease);
}
.nav-links a:not(.nav-github):hover span::after,
.nav-links a:not(.nav-github):focus-visible span::after { transform: scaleX(1) }

.nav-github {
  gap: 6px;
  margin-left: var(--s1);
  padding-inline: var(--s2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text) !important;
  font-weight: 600;
  box-shadow: var(--shadow-card);
  transition: border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.nav-github svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round }
.nav-github:hover { border-color: var(--border-strong); transform: translateY(-1px) }

/* ------------------------------------------------------------- hero --- */

.hero { padding: var(--s9) 0 var(--s7) }
.hero-copy { max-width: 1000px }

h1 { margin-bottom: var(--s4) }
.hero-lede { max-width: 52ch; margin-bottom: var(--s6) }

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s1) }

/* ---------------------------------------------------------- buttons --- */

.button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 48px;
  padding: 0 var(--s3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: 650 .875rem var(--sans);
  letter-spacing: -.006em;
  cursor: pointer;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.button svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round }
.button:hover { transform: translateY(-1px) }
.button:active { transform: translateY(0) }

.button.primary {
  border-color: transparent;
  background: var(--primary);
  color: var(--on-primary);
}
.button.primary:hover { background: var(--primary-hover) }
.button.secondary:hover { border-color: var(--border-strong) }

/* A pulse crosses the control's own edge on hover: the same primitive,
   at the smallest possible scale. */
.button::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1.5px;
  background: linear-gradient(90deg, transparent, currentColor, transparent);
  opacity: 0;
  transform: translateX(-100%);
}
.button:hover::after, .button:focus-visible::after {
  opacity: .55;
  animation: edge-cross 620ms var(--ease-io);
}
@keyframes edge-cross {
  from { transform: translateX(-100%) }
  to   { transform: translateX(100%) }
}

/* ----------------------------------------------------- install line --- */

.install-line {
  display: flex;
  align-items: center;
  gap: var(--s1);
  max-width: 780px;
  margin-top: var(--s5);
  padding: var(--s0) var(--s0) var(--s0) var(--s2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  transition: border-color var(--t-fast) var(--ease);
}
.install-line:hover { border-color: var(--border-strong) }
.install-prompt { flex: 0 0 auto; color: var(--pulse); font: 600 .8125rem var(--mono) }
.install-line code {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  padding: var(--s2) 0;
  color: var(--code);
  font-size: .8125rem;
  line-height: 1.5;
  white-space: nowrap;
  scrollbar-width: none;
}
.install-line code::-webkit-scrollbar { display: none }

.install-copy {
  position: relative;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.install-copy:hover { color: var(--text); border-color: var(--border-strong) }
.install-copy svg {
  grid-area: 1 / 1;
  fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.install-copy .i-done { opacity: 0; transform: scale(.6) }
.install-copy.copied { color: var(--pass-text); border-color: var(--edge-pass) }
.install-copy.copied .i-copy { opacity: 0; transform: scale(.6) }
.install-copy.copied .i-done { opacity: 1; transform: none }

/* =========================================================== sections ===
   Each section is a node on one traversal. A rail descends from the
   previous section and lands on the section's eyebrow dot.
   ======================================================================== */

.section > .shell { padding-top: var(--s12) }

/* The rail and its node are structure, so they render regardless. Only the
   arrival animation is withheld, and only when something can play it. */
.section > .shell::before {
  content: "";
  position: absolute;
  left: 3px;
  top: var(--s6);
  width: 1px;
  height: calc(var(--s12) - var(--s6) - 3px);
  background: linear-gradient(180deg, transparent, var(--border-strong) 22%, var(--pulse));
  transform-origin: top;
}

.js .section > .shell::before {
  transform: scaleY(0);
  transition: transform 900ms var(--ease);
}
.js .section.is-reached > .shell::before { transform: scaleY(1) }

.js .section .eyebrow i {
  transform: scale(.35);
  opacity: 0;
  transition: transform var(--t-slow) var(--ease) 260ms, opacity var(--t-mid) var(--ease) 260ms;
}
.js .section.is-reached .eyebrow i { transform: none; opacity: 1 }

.section-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s7);
  margin-bottom: var(--s7);
}
.section-heading > div { flex: 1 1 58% }
.section-heading > p {
  flex: 0 1 440px;
  color: var(--muted);
  font-size: 1.0625rem;
  line-height: 1.6;
  text-wrap: pretty;
}

/* Section composition changes with the kind of evidence being presented. */
.bug-heading {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(280px, .6fr);
  align-items: start;
}
.bug-heading h2 { max-width: 9ch; font-size: clamp(2.75rem, 6.4vw, 5.75rem) }
.bug-heading > p {
  margin-top: var(--s9);
  padding: var(--s3) 0 var(--s3) var(--s3);
  border-left: 1px solid var(--pulse);
}

.terminal-section > .shell {
  display: grid;
  grid-template-columns: minmax(260px, .56fr) minmax(0, 1.44fr);
  align-items: start;
  gap: var(--s8);
}
.terminal-section .section-heading { display: block; margin: var(--s3) 0 0 }
.terminal-section .section-heading > p { margin-top: var(--s3); font-size: .9375rem }

.report-section {
  margin-top: var(--s8);
  border-block: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-sunk) 78%, transparent);
}
.report-section > .shell { padding-bottom: var(--s10) }
.report-section .section-heading { align-items: start }
.report-section .section-heading h2 { max-width: 12ch }

/* Shared surface treatment for every instrument panel. */
.pulse-scene, .playground, .payload, .method-rail, .code-layout,
.terminal, .arch-frame, .report-figure, .final-cta {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

/* ==================================================== the instrument ===
   The canonical replay. Precise, causal, and it comes to rest.
   ====================================================================== */

.pulse-scene {
  margin-top: var(--s9);
  overflow: hidden;
  box-shadow: var(--shadow-lift);
}

.scene-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s2) var(--s2) var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.scene-meta { display: flex; flex-direction: column; gap: 3px; min-width: 0 }
.scene-kicker {
  color: var(--subtle);
  font: 650 .75rem/1.3 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.scene-phase {
  color: var(--text);
  font: 550 .8125rem/1.4 var(--mono);
  letter-spacing: -.01em;
}

.replay {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 var(--s2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: 600 .8125rem var(--sans);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.replay svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round }
.replay:hover { border-color: var(--pulse); color: var(--pulse) }
.replay:hover svg { animation: spin-once 620ms var(--ease) }
@keyframes spin-once { from { transform: rotate(0) } to { transform: rotate(-360deg) } }
.replay:disabled { cursor: default; opacity: .5 }
.replay:disabled:hover { border-color: var(--border); color: var(--text) }

.scene-status { display: flex; flex-wrap: wrap; gap: var(--s1); padding: var(--s3) var(--s3) 0 }
.status {
  flex: 1 1 200px;
  min-width: 0;
  padding: var(--s2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.status span, .status small {
  display: block;
  color: var(--subtle);
  font: 650 .6875rem/1.35 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.status strong { display: block; margin: var(--s0) 0; font: 650 .9375rem/1.3 var(--mono) }
.schema-status   { border-color: var(--edge-pass); background: var(--tint-pass) }
.schema-status strong { color: var(--pass-text) }
.semantic-status { border-color: var(--edge-fail); background: var(--tint-fail) }
.semantic-status strong { color: var(--fail-text) }

.graph-flow {
  display: grid;
  grid-template-columns: 1.08fr minmax(72px, .6fr) 1fr minmax(64px, .52fr) 1.14fr minmax(64px, .52fr) 1.06fr;
  align-items: center;
  padding: var(--s8) var(--s3) var(--s7);
}

.graph-node {
  position: relative;
  min-width: 0;
  padding: var(--s2);
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface-2);
  transition: border-color var(--t-mid) var(--ease), background var(--t-mid) var(--ease), transform var(--t-mid) var(--ease);
}
.graph-node strong, .graph-node small { display: block; overflow-wrap: anywhere }
.graph-node strong { font: 650 .8125rem/1.4 var(--mono); letter-spacing: -.01em }
.graph-node small { margin-top: 6px; color: var(--subtle); font-size: .6875rem; line-height: 1.4 }

.node-dot {
  display: block;
  width: 7px; height: 7px;
  margin-bottom: var(--s1);
  border-radius: 50%;
  background: var(--edge);
  transition: background var(--t-mid) var(--ease), box-shadow var(--t-mid) var(--ease);
}
.graph-node.producer .node-dot { background: var(--pulse); box-shadow: 0 0 0 4px var(--tint-pulse) }

.graph-node.direct   { border-color: var(--fail); background: var(--tint-fail) }
.graph-node.direct .node-dot { background: var(--fail); box-shadow: 0 0 0 4px var(--tint-fail) }
.graph-node.direct small { color: var(--fail-text) }
.graph-node.affected { border-color: var(--edge-fail); background: var(--tint-fail) }
.graph-node.affected .node-dot { background: var(--edge-fail) }
.graph-node.affected small { color: var(--fail-text); opacity: .9 }
.graph-node.terminal::after {
  content: "";
  position: absolute;
  top: var(--s2); right: var(--s2);
  width: 7px; height: 7px;
  border: 1.5px solid var(--edge-fail);
}

/* ---- edges -------------------------------------------------------- */

.graph-edge { position: relative; height: 44px }

.graph-edge .rail {
  position: absolute;
  top: 50%; left: 0;
  width: 100%; height: 2px;
  margin-top: -1px;
  border-radius: 2px;
  background: var(--edge);
}

/* One resolved-portion element per edge, scaled to however far meaning got. */
.graph-edge .rail-live {
  position: absolute;
  top: 50%; left: 0;
  width: 100%; height: 3px;
  margin-top: -1.5px;
  border-radius: 2px;
  background: var(--pulse);
  transform: scaleX(0);
  transform-origin: left center;
}
.first-edge .rail-live { transform: scaleX(var(--break-stop)) }

.graph-edge .pulse {
  position: absolute;
  top: 50%; left: 0;
  width: 11px; height: 11px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: var(--pulse);
  box-shadow: 0 0 0 4px var(--tint-pulse);
  opacity: 0;
  transform: translateX(calc(var(--edge-w, 120px) * var(--break-stop) - 5.5px));
}
.first-edge .pulse { opacity: 1 }

/* Trailing arc, so the pulse reads as travel and not a floating dot. */
.graph-edge .pulse::before {
  content: "";
  position: absolute;
  top: 4px; right: 6px;
  width: 34px; height: 3px;
  border-radius: 2px;
  background: linear-gradient(270deg, var(--pulse), transparent);
  opacity: 0;
}

.break-mark {
  position: absolute;
  top: 50%; left: 50%;
  width: 20px; height: 26px;
  margin: -13px 0 0 -4px;
}
.break-mark i {
  position: absolute;
  left: 0;
  width: 17px; height: 3px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.break-mark i:first-child { top: 3px }
.break-mark i:last-child  { top: 15px }

.edge-caption {
  position: absolute;
  top: -2px; left: 50%;
  color: var(--fail-text);
  font: 650 .6875rem var(--sans);
  letter-spacing: .09em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateX(-50%);
}

/* Blast radius: dashed, and clearly not successful propagation. Dashes come
   from a background image so one `background` override swaps edge state. */
.blast-edge .rail {
  height: 2px;
  border-radius: 0;
  background: repeating-linear-gradient(90deg, var(--edge-fail) 0 6px, transparent 6px 13px);
}

/* ---- witness ------------------------------------------------------ */

.scene-witness {
  margin: 0 var(--s3) var(--s3);
  overflow: hidden;
  border: 1px solid var(--edge-fail);
  border-left: 3px solid var(--fail);
  border-radius: var(--radius);
  background: var(--bg);
}
.witness-heading { padding: var(--s2) var(--s3) }
.witness-tag {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--fail-text);
  font: 650 .75rem/1.4 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.witness-tag i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--fail);
}
.witness-heading strong {
  display: block;
  margin-top: var(--s1);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -.012em;
}
.witness-heading strong code { color: var(--fail-text); font-size: .9375rem }

.witness-values {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  border-top: 1px solid var(--border);
  background: var(--border);
}
.witness-values > div { padding: var(--s2) var(--s3); background: var(--bg) }
.witness-values span {
  display: block;
  color: var(--subtle);
  font: 650 .6875rem/1.4 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.witness-values code { display: block; margin-top: 6px; font-size: .8125rem; line-height: 1.5 }
.witness-values code.ok  { color: var(--pass-text) }
.witness-values code.bad { color: var(--fail-text) }
.scene-witness > p {
  padding: var(--s2) var(--s3);
  border-top: 1px solid var(--border);
  color: var(--subtle);
  font-size: .75rem;
}
.scene-witness > p b { color: var(--muted); font-weight: 600 }

/* ---- replay timeline ----------------------------------------------
   Baseline: one pulse traverses every edge in turn, each resolving green
   behind it. Candidate: the same pulse leaves and never arrives. Trace:
   the blast propagates outward from the break, hop by hop.
   ------------------------------------------------------------------- */

.pulse-scene.is-playing .graph-node,
.pulse-scene.is-playing .scene-status,
.pulse-scene.is-playing .scene-witness,
.pulse-scene.is-playing .break-mark,
.pulse-scene.is-playing .edge-caption { opacity: 0 }
.pulse-scene.is-playing .graph-edge .pulse { opacity: 0 }

.pulse-scene.is-playing .graph-node { transform: translateY(6px) }
/* Colour has to stay in the transition list or the blast stagger below has
   nothing to delay, and every affected node lights at once, ahead of the
   edges that are supposed to be carrying the blast to it. */
.pulse-scene.is-playing .graph-node,
.pulse-scene.is-playing .scene-status {
  transition:
    opacity var(--t-mid) var(--ease),
    transform var(--t-mid) var(--ease),
    border-color var(--t-mid) var(--ease),
    background var(--t-mid) var(--ease);
  transition-delay: calc(var(--n, 0) * 70ms);
}
.pulse-scene.is-playing .graph-node small { transition: color var(--t-mid) var(--ease) }
.pulse-scene.is-playing.nodes-active .graph-node { opacity: 1; transform: none }

.pulse-scene.is-playing.baseline-active .scene-status,
.pulse-scene.is-playing.candidate-active .scene-status { opacity: 1 }
.pulse-scene.is-playing.baseline-active .semantic-status,
.pulse-scene.is-playing.candidate-active .semantic-status { visibility: hidden; opacity: 0 }

/* --- baseline: the pulse actually walks the graph --- */
.pulse-scene.is-playing.baseline-active .graph-edge .pulse {
  background: var(--pass);
  box-shadow: 0 0 0 4px var(--tint-pass);
  animation: hop-travel 380ms linear forwards;
  animation-delay: calc(var(--e, 0) * 380ms);
}
.pulse-scene.is-playing.baseline-active .graph-edge .pulse::before {
  background: linear-gradient(270deg, var(--pass), transparent);
  opacity: .8;
}
.pulse-scene.is-playing.baseline-active .graph-edge .rail-live {
  background: var(--pass);
  animation: rail-fill 380ms linear forwards;
  animation-delay: calc(var(--e, 0) * 380ms);
}
.pulse-scene.is-playing.baseline-active .blast-edge .rail { background: var(--edge) }

@keyframes hop-travel {
  from { opacity: 1; transform: translateX(-5.5px) }
  to   { opacity: 1; transform: translateX(calc(var(--edge-w, 120px) - 5.5px)) }
}
@keyframes rail-fill { from { transform: scaleX(0) } to { transform: scaleX(1) } }

/* Draining the baseline before the candidate runs. Without this the graph
   cuts from fully resolved to empty in one frame, which reads as a glitch
   rather than as a second run starting from a clean state. */
.pulse-scene.is-playing.baseline-active.resetting .graph-edge .rail-live {
  animation: rail-drain 300ms var(--ease-io) forwards;
  animation-delay: 0s;
}
.pulse-scene.is-playing.baseline-active.resetting .graph-edge .pulse {
  animation: pulse-out 200ms var(--ease) forwards;
  animation-delay: 0s;
}
@keyframes rail-drain { from { transform: scaleX(1); opacity: 1 } to { transform: scaleX(1); opacity: 0 } }
@keyframes pulse-out  { to { opacity: 0 } }

/* --- candidate: it leaves, and it does not arrive --- */
.pulse-scene.is-playing.candidate-active .first-edge .rail-live {
  background: var(--pulse);
  animation: rail-stop 900ms var(--ease-io) forwards;
}
.pulse-scene.is-playing.candidate-active .first-edge .pulse {
  animation: pulse-stop 900ms var(--ease-io) forwards;
}
.pulse-scene.is-playing.candidate-active .first-edge .pulse::before {
  opacity: .8;
  transition: opacity 200ms linear;
}
@keyframes pulse-stop {
  from { opacity: 1; transform: translateX(-5.5px) }
  to   { opacity: 1; transform: translateX(calc(var(--edge-w, 120px) * var(--break-stop) - 5.5px)) }
}
@keyframes rail-stop { from { transform: scaleX(0) } to { transform: scaleX(var(--break-stop)) } }

/* Nothing downstream may be asserted before the break is found. */
.pulse-scene.is-playing:not(.broken-active) .graph-node.direct,
.pulse-scene.is-playing:not(.impact-active) .graph-node.affected {
  border-color: var(--edge);
  background: var(--surface-2);
}
.pulse-scene.is-playing:not(.broken-active) .graph-node.direct .node-dot,
.pulse-scene.is-playing:not(.impact-active) .graph-node.affected .node-dot {
  background: var(--edge); box-shadow: none;
}
.pulse-scene.is-playing:not(.broken-active) .graph-node.direct small,
.pulse-scene.is-playing:not(.impact-active) .graph-node.affected small { color: var(--subtle) }
.pulse-scene.is-playing:not(.impact-active) .blast-edge .rail { background: var(--edge) }

/* --- break --- */
.pulse-scene.is-playing.broken-active .semantic-status { visibility: visible; opacity: 1 }
.pulse-scene.is-playing.broken-active .break-mark,
.pulse-scene.is-playing.broken-active .edge-caption {
  opacity: 1;
  transition: opacity var(--t-fast) var(--ease);
}
.pulse-scene.is-playing.broken-active .break-mark i { animation: cut-in 240ms var(--ease) backwards }
.pulse-scene.is-playing.broken-active .break-mark i:last-child { animation-delay: 60ms }
@keyframes cut-in {
  from { transform: rotate(42deg) scaleX(0) }
  to   { transform: rotate(42deg) scaleX(1) }
}
.pulse-scene.is-playing.broken-active .first-edge .pulse::before { opacity: 0 }

/* --- trace: the blast propagates hop by hop, it does not appear at once --- */
.pulse-scene.is-playing.impact-active .blast-edge .rail {
  animation: blast-in 300ms var(--ease) backwards;
  animation-delay: calc((var(--e, 1) - 1) * 190ms);
}
.pulse-scene.is-playing.impact-active .graph-node.affected,
.pulse-scene.is-playing.impact-active .graph-node.direct {
  transition-delay: calc((var(--n, 1) - 1) * 240ms);
}
.pulse-scene.is-playing.impact-active .graph-node.affected small,
.pulse-scene.is-playing.impact-active .graph-node.direct small {
  transition-delay: calc((var(--n, 1) - 1) * 240ms);
}
/* The blast arriving at a node is a discrete event, so the node marks it. */
.pulse-scene.is-playing.impact-active .graph-node.affected .node-dot,
.pulse-scene.is-playing.impact-active .graph-node.direct .node-dot {
  animation: blast-hit 420ms var(--ease) backwards;
  animation-delay: calc((var(--n, 1) - 1) * 240ms);
}
@keyframes blast-hit {
  0%   { box-shadow: 0 0 0 0 var(--tint-fail) }
  40%  { box-shadow: 0 0 0 7px var(--tint-fail) }
  100% { box-shadow: 0 0 0 4px var(--tint-fail) }
}
@keyframes blast-in {
  from { background: var(--edge) }
  to   { background: repeating-linear-gradient(90deg, var(--edge-fail) 0 6px, transparent 6px 13px) }
}

.pulse-scene.is-playing.witness-active .scene-witness {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}
.pulse-scene.is-playing:not(.witness-active) .scene-witness { transform: translateY(10px) }

/* ======================================================== playground === */

.playground { overflow: hidden }
.playground-toolbar {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  padding: var(--s2);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

/* Segmented control with a sliding thumb: state change, not decoration. */
.segmented {
  position: relative;
  display: flex;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
}
.playground-choice {
  position: relative;
  z-index: 1;
  min-height: 44px;
  padding: 0 var(--s2);
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font: 600 .8125rem var(--sans);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease);
}
.playground-choice.is-selected { color: var(--text) }
.segment-thumb {
  position: absolute;
  z-index: 0;
  top: 3px; left: 3px;
  height: calc(100% - 6px);
  border-radius: 7px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition: transform var(--t-mid) var(--ease), width var(--t-mid) var(--ease);
}
.playground-run { margin-left: auto }

.playground-graph {
  display: grid;
  grid-template-columns: minmax(180px, 1.2fr) minmax(120px, .72fr) minmax(180px, 1.1fr) 72px minmax(120px, .72fr) 72px minmax(108px, .64fr);
  align-items: center;
  gap: var(--s2);
  padding: var(--s5);
}
.playground-node {
  padding: var(--s3);
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface-2);
  transition: border-color var(--t-mid) var(--ease), background var(--t-mid) var(--ease);
}
.playground-node strong, .playground-node small { display: block }
.playground-node strong { font: 650 .875rem var(--mono); letter-spacing: -.01em }
.playground-node small { margin-top: 6px; color: var(--subtle); font-size: .75rem }
.playground-node-impact { padding: var(--s2) }
.playground-node-impact strong { overflow-wrap: anywhere; font-size: .75rem }
.playground-node-impact small { font-size: .6875rem; line-height: 1.45 }

/* The producer's recorded values and the consumer's contract, side by side.
   Switching the producer changes them, which is the whole point of the
   control: the schema never moves, one number does. */
.node-values {
  margin-top: var(--s2);
  padding-top: var(--s2);
  border-top: 1px solid var(--border);
}
.node-values > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  padding: 5px 0;
}
.node-values dt {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--subtle);
  font: .6875rem/1.4 var(--mono);
}
.node-values dd {
  flex: 0 0 auto;
  margin: 0;
  color: var(--text);
  font: 600 .75rem/1.4 var(--mono);
}
.node-values dd.is-breaking { color: var(--fail-text) }
.node-values dd.is-passing  { color: var(--pass-text) }
.playground-node[data-play-node="producer"] .node-dot { background: var(--pulse); box-shadow: 0 0 0 4px var(--tint-pulse) }
.playground.is-running.is-baseline .playground-node[data-play-node="consumer"] .node-dot { background: var(--pass); box-shadow: 0 0 0 4px var(--tint-pass) }
.playground.is-running.is-candidate .playground-node[data-play-node="consumer"] .node-dot { background: var(--fail); box-shadow: 0 0 0 4px var(--tint-fail) }
.playground.is-running.is-baseline .playground-node-impact .node-dot { background: var(--pass); box-shadow: 0 0 0 4px var(--tint-pass) }
.playground.is-running.is-candidate .playground-node-impact .node-dot { background: var(--fail); box-shadow: 0 0 0 4px var(--tint-fail) }

.playground-edge { position: relative; height: 44px }
.playground-edge .rail {
  position: absolute;
  top: 50%; left: 0;
  width: 100%; height: 2px;
  margin-top: -1px;
  border-radius: 2px;
  background: var(--edge);
  transition: background var(--t-mid) var(--ease);
}
.playground-edge .rail-live {
  position: absolute;
  top: 50%; left: 0;
  width: 100%; height: 3px;
  margin-top: -1.5px;
  border-radius: 2px;
  background: var(--pulse);
  transform: scaleX(0);
  transform-origin: left center;
}
.playground-edge small {
  position: absolute;
  left: 50%; top: -20px;
  color: var(--subtle);
  font: 650 .6875rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateX(-50%);
}
.playground-pulse {
  position: absolute;
  top: 50%; left: 0;
  width: 11px; height: 11px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: var(--pulse);
  box-shadow: 0 0 0 4px var(--tint-pulse);
  opacity: 0;
  transform: translateX(-5.5px);
}
.playground-break {
  position: absolute;
  top: 50%; left: 50%;
  width: 20px; height: 26px;
  margin: -13px 0 0 -4px;
  opacity: 0;
}
.playground-break i {
  position: absolute;
  left: 0;
  width: 17px; height: 3px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.playground-break i:first-child { top: 3px }
.playground-break i:last-child  { top: 15px }

.playground.is-running .playground-pulse { opacity: 1 }
.playground.is-running.is-baseline .playground-pulse {
  animation: play-travel-full 900ms var(--ease-io) forwards;
}
.playground.is-running.is-baseline .playground-edge .rail-live {
  background: var(--pass);
  animation: rail-resolve 900ms var(--ease-io) forwards;
}
.playground.is-running.is-baseline .playground-node:not([data-play-node="producer"]) { border-color: var(--pass); background: var(--tint-pass) }
.playground.is-running.is-baseline .playground-edge-impact .rail { background: var(--pass) }
.playground.is-running.is-candidate .playground-pulse {
  background: var(--fail);
  box-shadow: 0 0 0 4px var(--tint-fail);
  animation: play-travel-half 640ms var(--ease-io) forwards;
}
.playground.is-running.is-candidate .playground-edge .rail-live {
  animation: rail-half 640ms var(--ease-io) forwards;
}
.playground.is-running.is-candidate .playground-break {
  opacity: 1;
  transition: opacity var(--t-fast) var(--ease) 640ms;
}
.playground.is-running.is-candidate .playground-node:not([data-play-node="producer"]) { border-color: var(--edge-fail); background: var(--tint-fail) }
.playground.is-running.is-candidate .playground-edge-impact .rail {
  background: repeating-linear-gradient(90deg, var(--fail) 0 6px, transparent 6px 13px);
  opacity: .78;
  animation: impact-arrive var(--t-mid) var(--ease) backwards;
}
.playground.is-running.is-candidate .playground-edge-impact:nth-of-type(4) .rail { animation-delay: 720ms }
.playground.is-running.is-candidate .playground-edge-impact:nth-of-type(6) .rail { animation-delay: 880ms }
@keyframes impact-arrive { from { opacity: 0 } }

@keyframes play-travel-full {
  from { transform: translateX(-5.5px) }
  to   { transform: translateX(calc(var(--edge-w, 160px) - 5.5px)) }
}
@keyframes play-travel-half {
  from { transform: translateX(-5.5px) }
  to   { transform: translateX(calc(var(--edge-w, 160px) * var(--break-stop) - 5.5px)) }
}
@keyframes rail-resolve { from { transform: scaleX(0) } to { transform: scaleX(1) } }
@keyframes rail-half    { from { transform: scaleX(0) } to { transform: scaleX(var(--break-stop)) } }

.playground-result {
  display: flex;
  flex-direction: column;
  gap: var(--s0);
  min-height: 88px;
  padding: var(--s3) var(--s6);
  border-top: 1px solid var(--border);
  background: var(--bg);
  font-size: .9375rem;
}
.playground-result strong { font-weight: 600; letter-spacing: -.012em }
.playground-result strong.pass { color: var(--pass-text) }
.playground-result strong.fail { color: var(--fail-text) }
.playground-result span { color: var(--muted); font-size: .875rem }

.playground-witness {
  margin: 0 var(--s2) var(--s2);
  overflow: hidden;
  border: 1px solid var(--edge-fail);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: inset 4px 0 0 var(--fail);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--t-mid) var(--ease), transform var(--t-mid) var(--ease);
}
.playground-witness[hidden] { display: none }
.playground-witness.is-open { opacity: 1; transform: none }
.playground-witness > div { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border) }
.playground-witness > div > span { color: var(--fail-text); font: 650 .6875rem var(--mono); letter-spacing: .1em; text-transform: uppercase }
.playground-witness > div > strong { font-size: 1rem; font-weight: 600 }
.playground-witness dl { display: grid; grid-template-columns: repeat(4, 1fr); margin: 0 }
.playground-witness dl > div { min-width: 0; padding: var(--s2) var(--s3); border-right: 1px solid var(--border) }
.playground-witness dl > div:last-child { border-right: 0 }
.playground-witness dt { color: var(--subtle); font: 650 .6875rem var(--mono); letter-spacing: .08em; text-transform: uppercase }
.playground-witness dd { margin: var(--s1) 0 0; overflow-wrap: anywhere; color: var(--text); font-size: .8125rem }
.playground-witness dl > div:nth-child(1) dd { color: var(--pass-text) }
.playground-witness dl > div:nth-child(2) dd { color: var(--fail-text) }

/* ====================================================== bug section === */

.meaning-diff { display: grid; grid-template-columns: 1fr 96px 1fr; align-items: center }
.payload { overflow: hidden }
.payload-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--subtle);
  font: 650 .6875rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.badge { padding: 3px 7px; border: 1px solid currentColor; border-radius: 6px }
.badge.pass { color: var(--pass-text) }
.pass { color: var(--pass-text) }
.fail { color: var(--fail-text) }
.muted { color: var(--subtle) }

.payload pre, .terminal pre, .yaml {
  overflow: auto;
  background: var(--surface-code);
  font-size: .8125rem;
  line-height: 1.75;
  color: var(--code);
}
.payload pre { padding: var(--s3) }
.payload pre .k { color: var(--pulse) }
.payload pre .s { color: var(--pass-text) }
.payload pre .b, .payload pre .n { color: var(--unknown-text) }
.payload > p {
  display: flex;
  align-items: flex-start;
  gap: var(--s1);
  min-height: 72px;
  padding: var(--s2) var(--s3);
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: .8125rem;
  line-height: 1.55;
}
.flow-dot, .break-dot {
  flex: 0 0 auto;
  width: 7px; height: 7px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--pass);
}
.break-dot { background: var(--fail) }

.contract-cut { position: relative; display: grid; place-items: center; height: 3px }
.cut-rail {
  display: block;
  width: 100%; height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--pulse) 0 42%, transparent 42% 58%, var(--edge) 58%);
}
.contract-cut i {
  position: absolute;
  left: 46%;
  width: 20px; height: 3px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.contract-cut i:nth-of-type(1) { top: -9px }
.contract-cut i:nth-of-type(2) { top: 6px }

.diff-caption { margin-top: var(--s4); color: var(--muted); text-align: center }
.diff-caption strong { color: var(--text); font-weight: 600 }
.diff-caption code { color: var(--pulse); font-size: .9375rem }

/* ========================================================== method === */

.method-rail {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  padding: 0;
  overflow: hidden;
  list-style: none;
}
.method-rail li {
  position: relative;
  min-height: 200px;
  padding: var(--s3);
  border-right: 1px solid var(--border);
}
.method-rail li:last-child { border-right: 0 }
.method-rail li::before {
  content: "";
  position: absolute;
  top: 47px; left: 0; right: 0;
  height: 1.5px;
  background: var(--edge);
  opacity: .55;
}
.method-rail li:first-child::before { left: var(--s3) }
.method-rail li:last-child::before { right: calc(100% - var(--s3) - 28px) }
.method-rail span {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border: 1.5px solid var(--pulse);
  border-radius: 50%;
  background: var(--surface);
  color: var(--pulse);
  font: 650 .6875rem var(--mono);
}
.method-rail strong { display: block; margin-top: var(--s5); font-size: 1.0625rem; letter-spacing: -.018em }
.method-rail p { margin-top: var(--s1); color: var(--muted); font-size: .8125rem; line-height: 1.55 }
.method-rail .step-break span { border-color: var(--fail); color: var(--fail-text) }
/* The method rail is itself a graph edge, so step 03 has to actually cut it:
   the rail opens a gap and the canonical two-stroke mark sits in the gap. */
.method-rail .step-break::before {
  background: linear-gradient(90deg, var(--edge) 0 52%, transparent 52% 74%, var(--edge) 74%);
}
.rail-cut {
  position: absolute;
  top: 47px; left: 60%;
  width: 16px; height: 0;
}
.rail-cut b {
  position: absolute;
  left: 0;
  width: 15px; height: 2.5px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.rail-cut b:first-child { top: -6px }
.rail-cut b:last-child  { top: 4px }

/* ======================================================= contracts === */

.code-layout { display: grid; grid-template-columns: 1.6fr .8fr; overflow: hidden }
.code-pane { border-right: 1px solid var(--border); min-width: 0 }
.pane-bar {
  display: flex;
  align-items: center;
  gap: var(--s1);
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--subtle);
  font: 600 .75rem var(--mono);
}
.pane-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--pulse) }
.yaml { padding: var(--s4) var(--s3) }
.yaml .key    { color: var(--pulse) }
.yaml .string { color: var(--pass-text) }
.yaml .sev    { color: var(--fail-text) }
.yaml .bool, .yaml .num { color: var(--unknown-text) }

.evaluator-list { padding: var(--s4) var(--s3) }
.list-label {
  color: var(--subtle);
  font: 650 .75rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.evaluator-list ul { margin: var(--s3) 0; padding: 0; list-style: none }
.evaluator-list li {
  display: flex;
  gap: var(--s2);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--border);
  font-size: .875rem;
}
.evaluator-list li span { color: var(--subtle); font: .75rem var(--mono) }

/* Text link as a graph edge that completes on hover. */
.edge-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: 6px;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--pulse);
}
.edge-link svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--t-fast) var(--ease) }
.edge-link:hover svg { transform: translate(2px, -2px) }

/* ======================================================== terminal === */

.terminal { overflow: hidden }
.terminal-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.tl { width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong) }
.terminal-bar strong { margin-left: var(--s1); color: var(--subtle); font: 600 .75rem var(--mono) }
.terminal pre { padding: var(--s4) var(--s3) }

/* ===================================================== architecture ===
   Built from the same primitives as every other graph on the page rather
   than shipped as an image: theme-aware, selectable, and it reflows to a
   vertical topology instead of scaling its labels into illegibility.
   ====================================================================== */

.arch-frame { padding: var(--s6) var(--s5) var(--s5) }
.pane-label {
  color: var(--subtle);
  font: 650 .75rem var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
}

.pipeline {
  display: grid;
  grid-template-columns: 1fr minmax(40px, .55fr) 1fr minmax(40px, .55fr) 1fr minmax(40px, .55fr) 1fr minmax(40px, .55fr) 1fr;
  align-items: stretch;
  margin-top: var(--s6);
  padding: 0;
  list-style: none;
}
.stage {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: var(--s2);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  background: var(--surface-2);
}
.stage-tag {
  color: var(--subtle);
  font: 650 .75rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.stage strong { font-size: 1rem; font-weight: 600; letter-spacing: -.018em }
.stage small { color: var(--subtle); font-size: .75rem; line-height: 1.4 }
.stage-outside { border-style: dashed }
.stage-check   { border-color: var(--pulse) }
.stage-check .stage-tag { color: var(--pulse) }
.stage-trace   { border-color: var(--edge-fail) }
.stage-trace .stage-tag { color: var(--fail-text) }
.stage-explain { border-color: var(--edge-pass) }
.stage-explain .stage-tag { color: var(--pass-text) }

.stage-edge { position: relative; display: grid; place-items: center; grid-row: 1 }
.stage-edge .rail {
  width: 100%; height: 1.5px;
  border-radius: 2px;
  background: var(--edge);
}
/* Contract labels drop below the row: the edge columns are far too narrow
   to hold them without colliding with the stages either side. */
.stage-edge em {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  color: var(--subtle);
  font: .6875rem var(--mono);
  font-style: normal;
  white-space: nowrap;
  transform: translateX(-50%);
}
.stage { grid-row: 1 }

/* Brackets say exactly which stages sit either side of the trace boundary. */
.bracket {
  grid-row: 3;
  padding-top: var(--s1);
  border-top: 1px dashed var(--border-strong);
}
.bracket span {
  color: var(--subtle);
  font: 650 .6875rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.bracket-outside { grid-column: 1 }
.bracket-core { grid-column: 3 / -1 }
.bracket-core { border-top-color: var(--pulse); border-top-style: solid }
.bracket-core span { color: var(--pulse) }

.pipeline { row-gap: var(--s6) }
.arch-note { margin-top: var(--s5); color: var(--muted); font-size: .8125rem }

/* ========================================================== report === */

.report-split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2) }
.report-pane {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.report-pane .yaml { flex: 1 }
.pane-note { margin-left: auto; color: var(--subtle); font: .6875rem var(--mono) }

.report-mock { display: flex; flex-direction: column; flex: 1 }
.mock-verdict { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--border) }
.mock-verdict > div { padding: var(--s2) var(--s3); background: var(--surface) }
.mock-verdict span {
  display: block;
  color: var(--subtle);
  font: 650 .6875rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.mock-verdict strong { display: block; margin-top: 4px; font: 650 .9375rem var(--mono) }

.mock-row { padding: var(--s2) var(--s3); border-top: 1px solid var(--border) }
.mock-label {
  display: block;
  margin-bottom: 6px;
  color: var(--subtle);
  font: 650 .75rem var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.mock-row p { font-size: .8125rem; line-height: 1.6; color: var(--muted) }
.mock-row code { font-size: .75rem }
.mock-row code.ok { color: var(--pass-text) }
.mock-row code.bad { color: var(--fail-text) }
.mock-row b { color: var(--text); font-weight: 600 }

.mock-edge { display: flex; align-items: center; gap: var(--s1); font-family: var(--mono) }
.mock-edge i {
  position: relative;
  width: 34px; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--pulse) 0 40%, transparent 40% 60%, var(--edge) 60%);
}
.mock-edge i::before, .mock-edge i::after {
  content: "";
  position: absolute;
  left: 44%;
  width: 9px; height: 2px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.mock-edge i::before { top: -4px }
.mock-edge i::after  { top: 3px }

.mock-chips { display: flex; flex-wrap: wrap; gap: 6px }
.mock-chips em {
  padding: 3px 8px;
  border: 1px solid var(--edge-fail);
  border-radius: 6px;
  color: var(--fail-text);
  font: .6875rem var(--mono);
  font-style: normal;
}
.mock-repair { margin-top: auto; background: var(--tint-pulse) }

/* =========================================================== proof === */

.proof-section > .shell {
  display: grid;
  grid-template-columns: minmax(250px, .55fr) minmax(0, 1.45fr);
  gap: var(--s8);
}
.proof-intro h2 { max-width: 10ch }
.proof-intro > p:last-child { max-width: 34ch; margin-top: var(--s3); color: var(--muted) }
.proof-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 0;
  border-top: 1px solid var(--border-strong);
}
.proof-grid > div { min-width: 0; padding: var(--s4) var(--s3); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border) }
.proof-grid > div:nth-child(3n) { border-right: 0 }
.proof-grid dt { color: var(--subtle); font: 650 .6875rem var(--mono); letter-spacing: .1em; text-transform: uppercase }
.proof-grid dd { margin: var(--s2) 0 0 }
.proof-grid dd strong { display: block; overflow-wrap: anywhere; color: var(--text); font-size: clamp(1.4rem, 2.6vw, 2.25rem); font-weight: 620; letter-spacing: -.035em }
.proof-grid small { display: block; margin-top: var(--s1); color: var(--muted); font-size: .75rem }
.proof-note { grid-column: 2; color: var(--muted); font-size: .8125rem }
.proof-note a { color: var(--text); text-decoration: underline; text-decoration-color: var(--edge-pulse); text-underline-offset: 4px }

/* ===================================================== limitations === */

.limitations-section {
  margin-top: var(--s12);
  border-block: 1px solid var(--border);
  background: var(--bg-sunk);
}
.limitations-section > .shell {
  display: grid;
  grid-template-columns: minmax(260px, .7fr) minmax(0, 1.3fr);
  gap: var(--s8);
  padding-bottom: var(--s10);
}
.limitations-lead > span { color: var(--unknown-text); font: 650 .6875rem var(--mono); letter-spacing: .13em; text-transform: uppercase }
.limitations-lead h2 { max-width: 11ch; margin-top: var(--s3) }
.limitations-lead p { margin-top: var(--s3); color: var(--muted) }
.limitations-list { padding: 0; border-top: 1px solid var(--border-strong); list-style: none }
.limitations-list li { display: grid; grid-template-columns: 48px 1fr; gap: var(--s2); padding: var(--s3) 0; border-bottom: 1px solid var(--border) }
.limitations-list span { color: var(--unknown-text); font: .75rem var(--mono) }
.limitations-list p { max-width: 60ch; color: var(--text); font-size: 1rem }
.limitations-link { grid-column: 2; justify-self: start; display: inline-flex; gap: var(--s1); min-height: 44px; align-items: center; color: var(--muted); font-size: .875rem }
.limitations-link:hover { color: var(--text) }

/* ==================================================== contribution === */

.contribution-section > .shell {
  display: grid;
  grid-template-columns: minmax(260px, .62fr) minmax(0, 1.38fr);
  gap: var(--s8);
}
.contribution-lead h2 { max-width: 10ch }
.contribution-lead > p:last-child { max-width: 34ch; margin-top: var(--s3); color: var(--muted) }
.contribution-paths { border-top: 1px solid var(--border-strong) }
.contribution-paths a {
  position: relative;
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr) minmax(190px, .72fr);
  gap: var(--s3);
  align-items: center;
  min-height: 116px;
  padding: var(--s3) var(--s6) var(--s3) 0;
  border-bottom: 1px solid var(--border);
}
.contribution-paths a::after { content: "↗"; position: absolute; right: var(--s1); color: var(--subtle); transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease) }
.contribution-paths a:hover::after, .contribution-paths a:focus-visible::after { color: var(--pulse); transform: translate(2px, -2px) }
.contribution-paths span { color: var(--pulse); font: 650 .6875rem var(--mono); letter-spacing: .1em; text-transform: uppercase }
.contribution-paths strong { font-size: 1.125rem; font-weight: 600; line-height: 1.35 }
.contribution-paths small { color: var(--muted); font-size: .8125rem; line-height: 1.55 }
.contribution-footer { grid-column: 2; display: flex; flex-wrap: wrap; gap: var(--s4) }
.contribution-footer a { min-height: 44px; display: inline-flex; align-items: center; color: var(--muted); font-size: .875rem; text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 4px }
.contribution-footer a:hover { color: var(--text) }

/* ============================================================= cta === */

.final-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--s9) var(--s7);
  text-align: center;
  box-shadow: var(--shadow-lift);
}
.final-cta h2 { max-width: 16ch }
.final-cta .eyebrow { justify-content: center }
.cta-lede { max-width: 52ch; margin: var(--s3) 0 var(--s6) }
.final-cta .hero-actions { justify-content: center }
.cta-mark { position: relative; width: 160px; height: 3px; margin-bottom: var(--s6) }
.cta-rail {
  display: block;
  width: 100%; height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--pulse) 0 44%, transparent 44% 56%, var(--edge) 56%);
}
.cta-mark::before, .cta-mark::after {
  content: "";
  position: absolute;
  top: -3px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--pulse);
}
.cta-mark::before { left: -4px }
.cta-mark::after  { right: -4px; background: var(--edge) }
.cta-mark i {
  position: absolute;
  left: 46%;
  width: 20px; height: 3px;
  border-radius: 2px;
  background: var(--fail);
  transform: rotate(42deg);
  transform-origin: left center;
}
.cta-mark i:first-of-type { top: -8px }
.cta-mark i:last-of-type  { top: 7px }

/* =========================================================== modal === */

.setup-modal[hidden] { display: none }
.setup-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: var(--s3);
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(11, 15, 20, .5);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--t-mid) var(--ease);
}
.setup-modal.is-open .modal-backdrop { opacity: 1 }

/* Opening the dialog expands a subgraph: it grows from the edge outward. */
.setup-dialog {
  position: relative;
  width: min(720px, 100%);
  max-height: calc(100dvh - var(--s6));
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-modal);
  opacity: 0;
  transform: scale(.9);
  transition: opacity 260ms var(--ease), transform 380ms var(--ease);
}
.setup-modal.is-open .setup-dialog { opacity: 1; transform: none }

.setup-dialog-header {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s5) var(--s5) var(--s3);
}
.setup-dialog-header h2 { font-size: clamp(1.75rem, 3.6vw, 2.25rem) }
.setup-dialog-header p:not(.eyebrow) {
  max-width: 52ch;
  margin-top: var(--s2);
  color: var(--muted);
  font-size: .875rem;
  line-height: 1.6;
}
.modal-close {
  position: sticky;
  top: 0;
  flex: 0 0 44px;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.modal-close svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round }
.modal-close:hover { color: var(--text); border-color: var(--border-strong) }

.setup-tabs {
  position: relative;
  display: flex;
  gap: var(--s0);
  overflow-x: auto;
  padding: 0 var(--s5);
  border-bottom: 1px solid var(--border);
  scrollbar-width: none;
}
.setup-tabs::-webkit-scrollbar { display: none }
.setup-tab {
  min-height: 48px;
  padding: 0 var(--s2);
  border: 0;
  background: transparent;
  color: var(--muted);
  font: 600 .8125rem var(--sans);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease);
}
.setup-tab:hover, .setup-tab.is-active { color: var(--text) }
/* The active tab indicator is an edge that travels between tabs. */
.tab-rail {
  position: absolute;
  bottom: -1px; left: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--pulse);
  transition: transform var(--t-mid) var(--ease), width var(--t-mid) var(--ease);
}

.setup-panel { padding: var(--s5) var(--s5) var(--s4) }
.setup-panel[hidden] { display: none }
.setup-panel-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--s2) }
.setup-panel-meta strong { font-size: 1rem; font-weight: 600; letter-spacing: -.015em }
.setup-panel p { margin: var(--s2) 0 var(--s3); color: var(--muted); font-size: .875rem; line-height: 1.6 }
.support-badge {
  padding: 4px 8px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font: 650 .6875rem var(--mono);
  white-space: nowrap;
}
.support-badge.available { color: var(--pass-text) }
.support-badge.cli { color: var(--pulse) }
.support-badge.planned { color: var(--unknown-text) }

.command-line {
  display: flex;
  align-items: center;
  gap: var(--s1);
  padding: var(--s1) var(--s1) var(--s1) var(--s2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-code);
}
.command-line code {
  flex: 1;
  min-width: 0;
  overflow: auto;
  color: var(--code);
  font-size: .75rem;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.copy-button {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 var(--s2);
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: 600 .75rem var(--sans);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.copy-button:hover { border-color: var(--border-strong) }
.copy-button.copied { border-color: var(--edge-pass); color: var(--pass-text) }
.copy-feedback { display: block; min-height: 20px; margin-top: var(--s1); color: var(--pass-text); font: .6875rem var(--mono) }

body.modal-open { overflow: hidden }

/* ========================================================== footer === */

.site-footer { margin-top: var(--s11); border-top: 1px solid var(--border) }
.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 112px;
  color: var(--subtle);
  font-size: .8125rem;
}
.footer-brand { display: flex; align-items: center; gap: var(--s1) }
.footer-inner nav { display: flex; flex-wrap: wrap; gap: var(--s3) }
.footer-inner nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  transition: color var(--t-fast) var(--ease);
}
.footer-inner nav a:hover { color: var(--text) }

/* ====================================================== responsive === */

@media (max-width: 1080px) {
  :root { --gutter: var(--s5) }
  .section > .shell { padding-top: var(--s10) }
  .section > .shell::before { height: calc(var(--s10) - var(--s6) - 3px) }
  .method-rail { grid-template-columns: repeat(3, 1fr) }
  .method-rail li:nth-child(3) { border-right: 0 }
  .method-rail li:nth-child(-n+3) { border-bottom: 1px solid var(--border) }
  .method-rail li:last-child::before,
  .method-rail li:nth-child(3)::before { right: calc(100% - var(--s3) - 28px) }
  .method-rail li:nth-child(4)::before { left: var(--s3) }
  .code-layout { grid-template-columns: 1fr }
  .code-pane { border-right: 0; border-bottom: 1px solid var(--border) }
  .final-cta { padding: var(--s8) var(--s5) }
}

@media (max-width: 900px) {
  .nav-links a:not(.nav-github) { display: none }
  .hero { padding: var(--s8) 0 var(--s7) }
  .section-heading { flex-direction: column; align-items: flex-start; gap: var(--s3); margin-bottom: var(--s6) }
  .section-heading > p { flex: 1 1 auto }
  .bug-heading { grid-template-columns: 1fr }
  .bug-heading > p { margin-top: 0 }
  .terminal-section > .shell,
  .proof-section > .shell,
  .limitations-section > .shell,
  .contribution-section > .shell { grid-template-columns: 1fr; gap: var(--s6) }
  .terminal-section .section-heading { margin-top: 0 }
  .proof-note,
  .limitations-link,
  .contribution-footer { grid-column: 1 }
  .contribution-paths a { grid-template-columns: 92px minmax(0, 1fr) }
  .contribution-paths small { grid-column: 2 }
  .meaning-diff { grid-template-columns: 1fr; gap: var(--s6) }
  .contract-cut { width: 3px; height: 56px; margin-inline: auto }
  .cut-rail { width: 3px; height: 100%; background: linear-gradient(180deg, var(--pulse) 0 42%, transparent 42% 58%, var(--edge) 58%) }
  .contract-cut i { left: -9px; top: 42%; transform: rotate(-42deg) }
  .contract-cut i:nth-of-type(1) { top: 38% }
  .contract-cut i:nth-of-type(2) { top: 52% }
  .playground-graph { padding: var(--s7) var(--s4) }
  .playground-result { padding-inline: var(--s4) }

  /* The pipeline becomes a vertical topology rather than shrinking. */
  .arch-frame { padding: var(--s5) var(--s3) }
  .pipeline { grid-template-columns: 1fr; row-gap: 0; margin-top: var(--s4) }
  .stage, .stage-edge, .bracket { grid-row: auto; grid-column: 1 }
  .stage-edge { height: 48px }
  .stage-edge .rail { width: 1.5px; height: 100% }
  .stage-edge em {
    top: 50%; left: calc(50% + 14px);
    max-width: calc(50% - 20px);
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.35;
    transform: translateY(-50%);
  }
  /* Brackets become inline captions; a vertical stack has no row to span. */
  .bracket { padding: var(--s1) 0 var(--s3); border-top: 0 }
  .bracket-outside { order: -1; padding-top: 0 }
  .bracket-core { display: none }

  .report-split { grid-template-columns: 1fr }
}

/* ---- mobile is rethought, not compressed ---- */
@media (max-width: 700px) {
  :root { --gutter: var(--s3) }

  .nav { min-height: 64px }
  .nav-github { padding-inline: var(--s2) }

  .hero { padding: var(--s7) 0 var(--s6) }
  h1 { margin-bottom: var(--s3) }
  .hero-lede { margin-bottom: var(--s5) }
  .hero-actions { gap: var(--s1) }
  .hero-actions .button { flex: 1 1 140px }
  .install-line { margin-top: var(--s4) }
  /* Signal that the command runs past the edge instead of just clipping it. */
  .install-line code {
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent);
            mask-image: linear-gradient(90deg, #000 88%, transparent);
  }

  .section > .shell { padding-top: var(--s9) }
  .section > .shell::before { top: var(--s5); height: calc(var(--s9) - var(--s5) - 3px) }
  .section-heading { margin-bottom: var(--s5) }
  .section-heading > p { font-size: .9375rem }
  .bug-heading h2 { font-size: clamp(2.6rem, 14vw, 4.25rem) }
  .bug-heading > p { padding-left: var(--s2) }
  .proof-grid { grid-template-columns: 1fr 1fr }
  .proof-grid > div:nth-child(3n) { border-right: 1px solid var(--border) }
  .proof-grid > div:nth-child(2n) { border-right: 0 }
  .proof-grid > div { padding: var(--s3) var(--s2) }
  .proof-grid dd strong { font-size: 1.45rem }
  .limitations-list li { grid-template-columns: 36px 1fr }
  .contribution-paths a { grid-template-columns: 1fr; gap: var(--s1); padding-right: var(--s5) }
  .contribution-paths small { grid-column: 1 }
  .contribution-footer { gap: var(--s2) var(--s4) }

  .pulse-scene { margin-top: var(--s6); border-radius: var(--radius) }
  .scene-toolbar { flex-direction: column; align-items: stretch; gap: var(--s2); padding: var(--s2) }
  .replay { justify-content: center; width: 100% }
  .scene-status { padding: var(--s2) var(--s2) 0 }
  .status { flex: 1 1 120px; padding: var(--s1) var(--s2) }
  .status small { display: none }

  /* Vertical topology, built from the same primitives. No rotation hacks. */
  .graph-flow { grid-template-columns: 1fr; padding: var(--s4) var(--s2) var(--s5) }
  .graph-node { padding: var(--s2) }
  /* A vertical edge needs more length than a horizontal one: the cut is a
     fixed pixel height, so the pulse needs real distance to stop short of it. */
  .graph-edge { height: 88px; --break-stop: .28 }
  .graph-edge .rail {
    top: 0; left: 50%;
    width: 2px; height: 100%;
    margin: 0 0 0 -1px;
  }
  .first-edge .rail-live {
    top: 0; left: 50%;
    width: 3px; height: calc(var(--break-stop) * 100%);
    margin: 0 0 0 -1.5px;
    transform-origin: top center;
  }
  .blast-edge .rail {
    background: repeating-linear-gradient(180deg, var(--edge-fail) 0 6px, transparent 6px 13px);
  }
  .pulse-scene.is-playing:not(.impact-active) .blast-edge .rail { background: var(--edge) }
  .pulse-scene.is-playing.baseline-active .blast-edge .rail { background: var(--pass) }
  .pulse {
    top: 0; left: 50%;
    margin: -5.5px 0 0 -5.5px;
    transform: translateY(calc(var(--edge-h, 88px) * var(--break-stop)));
  }
  .pulse::before { display: none }
  .break-mark { top: 50%; left: 50%; margin: -9px 0 0 -8px }
  .break-mark i:first-child { top: 0 }
  .break-mark i:last-child { top: 12px }
  .edge-caption { top: calc(50% - 30px); left: calc(50% + 16px); transform: none }
  .pulse-scene.is-playing.candidate-active .pulse { animation-name: pulse-travel-v }
  @keyframes pulse-travel-v {
    from { transform: translateY(0) }
    to   { transform: translateY(calc(var(--edge-h, 88px) * var(--break-stop)) ) }
  }

  .scene-witness { margin: 0 var(--s2) var(--s2) }
  .witness-heading, .witness-values > div, .scene-witness > p { padding-inline: var(--s2) }
  .witness-heading strong { font-size: .9375rem }
  .witness-values { grid-template-columns: 1fr }

  .playground-toolbar { flex-direction: column; align-items: stretch; padding: var(--s2) }
  .segmented { width: 100% }
  .playground-choice { flex: 1 1 0; min-width: 0; padding-inline: var(--s1); font-size: .75rem }
  .playground-run { margin-left: 0; width: 100% }
  .playground-graph { grid-template-columns: 1fr; gap: var(--s2); padding: var(--s5) var(--s3) }
  .playground-node { padding: var(--s2) }
  .playground-edge { height: 96px; --break-stop: .30 }
  .playground-edge .rail { top: 0; left: 50%; width: 2px; height: 100%; margin: 0 0 0 -1px }
  .playground-edge .rail-live { top: 0; left: 50%; width: 3px; height: 100%; margin: 0 0 0 -1.5px; transform: scaleY(0); transform-origin: top center }
  .playground-edge small {
    top: 50%; left: calc(50% + 14px);
    max-width: calc(50% - 20px);
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.35;
    text-align: left;
    transform: translateY(-50%);
  }
  .playground-pulse { top: 0; left: 50%; margin: -5.5px 0 0 -5.5px; transform: translateY(0) }
  .playground-break { top: 50%; left: 50%; margin: -9px 0 0 -8px }
  .playground-break i:first-child { top: 0 }
  .playground-break i:last-child { top: 12px }
  .playground.is-running.is-baseline .playground-pulse { animation-name: play-travel-full-v }
  .playground.is-running.is-candidate .playground-pulse { animation-name: play-travel-half-v }
  .playground.is-running.is-baseline .playground-edge .rail-live { animation-name: rail-resolve-v }
  .playground.is-running.is-candidate .playground-edge .rail-live { animation-name: rail-half-v }
  .playground.is-running.is-candidate .playground-edge-impact .rail { background: repeating-linear-gradient(180deg, var(--fail) 0 6px, transparent 6px 13px) }
  @keyframes play-travel-full-v { from { transform: translateY(0) } to { transform: translateY(calc(var(--edge-h, 96px) - 11px)) } }
  @keyframes play-travel-half-v { from { transform: translateY(0) } to { transform: translateY(calc(var(--edge-h, 64px) * .46)) } }
  @keyframes rail-resolve-v { from { transform: scaleY(0) } to { transform: scaleY(1) } }
  @keyframes rail-half-v    { from { transform: scaleY(0) } to { transform: scaleY(var(--break-stop)) } }
  .playground-result { padding: var(--s3) }
  .playground-witness > div { padding: var(--s3) }
  .playground-witness dl { grid-template-columns: 1fr 1fr }
  .playground-witness dl > div { border-bottom: 1px solid var(--border) }
  .playground-witness dl > div:nth-child(2) { border-right: 0 }
  .playground-witness dl > div:nth-last-child(-n+2) { border-bottom: 0 }

  .method-rail { grid-template-columns: 1fr }
  .method-rail li { min-height: 0; border-right: 0; border-bottom: 1px solid var(--border) }
  .method-rail li:last-child { border-bottom: 0 }
  .method-rail li::before {
    top: var(--s3); bottom: calc(var(--s3) * -1); left: calc(var(--s3) + 12px) !important;
    right: auto !important;
    width: 1.5px; height: auto;
  }
  .method-rail li:last-child::before { display: none }
  .method-rail strong { margin-top: var(--s2) }
  .method-rail .step-break::before {
    background: linear-gradient(180deg, var(--edge) 0 30%, transparent 30% 58%, var(--edge) 58%);
  }
  .rail-cut { top: 68px; left: calc(var(--s3) + 12px) }
  .rail-cut b { transform: rotate(-42deg); left: -7px }
  .rail-cut b:first-child { top: 0 }
  .rail-cut b:last-child  { top: 10px }

  .yaml, .evaluator-list, .terminal pre { padding: var(--s3) var(--s2) }
  .yaml, .terminal pre, .payload pre { font-size: .75rem }
  .arch-frame { padding: var(--s2) }

  .final-cta { padding: var(--s6) var(--s3); border-radius: var(--radius) }
  .cta-mark { width: 120px }

  .setup-modal { align-items: flex-end; padding: 0 }
  .setup-dialog {
    width: 100%;
    max-height: 92dvh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
    transform: translateY(16px);
  }
  .setup-dialog-header { padding: var(--s4) var(--s3) var(--s2) }
  .setup-tabs { padding-inline: var(--s3) }
  .setup-panel { padding: var(--s3) }
  .command-line { flex-direction: column; align-items: stretch; padding: var(--s2) }
  .command-line .install-prompt { display: none }
  .copy-button { width: 100% }

  .footer-inner { flex-direction: column; align-items: flex-start; gap: var(--s3); padding: var(--s5) 0 }
}

@media (max-width: 360px) {
  .proof-grid { grid-template-columns: 1fr }
  .proof-grid > div,
  .proof-grid > div:nth-child(2n),
  .proof-grid > div:nth-child(3n) { border-right: 0 }
}

/* ================================================= reduced motion === */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  /* Every state the motion would have revealed is present without it. */
  .js .section > .shell::before { transform: scaleY(1) }
  .js .section .eyebrow i { transform: none; opacity: 1 }
  .pulse-scene.is-playing .graph-node,
  .pulse-scene.is-playing .scene-status,
  .pulse-scene.is-playing .scene-witness,
  .pulse-scene.is-playing .pulse,
  .pulse-scene.is-playing .break-mark,
  .pulse-scene.is-playing .edge-caption { opacity: 1; transform: none }
  .playground.is-running .playground-pulse { opacity: 1 }
  .playground.is-running .playground-edge .rail-live { transform: scaleX(1) }
  .playground.is-running.is-candidate .playground-edge .rail-live { transform: scaleX(var(--break-stop)) }
  .playground.is-running.is-candidate .playground-break {
    opacity: 1;
    transition: none !important;
  }
  .playground.is-running.is-candidate .playground-edge-impact .rail {
    opacity: .78;
    animation: none !important;
  }
  .button::after { display: none }
}

@media (max-width: 700px) and (prefers-reduced-motion: reduce) {
  .playground.is-running .playground-edge .rail-live { transform: scaleY(1) }
  .playground.is-running.is-candidate .playground-edge .rail-live {
    transform: scaleY(var(--break-stop));
  }
}
