/*
 * callsign landing · 1970s engineering-document register applied
 * within DESIGN.md's void-dark + signal-green palette. The page reads
 * as an infrastructure datasheet (numbered sections, annotated
 * figures, tabular endpoint references, live instrumentation) rather
 * than a marketing SaaS landing.
 *
 * Loaded into apps/landing/index.html, served by Cloudflare Pages.
 * Token system kept in sync with DESIGN.md.
 */

    :root {
      --void:           #06060B;
      --base:           #0C0C14;
      --surface:        #13131F;
      --text-primary:   #E8E7ED;
      --text-secondary: #8A8899;
      --text-tertiary:  #5C5A6A;
      --rule:           rgba(232, 231, 237, 0.10);
      --rule-strong:    rgba(232, 231, 237, 0.18);
      --accent:         #5BF0A5;
      --accent-dim:     rgba(91, 240, 165, 0.12);
    }

    *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

    html { color-scheme: dark; }

    body {
      background: var(--void);
      color: var(--text-primary);
      font-family: 'DM Sans', sans-serif;
      font-size: 14px;
      line-height: 1.6;
      min-height: 100vh;
      -webkit-font-smoothing: antialiased;
      text-rendering: optimizeLegibility;
    }
    /* Safety net against horizontal-scroll regressions from fixed-pixel
       margins or wide media. `clip` (not `hidden`) preserves
       position: sticky on .topnav by not creating a new scroll
       container. Chrome 90+, Safari 16+, Firefox 81+. */
    html, body { overflow-x: clip; }

    a { color: inherit; text-decoration: none; }

    /* ─── top nav ─── sticky header strip; mono / restrained. */
    .topnav {
      position: sticky;
      top: 0;
      z-index: 100;
      width: 100%;
      background: rgba(6, 6, 11, 0.78);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border-bottom: 1px solid var(--rule);
    }
    .topnav-inner {
      max-width: 880px;
      margin: 0 auto;
      padding: 14px 72px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 24px;
    }
    .topnav-brand {
      font-family: 'DM Mono', monospace;
      font-size: 13px;
      font-weight: 500;
      letter-spacing: 0.04em;
      color: var(--text-primary);
    }
    .topnav-dot { color: var(--accent); }
    .topnav-links {
      display: flex;
      align-items: center;
      gap: 24px;
    }
    .topnav-link {
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      color: var(--text-tertiary);
      letter-spacing: 0.16em;
      text-transform: uppercase;
      transition: color 0.15s ease;
    }
    .topnav-link:hover { color: var(--text-primary); }
    .topnav-link-strong { color: var(--text-secondary); font-weight: 500; }
    .topnav-link-strong:hover { color: var(--accent); }
    .topnav-cta {
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      font-weight: 500;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--accent);
      border: 1px solid var(--accent);
      padding: 7px 16px;
      transition: background 0.15s ease, color 0.15s ease;
    }
    .topnav-cta:hover {
      background: var(--accent);
      color: var(--void);
    }

    /* document container */
    .doc {
      max-width: 880px;
      margin: 0 auto;
      padding: 36px 72px 80px;
      position: relative;
    }

    /* ─── title block ─── */
    .title-block {
      display: grid;
      grid-template-columns: 1fr auto;
      align-items: end;
      gap: 32px;
      padding-bottom: 28px;
      margin-bottom: 64px;
      position: relative;
      /* border now drawn by .rule-bottom::after so it can plot-on-load */
    }
    .brand {
      font-family: 'DM Sans', sans-serif;
      font-size: 32px;
      font-weight: 700;
      letter-spacing: -0.04em;
      line-height: 1;
    }
    .brand-dot { color: var(--accent); }
    .subtitle {
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      margin-top: 10px;
    }

    .meta {
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      color: var(--text-tertiary);
      letter-spacing: 0.08em;
      text-align: right;
      line-height: 1.9;
      text-transform: uppercase;
    }
    .meta dt { display: inline; }
    .meta dd { display: inline; color: var(--text-secondary); margin-left: 8px; }
    .meta .row { display: block; }

    /* ─── section ─── */
    section.spec {
      margin-bottom: 64px;
      position: relative;
    }

    /* §01 PROTOCOL becomes the prototype's hero moment: tall, dramatic,
       with the signal canvas running at production intensity behind it.
       Engineering-document register holds (numbered section, hairline
       rule, technical prose) but the section reads as a hero. */
    section.spec.spec-hero {
      min-height: 64vh;
      padding: 8px 0 48px;
      margin-bottom: 64px;
      margin-left: -72px;
      margin-right: -72px;
      padding-left: 72px;
      padding-right: 72px;
      overflow: hidden;
      isolation: isolate;
    }
    section.spec.spec-hero > * { position: relative; z-index: 1; }
    section.spec.spec-hero .section-num { left: 0; }
    .spec-canvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      opacity: 0.95;
      pointer-events: none;
      z-index: 0;
    }

    /* Top-line indicator strip: [LIVE] dot + instrumentation readouts.
       Single horizontal row above the hero title. Mono, restrained. */
    .hero-strip {
      display: flex;
      align-items: center;
      gap: 24px;
      padding-top: 8px;
      margin-bottom: 36px;
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      letter-spacing: 0.18em;
      text-transform: uppercase;
      color: var(--text-tertiary);
      flex-wrap: wrap;
    }
    .hero-live {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      color: var(--accent);
      font-weight: 500;
    }
    .hero-live-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 8px var(--accent);
      animation: live-pulse 2s ease-in-out infinite;
    }
    .hero-stat {
      display: inline-flex;
      align-items: baseline;
      gap: 8px;
    }
    .hero-stat-label { color: var(--text-tertiary); }
    .hero-stat-value {
      color: var(--text-primary);
      font-variant-numeric: tabular-nums;
      font-weight: 500;
      letter-spacing: 0.08em;
      min-width: 2.5ch;
      display: inline-block;
      text-align: right;
    }

    /* Hero typewriter title. Big DM Sans on a single line; clamp sized
       so "agent information exchange." (27 chars) fits inside the doc's
       content width without wrapping at any viewport. */
    .hero-title {
      font-family: 'DM Sans', sans-serif;
      font-size: clamp(22px, 3.6vw, 42px);
      font-weight: 600;
      line-height: 1.1;
      letter-spacing: -0.035em;
      color: var(--text-primary);
      /* Internal hero rhythm: strip → title 32px (down from 48), title → p
         18px (down from 24). Combined with p { margin-bottom: 14px } below,
         the stepping reads as a 32→18→14 ratio decrement instead of the
         prior 48→24→14 stutter. */
      margin: 32px 0 18px;
      white-space: nowrap;
    }
    .hero-title .accent { color: var(--accent); }
    .hero-title .typed { white-space: pre; }

    /* TextScramble — in-flight noise glyphs render in accent, resolved
       characters inherit the parent color (text-primary). Layout-safe:
       width never changes during decode because every glyph occupies
       one mono cell (.hero-title is sans, but glyphs are inline spans
       so the host's metrics dominate). Reduced-motion paints final
       text in primary color so noise glyphs never show. */
    .scramble {
      color: var(--accent);
      opacity: 0.92;
    }
    @media (prefers-reduced-motion: reduce) {
      .scramble { color: inherit; opacity: 1; }
    }

    section.spec.spec-hero p {
      max-width: 64ch;
      font-size: 15px;
      line-height: 1.7;
      color: var(--text-secondary);
      opacity: 0;
      transform: translateY(4px);
      transition: opacity 600ms cubic-bezier(0.22, 1, 0.36, 1),
                  transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
    }
    section.spec.spec-hero.typed-done p { opacity: 1; transform: none; }
    section.spec.spec-hero.typed-done p:nth-of-type(2) { transition-delay: 120ms; }
    section.spec.spec-hero p:first-of-type {
      font-size: 16px;
      color: var(--text-primary);
    }

    /* Hero stat strip animates in slightly after the typewriter starts */
    .hero-strip {
      opacity: 0;
      transition: opacity 500ms ease-out;
    }
    body.loaded .hero-strip { opacity: 1; }
    .section-num {
      position: absolute;
      left: -72px;
      top: 0;
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      color: var(--accent);
      letter-spacing: 0.16em;
      font-weight: 500;
      text-transform: uppercase;
      padding-top: 2px;
    }
    .section-head {
      font-family: 'DM Sans', sans-serif;
      font-size: 13px;
      font-weight: 600;
      color: var(--text-primary);
      letter-spacing: 0.18em;
      text-transform: uppercase;
      padding-bottom: 12px;
      margin-bottom: 18px;
      border-bottom: 1px solid var(--rule);
    }

    /* ─── body prose ─── */
    section.spec p {
      max-width: 64ch;
      color: var(--text-secondary);
      margin-bottom: 14px;
    }
    section.spec a.inline {
      color: var(--accent);
      transition: opacity 0.15s ease;
    }
    section.spec a.inline:hover { opacity: 0.75; }

    code, .mono {
      font-family: 'DM Mono', monospace;
    }
    p code, td code {
      font-size: 0.92em;
      color: var(--text-primary);
      background: var(--base);
      padding: 1px 6px;
      border: 1px solid var(--rule);
      /* no border-radius — crisp drafting-board edges */
    }

    /* ─── figure block ─── */
    figure {
      margin: 32px 0 16px;
      padding: 28px 0 8px;
      border-top: 1px solid var(--rule);
      border-bottom: 1px solid var(--rule);
    }
    figcaption {
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      color: var(--text-tertiary);
      letter-spacing: 0.06em;
      text-align: center;
      padding: 16px 16px 4px;
      line-height: 1.7;
    }
    figcaption .fig-num {
      color: var(--accent);
      margin-right: 10px;
      letter-spacing: 0.14em;
    }
    figcaption .legend { display: block; margin-top: 8px; color: var(--text-secondary); }
    figcaption .legend strong {
      color: var(--accent);
      font-weight: 500;
      margin-right: 4px;
    }
    figcaption .legend span + strong { margin-left: 14px; }

    /* ─── fig. 1 — topology schematic ─── */
    .topology { width: 100%; height: auto; display: block; max-width: 720px; margin: 0 auto; }
    .topology .frame { fill: none; stroke: var(--rule-strong); stroke-width: 1; }
    .topology .frame-event {
      stroke: var(--accent);
      stroke-width: 1.25;
    }
    .topology .frame-event-bg {
      fill: var(--accent-dim);
      stroke: none;
    }
    .topology .label {
      fill: var(--text-primary);
      font-family: 'DM Sans', sans-serif;
      font-size: 12px;
      font-weight: 500;
    }
    .topology .label-accent { fill: var(--accent); }
    .topology .label-mono {
      fill: var(--text-secondary);
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      letter-spacing: 0.04em;
    }
    .topology .callout-line {
      stroke: var(--accent);
      stroke-width: 0.5;
      stroke-dasharray: 2 2;
      fill: none;
    }
    .topology .callout-marker {
      fill: var(--void);
      stroke: var(--accent);
      stroke-width: 1;
    }
    .topology .callout-letter {
      fill: var(--accent);
      font-family: 'DM Mono', monospace;
      font-size: 8px;
      font-weight: 500;
      letter-spacing: 0.08em;
    }
    .topology .dimension {
      stroke: var(--text-tertiary);
      stroke-width: 0.5;
      fill: none;
    }
    .topology .dimension-label {
      fill: var(--text-tertiary);
      font-family: 'DM Mono', monospace;
      font-size: 8px;
      letter-spacing: 0.14em;
    }
    .topology .connector {
      stroke: var(--rule-strong);
      stroke-width: 1;
      fill: none;
    }
    .topology .connector-active {
      stroke: var(--accent);
      stroke-width: 1.25;
      fill: none;
    }

    /* ─── spec tables ─── */
    .spec-table {
      width: 100%;
      border-collapse: collapse;
      font-size: 13px;
      margin: 8px 0 8px;
    }
    .spec-table th, .spec-table td {
      padding: 12px 14px;
      text-align: left;
      border-bottom: 1px solid var(--rule);
      vertical-align: top;
    }
    .spec-table th {
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      font-weight: 500;
      border-bottom: 1px solid var(--rule-strong);
      padding-top: 0;
    }
    .spec-table td.mono {
      font-family: 'DM Mono', monospace;
      font-size: 12px;
      color: var(--text-primary);
    }
    .spec-table td.dim {
      color: var(--text-tertiary);
      font-family: 'DM Mono', monospace;
      font-size: 11px;
    }
    .spec-table .col-num {
      width: 38px;
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.1em;
    }
    .spec-table .method {
      width: 64px;
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      font-weight: 500;
      color: var(--text-primary);
      letter-spacing: 0.06em;
    }
    .spec-table sup {
      color: var(--accent);
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      margin-left: 2px;
    }

    /* ─── footnotes ─── */
    .footnotes {
      list-style: none;
      counter-reset: footnote;
      font-size: 12px;
      color: var(--text-tertiary);
      margin-top: 28px;
      padding-top: 16px;
      border-top: 1px dashed var(--rule);
      max-width: 64ch;
    }
    .footnotes li {
      counter-increment: footnote;
      padding-left: 24px;
      position: relative;
      margin-bottom: 8px;
      line-height: 1.55;
    }
    .footnotes li::before {
      content: counter(footnote) ".";
      position: absolute;
      left: 0;
      color: var(--accent);
      font-family: 'DM Mono', monospace;
      font-size: 10px;
    }
    .footnotes code {
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      color: var(--text-secondary);
      background: transparent;
      border: 0;
      padding: 0;
    }

    /* ─── code figures ─── */
    .code-fig { margin: 28px 0; }
    .code-fig pre {
      background: var(--base);
      border: 1px solid var(--rule);
      padding: 18px 20px;
      font-family: 'DM Mono', monospace;
      font-size: 12px;
      line-height: 1.7;
      color: var(--text-secondary);
      overflow-x: auto;
      white-space: pre;
    }
    .code-fig-caption {
      font-family: 'DM Mono', monospace;
      font-size: 10px;
      color: var(--text-tertiary);
      letter-spacing: 0.06em;
      margin-bottom: 10px;
      display: flex;
      align-items: baseline;
      gap: 14px;
    }
    .code-fig-caption .num {
      color: var(--accent);
      letter-spacing: 0.14em;
    }
    .code-fig-caption .label { flex: 1; }
    .code-copy {
      background: transparent;
      border: 1px solid var(--rule-strong);
      color: var(--text-tertiary);
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      letter-spacing: 0.16em;
      text-transform: uppercase;
      padding: 4px 11px;
      cursor: pointer;
      transition: color 0.15s, border-color 0.15s, background 0.15s;
    }
    .code-copy:hover {
      color: var(--text-primary);
      border-color: var(--text-secondary);
    }
    .code-copy.done {
      color: var(--accent);
      border-color: var(--accent);
      background: var(--accent-dim);
    }

    /* ─── network state · live table ─── */
    .live-status {
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      margin: 16px 0 8px;
      display: flex;
      align-items: center;
      gap: 10px;
    }
    .live-status-dot {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 8px var(--accent);
      animation: live-pulse 2s ease-in-out infinite;
    }
    @keyframes live-pulse {
      0%, 100% { opacity: 1; transform: scale(1); }
      50%      { opacity: 0.4; transform: scale(0.85); }
    }
    .live-table {
      width: 100%;
      border-collapse: collapse;
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      margin-top: 4px;
    }
    .live-table th, .live-table td {
      padding: 9px 14px;
      text-align: left;
      border-bottom: 1px solid var(--rule);
    }
    .live-table th {
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      font-weight: 500;
      border-bottom: 1px solid var(--rule-strong);
      padding-top: 0;
    }
    .live-table .live-slug { color: var(--accent); }
    /* Slug cell wraps in an <a> for injected real events (the JS in
       index.html builds rows with anchor tags pointing at
       console.callsign.sh/channels/{slug}/{topic}). Inherits the
       accent color from the parent; hover lifts it from 100% to 75%
       opacity for a quiet affordance. Static fallback rows have no
       anchor and read as plain text. */
    .live-table .live-slug a {
      color: inherit;
      text-decoration: none;
      transition: opacity 0.15s ease;
    }
    .live-table .live-slug a:hover { opacity: 0.75; }
    .live-table .live-payload {
      color: var(--text-secondary);
      max-width: 320px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .live-table .live-time {
      color: var(--text-tertiary);
      font-size: 10px;
      letter-spacing: 0.04em;
      white-space: nowrap;
    }

    /* ─── CTA stamp ─── */
    .cta-stamp {
      margin-top: 56px;
      padding-top: 24px;
      border-top: 1px solid var(--rule-strong);
      text-align: center;
    }
    .cta-stamp-link {
      display: inline-block;
      font-family: 'DM Mono', monospace;
      font-size: 13px;
      font-weight: 500;
      letter-spacing: 0.22em;
      color: var(--accent);
      padding: 14px 32px;
      border: 1px solid var(--accent);
      transition: background 0.15s ease, color 0.15s ease;
    }
    .cta-stamp-link:hover {
      background: var(--accent);
      color: var(--void);
    }
    .cta-stamp-rev {
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      margin-top: 14px;
    }
    /* Secondary wayfinding under the primary CTA. Quieter than the
       bordered stamp so it reads as the lower-commitment path:
       "browse before you create." Lowercase to match register prose,
       accent on hover. */
    .cta-stamp-secondary {
      margin-top: 18px;
      font-family: 'DM Mono', monospace;
      font-size: 11px;
      letter-spacing: 0.14em;
      color: var(--text-tertiary);
    }
    .cta-stamp-secondary a {
      color: var(--text-secondary);
      transition: color 0.15s ease;
    }
    .cta-stamp-secondary a:hover {
      color: var(--accent);
    }

    /* ─── document footer (bibliography style) ─── */
    .doc-foot {
      margin-top: 64px;
      padding-top: 16px;
      border-top: 1px solid var(--rule);
      font-family: 'DM Mono', monospace;
      font-size: 9px;
      color: var(--text-tertiary);
      letter-spacing: 0.14em;
      text-transform: uppercase;
      display: flex;
      flex-wrap: wrap;
      gap: 18px;
      justify-content: space-between;
      align-items: baseline;
    }
    .doc-foot nav {
      display: flex;
      gap: 18px;
      flex-wrap: wrap;
    }
    .doc-foot nav a { color: var(--text-tertiary); transition: color 0.15s ease; }
    .doc-foot nav a:hover { color: var(--text-primary); }

    /* ─── fixed gutter marks (page-edge measure) ─── */
    .gutter {
      position: fixed;
      left: 16px;
      top: 0;
      bottom: 0;
      width: 32px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 80px 0;
      font-family: 'DM Mono', monospace;
      font-size: 8px;
      color: var(--text-tertiary);
      letter-spacing: 0.16em;
      pointer-events: none;
      opacity: 0.55;
      text-align: center;
    }
    .gutter span::before {
      content: "";
      display: inline-block;
      width: 8px;
      height: 1px;
      background: var(--text-tertiary);
      vertical-align: middle;
      margin-right: 6px;
    }

    /* ─── motion: rule-draw on viewport entry ──────────────────────────
       Hairline rules grow from left → right when scrolled into view.
       Page feels like it's being printed as you read. Applied via a
       ::after pseudo-element so the host element's existing border can
       be replaced by an animated 1px stroke without affecting layout. */
    .rule-bottom, .rule-top, .rule-strong-bottom {
      position: relative;
      /* host elements override their original border to width 0 */
    }
    .rule-bottom { border-bottom: 0 !important; padding-bottom: 14px; }
    .rule-top    { border-top: 0 !important; padding-top: 28px; }
    .rule-strong-bottom { border-bottom: 0 !important; }

    .rule-bottom::after,
    .rule-top::after,
    .rule-strong-bottom::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      height: 1px;
      background: var(--rule);
      transform: scaleX(0);
      transform-origin: left;
      transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1);
    }
    .rule-bottom::after        { bottom: 0; }
    .rule-top::after           { top: 0; }
    .rule-strong-bottom::after { bottom: 0; background: var(--rule-strong); }
    .rule-top.rule-strong::after,
    .rule-bottom.rule-strong::after { background: var(--rule-strong); }
    .rule-bottom.drawn::after,
    .rule-top.drawn::after,
    .rule-strong-bottom.drawn::after { transform: scaleX(1); }

    /* ─── motion: plotter-draw FIG. 1 ─────────────────────────────────
       Initial state hides every stroke and fades every fill. On first
       viewport entry the page adds .plotted, which staggers:
         Stage 1 (0 → 600ms):  frame rects line-draw
         Stage 2 (550 → 950):  connectors line-draw
         Stage 3 (900 → 1500): callouts (lines + markers + letters)
       Total ~1.5s, fires once, never replays. */
    .topology line,
    .topology rect:not(.frame-event-bg),
    .topology path {
      stroke-dasharray: 1000;
      stroke-dashoffset: 1000;
      transition: stroke-dashoffset 600ms cubic-bezier(0.22, 1, 0.36, 1);
    }
    .topology .frame-event-bg,
    .topology text,
    .topology .callout-marker {
      opacity: 0;
      transition: opacity 400ms ease-out;
    }

    /* Stage 1 — frame rects */
    .plotted .topology rect:not(.frame-event-bg) { stroke-dashoffset: 0; }
    /* Stage 2 — connectors (lines without callout-line / dimension class) */
    .plotted .topology .connector,
    .plotted .topology .connector-active {
      stroke-dashoffset: 0;
      transition-delay: 550ms;
    }
    /* Stage 3 — callout lines + dimension */
    .plotted .topology .callout-line,
    .plotted .topology .dimension line {
      stroke-dashoffset: 0;
      transition-delay: 900ms;
    }
    /* Stage 1 fills/text appear with rects */
    .plotted .topology .frame-event-bg { opacity: 1; transition-delay: 300ms; }
    .plotted .topology .label,
    .plotted .topology .label-mono,
    .plotted .topology .label-accent { opacity: 1; transition-delay: 350ms; }
    /* Stage 3 callout text + markers */
    .plotted .topology .callout-marker,
    .plotted .topology .callout-letter,
    .plotted .topology .dimension-label {
      opacity: 1;
      transition-delay: 1100ms;
    }

    /* ─── motion: traveling pulses ─────────────────────────────────────
       SMIL <animateMotion> drives the visuals; the CSS here only sets
       fill and an ambient drop-shadow so the dot reads as signal. */
    .topology .pulse {
      fill: var(--accent);
      filter: drop-shadow(0 0 4px rgba(91, 240, 165, 0.85));
    }
    .topology .pulse-path { fill: none; stroke: none; }

    /* ─── motion: live ticker row fade-in ──────────────────────────────
       Tagged with .row-new on first render; the class auto-clears after
       the fade so subsequent diffs work. */
    .live-table tr.row-new td {
      animation: row-fade-in 600ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
    }
    .live-table tr.row-new:nth-child(2) td { animation-delay: 40ms; }
    .live-table tr.row-new:nth-child(3) td { animation-delay: 80ms; }
    .live-table tr.row-new:nth-child(4) td { animation-delay: 120ms; }
    .live-table tr.row-new:nth-child(5) td { animation-delay: 160ms; }
    .live-table tr.row-new:nth-child(6) td { animation-delay: 200ms; }
    @keyframes row-fade-in {
      from { opacity: 0; transform: translateY(-2px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* ─── motion: gutter marks tick in on load ─────────────────────────
       Sequential top → bottom on first paint. */
    .gutter span {
      opacity: 0;
      transform: translateX(-4px);
      transition: opacity 300ms ease-out, transform 300ms ease-out;
    }
    body.loaded .gutter span                  { opacity: 1; transform: none; }
    body.loaded .gutter span:nth-child(1)     { transition-delay: 100ms; }
    body.loaded .gutter span:nth-child(2)     { transition-delay: 200ms; }
    body.loaded .gutter span:nth-child(3)     { transition-delay: 300ms; }
    body.loaded .gutter span:nth-child(4)     { transition-delay: 400ms; }
    body.loaded .gutter span:nth-child(5)     { transition-delay: 500ms; }

    /* ─── reduced motion: every animated layer goes static instantly ─── */
    @media (prefers-reduced-motion: reduce) {
      .rule-bottom::after,
      .rule-top::after,
      .rule-strong-bottom::after { transform: scaleX(1); transition: none; }
      .topology line,
      .topology rect:not(.frame-event-bg),
      .topology path,
      .topology .frame-event-bg,
      .topology text,
      .topology .callout-marker {
        stroke-dashoffset: 0 !important;
        opacity: 1 !important;
        transition: none !important;
      }
      .topology .pulse,
      .topology animateMotion { display: none; }
      .gutter span { opacity: 1; transform: none; transition: none; }
      .live-table tr.row-new td { animation: none; }
      .live-status-dot { animation: none; }
    }

    /* ─── focus visible ─── */
    a:focus-visible, button:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 3px;
    }

    /* ─── responsive ─── */
    @media (max-width: 900px) {
      .gutter { display: none; }
      .doc { padding: 32px 24px 64px; }
      .section-num {
        position: static;
        display: block;
        margin-bottom: 8px;
      }
      .title-block {
        grid-template-columns: 1fr;
        gap: 18px;
      }
      .meta { text-align: left; }
      .brand { font-size: 28px; }
      /* Hero was full-bleed at desktop via -72px margins + 72px padding;
         at narrow widths those negative margins push past the viewport
         and cause horizontal scroll. Match the .doc's 24px gutter
         instead. */
      section.spec.spec-hero {
        margin-left: 0;
        margin-right: 0;
        padding-left: 24px;
        padding-right: 24px;
      }
      /* Topnav previously held 72px horizontal padding at every width;
         pull it in line with .doc so brand + links + CTA fit a 375px
         viewport without overflow. */
      .topnav-inner { padding: 14px 24px; }
    }
    @media (max-width: 520px) {
      .doc { padding: 24px 18px 48px; }
      .code-fig-caption { flex-wrap: wrap; gap: 8px; }
      .live-table { font-size: 10px; }
      .live-table th, .live-table td { padding: 7px 8px; }
      .live-table .live-payload { max-width: 160px; }
      section.spec.spec-hero {
        padding-left: 18px;
        padding-right: 18px;
      }
      .topnav-inner { padding: 14px 18px; }
    }
