/* ================================================================
   keyframe-storyboard (kfsb) — WS-Render-1a
   Ported verbatim from design/keyframe-storyboard-system/keyframe-reference.html
   with that file's standalone page rules (body, body > footer) removed.
   Every token aliases a real egtry site variable from assets/css/main.css
   (--bg, --bg-code, --bg-soft, --text, --text-light, --border, --primary,
   --accent), all eight of which were verified to exist with these exact
   fallback values. The component is fully static: no animation, no state.
   ================================================================ */
/* ================================================================
     kfsb — keyframe storyboard component
     Tokens alias egtry site variables (assets/css/main.css) with the
     site's literal values as fallbacks. Dark values are a PROPOSED
     extension (the site is light-only today) — validated pair.
     ================================================================ */
  :is(.code-example, .kfsb) {
    --kfsb-page:    var(--bg, #ffffff);
    --kfsb-card:    var(--bg, #ffffff);
    --kfsb-code-bg: var(--bg-code, #f3f4f6);
    --kfsb-soft:    var(--bg-soft, #f6f7f9);
    --kfsb-ink:     var(--text, #222831);
    --kfsb-ink-2:   var(--text-light, #616161);
    --kfsb-muted:   #5f6670;
    --kfsb-hair:    var(--border, #d9dee7);
    --kfsb-edge:    #b6c0cf;
    --kfsb-write:   var(--primary, #245ea8);
    --kfsb-read:    var(--accent, #b25c2b);
    --kfsb-sans:    system-ui, -apple-system, sans-serif;
    --kfsb-mono:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) :is(.code-example, .kfsb) {
      --kfsb-page:    #131519;
      --kfsb-card:    #1b1e24;
      --kfsb-code-bg: #22262d;
      --kfsb-soft:    #1b1e24;
      --kfsb-ink:     #e8eaed;
      --kfsb-ink-2:   #b3bac4;
      --kfsb-muted:   #8b93a0;
      --kfsb-hair:    #2e333b;
      --kfsb-edge:    #454c58;
      --kfsb-write:   #4a89dc;
      --kfsb-read:    #cc7a44;
    }
  }
  :root[data-theme="dark"] :is(.code-example, .kfsb) {
    --kfsb-page:    #131519;
    --kfsb-card:    #1b1e24;
    --kfsb-code-bg: #22262d;
    --kfsb-soft:    #1b1e24;
    --kfsb-ink:     #e8eaed;
    --kfsb-ink-2:   #b3bac4;
    --kfsb-muted:   #8b93a0;
    --kfsb-hair:    #2e333b;
    --kfsb-edge:    #454c58;
    --kfsb-write:   #4a89dc;
    --kfsb-read:    #cc7a44;
  }
  .kfsb {
    color: var(--kfsb-ink);
    font-family: var(--kfsb-sans);
  }

  /* The legend (.kfsb-legend/.kfsb-swatch) was removed in the step-by-step redesign:
     it repeated once per source variant, and the write/read distinction it explained is
     already carried without colour by the `→` on a write chip. */

  /* ---------- full source (shown once per storyboard) ---------- */
  .kfsb-source {
    background: var(--kfsb-card);
    border: 1px solid var(--kfsb-hair);
    border-radius: 12px;
    padding: 1rem 1.25rem;
    overflow-x: auto;
    margin: 0 0 1.5rem;
  }
  .kfsb-source pre { margin: 0; font-family: var(--kfsb-mono); font-size: 0.85rem; line-height: 1.6; color: var(--kfsb-ink); }

  /* ---------- rail ---------- */
  .kfsb-frames { list-style: none; margin: 0; padding: 0; position: relative; }
  .kfsb-frames::before {
    content: "";
    position: absolute; left: 15px; top: 8px; bottom: 8px;
    width: 2px; background: var(--kfsb-hair); border-radius: 1px;
  }
  .kfsb-frame { position: relative; padding: 0 0 2.25rem 3.25rem; }
  .kfsb-frame:last-child { padding-bottom: 0; }
  .kfsb-dot {
    position: absolute; left: 0; top: 0;
    width: 32px; height: 32px; border-radius: 50%;
    background: var(--kfsb-card);
    border: 2px solid var(--kfsb-edge);
    color: var(--kfsb-ink-2);
    font-size: 0.85rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
  }
  /* call depth: content indents, dot stays on the rail */
  .kfsb-frame[data-depth="2"] > :not(.kfsb-dot) { margin-left: 1.5rem; }
  .kfsb-frame[data-depth="3"] > :not(.kfsb-dot) { margin-left: 3rem; }

  .kfsb-frame > header { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
  .kfsb-title { font-size: 1.05rem; font-weight: 700; margin: 0.2rem 0 0.1rem; }
  .kfsb-tag {
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.03em;
    color: var(--kfsb-ink-2);
    background: var(--kfsb-card);
    border: 1px solid var(--kfsb-hair);
    border-radius: 999px;
    padding: 0.05rem 0.6rem;
  }
  /* .kfsb-kind ("KIND: SETUP") and .kfsb-instruction ("Reads `i` (0), …") are no longer
     emitted — the first named this renderer's own taxonomy, the second restated the
     chips spliced into the code window directly below it. */
  .kfsb-frame > header { margin-bottom: 0.55rem; }

  .kfsb-card {
    background: var(--kfsb-card);
    border: 1px solid var(--kfsb-hair);
    border-radius: 12px;
    padding: 1rem 1.1rem;
  }
  .kfsb-frame--quiet .kfsb-card { padding: 0.75rem 1.1rem 0.9rem; }

  /* ---------- code window ---------- */
  .kfsb-code {
    background: var(--kfsb-code-bg);
    border: 1px solid var(--kfsb-hair);
    border-radius: 10px;
    padding: 0.6rem 0;
    overflow-x: auto;
    margin: 0;
  }
  .kfsb-code pre {
    margin: 0;
    background: var(--kfsb-code-bg);
    color: var(--kfsb-ink);
    font-family: var(--kfsb-mono);
    font-size: 0.82rem;
    line-height: 1.85;
  }
  .kfsb-ln {
    display: block;
    padding: 0 1rem 0 0.6rem;
    color: var(--kfsb-muted);
    border-left: 3px solid transparent;
    white-space: pre;
  }
  .kfsb-ln--on {
    color: var(--kfsb-ink);
    border-left-color: var(--kfsb-edge);
    background: color-mix(in srgb, var(--kfsb-ink) 4%, transparent);
  }
  .kfsb-no {
    display: inline-block;
    width: 2ch; margin-right: 1.25ch;
    color: var(--kfsb-muted);
    text-align: right;
    font-size: 0.85em;
  }
  .kfsb-ell { display: block; padding: 0 1rem 0 0.6rem; color: var(--kfsb-muted); letter-spacing: 0.2em; }

  /* ---------- inline hotspots ---------- */
  .kfsb-tok { border-radius: 5px; padding: 0 2px; }
  .kfsb-tok--r { background: color-mix(in srgb, var(--kfsb-read) 16%, transparent); box-shadow: inset 0 -1.5px 0 var(--kfsb-read); }
  .kfsb-tok--w { background: color-mix(in srgb, var(--kfsb-write) 16%, transparent); box-shadow: inset 0 -1.5px 0 var(--kfsb-write); }
  .kfsb-chip {
    display: inline-block;
    font: 700 0.68em/1.6 var(--kfsb-sans);
    padding: 0 0.45em; margin-left: 3px;
    border-radius: 999px; border: 1px solid;
    transform: translateY(-0.15em);
    white-space: nowrap;
  }
  .kfsb-chip--r { color: var(--kfsb-read); border-color: color-mix(in srgb, var(--kfsb-read) 45%, transparent); background: var(--kfsb-card); }
  .kfsb-chip--w { color: var(--kfsb-write); border-color: color-mix(in srgb, var(--kfsb-write) 45%, transparent); background: var(--kfsb-card); }
  .kfsb-chip--verdict { color: var(--kfsb-ink); border-color: var(--kfsb-edge); background: var(--kfsb-card); }

  /* ---------- state strip ---------- */
  .kfsb-state { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.5rem 0.75rem; margin-top: 0.9rem; }
  .kfsb-state-lbl {
    flex-basis: 100%;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--kfsb-muted);
  }
  .kfsb-tile { text-align: center; font-family: var(--kfsb-mono); }
  .kfsb-tile .v {
    display: block; min-width: 44px;
    border: 1.5px solid var(--kfsb-hair);
    border-radius: 7px;
    padding: 0.28rem 0.55rem;
    font-size: 0.85rem; font-weight: 600;
    color: var(--kfsb-ink);
    background: var(--kfsb-code-bg);
  }
  .kfsb-tile .n { display: block; font-size: 0.68rem; color: var(--kfsb-muted); margin-top: 0.25rem; }
  .kfsb-tile--w .v { border-color: var(--kfsb-write); background: color-mix(in srgb, var(--kfsb-write) 12%, var(--kfsb-card)); }
  .kfsb-tile--r .v { border-color: var(--kfsb-read); background: color-mix(in srgb, var(--kfsb-read) 12%, var(--kfsb-card)); }
  .kfsb-tile .arr { color: var(--kfsb-ink-2); font-weight: 400; }
  .kfsb-cells { display: flex; gap: 4px; }
  .kfsb-cells .kfsb-tile .v { min-width: 40px; padding: 0.28rem 0; }

  /* ---------- stdout ----------
     One <pre> per step holding every line that step printed. It used to be one <p> per
     LINE, each with its own border and its own "OUTPUT" label; java's arrays_util prints
     55 lines from a single statement and rendered them as 55 stacked panels. */
  .kfsb-stdout {
    margin: 0.9rem 0 0;
    font-family: var(--kfsb-mono);
    font-size: 0.8rem;
    line-height: 1.65;
    color: var(--kfsb-ink-2);
    background: var(--kfsb-code-bg);
    border: 1px solid var(--kfsb-hair);
    border-left: 3px solid var(--kfsb-edge);
    border-radius: 8px;
    padding: 0.5rem 0.75rem;
    white-space: pre-wrap;
    overflow-x: auto;
  }
  .kfsb-stdout .lbl {
    display: block;
    font-family: var(--kfsb-sans);
    font-size: 0.68rem; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--kfsb-muted);
    margin-bottom: 0.3rem;
  }

  /* ---------- ledger (grouped passes / unwinds) ---------- */
  .kfsb-ledger-wrap { margin-top: 1.1rem; }
  .kfsb-ledger-wrap > .lbl {
    display: block;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--kfsb-muted);
    margin-bottom: 0.4rem;
  }
  /* Sized to its contents, not to the card. A four-column table stretched to 100% put
     `i`, `nums[i]` and `x` 250px apart, so reading one pass meant three saccades. */
  .kfsb-ledger {
    width: auto; min-width: min(100%, 22rem); max-width: 100%;
    border-collapse: collapse; font-size: 0.85rem;
  }
  .kfsb-ledger caption {
    caption-side: top; text-align: left;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em;
    text-transform: uppercase; color: var(--kfsb-muted);
    padding-bottom: 0.4rem;
  }
  .kfsb-ledger th {
    text-align: left;
    font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--kfsb-muted);
    padding: 0.35rem 0.75rem;
    border-bottom: 1px solid var(--kfsb-edge);
  }
  /* A column header is a variable NAME. Uppercasing it rewrote the program: the `nums[i]`
     column read `NUMS[I]`, which is not an identifier in any of these languages. */
  .kfsb-ledger th code {
    text-transform: none; letter-spacing: 0;
    font-family: var(--kfsb-mono); font-size: 0.95em;
  }
  .kfsb-ledger td {
    font-family: var(--kfsb-mono);
    font-variant-numeric: tabular-nums;
    color: var(--kfsb-ink-2);
    padding: 0.4rem 0.75rem;
    border-bottom: 1px solid var(--kfsb-hair);
  }
  /* The pass number is a row header, not a column header: it inherited the uppercase,
     muted, thick-ruled <th> styling and drew a heavy line the width of the column under
     every digit. */
  .kfsb-ledger tbody th {
    text-transform: none; letter-spacing: 0;
    font-family: var(--kfsb-mono); font-variant-numeric: tabular-nums;
    font-size: 0.85rem; font-weight: 600;
    color: var(--kfsb-ink-2);
    padding: 0.4rem 0.75rem;
    border-bottom: 1px solid var(--kfsb-hair);
  }
  .kfsb-ledger td.emph { color: var(--kfsb-ink); font-weight: 600; }
  .kfsb-ledger td .arr { color: var(--kfsb-muted); }
  .kfsb-ledger tr:last-child td, .kfsb-ledger tr:last-child th { border-bottom: none; }
  /* The elided middle of a long loop — see LEDGER_MAX_ROWS. */
  .kfsb-ledger-gap td {
    text-align: center; letter-spacing: 0.12em;
    font-family: var(--kfsb-sans); font-size: 0.75rem;
    color: var(--kfsb-muted);
  }

  /* ---------- diagram-state (diagramkit SVG) ---------- */
  .kfsb-dgm { margin: 0; }
  .kfsb-dgm svg { display: block; width: 100%; max-width: 368px; height: auto; margin: 0 auto; }
  .kfsb-dgm figcaption { text-align: center; font-size: 0.8rem; color: var(--kfsb-muted); margin-top: 0.75rem; }
  .kfsb-dgm .kfsb-edge-line { stroke: var(--kfsb-edge); stroke-width: 1.5; }
  .kfsb-dgm .kfsb-node rect { fill: var(--kfsb-card); stroke: var(--kfsb-hair); stroke-width: 1.5; }
  .kfsb-dgm .kfsb-node--a rect { stroke: var(--kfsb-write); stroke-width: 2; fill: color-mix(in srgb, var(--kfsb-write) 14%, var(--kfsb-card)); }
  .kfsb-dgm .kfsb-node--b rect { stroke: var(--kfsb-read); stroke-width: 2; fill: color-mix(in srgb, var(--kfsb-read) 14%, var(--kfsb-card)); }
  .kfsb-dgm .kfsb-val { font: 600 15px var(--kfsb-sans); fill: var(--kfsb-ink); }
  .kfsb-dgm .kfsb-sub { font: 700 10.5px var(--kfsb-sans); fill: var(--kfsb-muted); letter-spacing: 0.03em; }
  .kfsb-dgm .kfsb-node--a .kfsb-sub { fill: var(--kfsb-write); }
  .kfsb-dgm .kfsb-node--b .kfsb-sub { fill: var(--kfsb-read); }

  @media (max-width: 480px) {
    .kfsb-frame { padding-left: 2.6rem; }
    .kfsb-frame[data-depth="2"] > :not(.kfsb-dot) { margin-left: 0.75rem; }
    .kfsb-frame[data-depth="3"] > :not(.kfsb-dot) { margin-left: 1.5rem; }
    .kfsb-ledger th, .kfsb-ledger td { padding-inline: 0.4rem; }
  }
