
  /* A timeline reads on white paper; the things people posted are black boxes.
     That split is the whole visual system here: prose, names, numbers and
     hairlines live on paper — and every board a rule runs on (the canvases, the
     card deck, the circuit widgets, even the 44px avatars, which are all Life
     patterns) is the same near-black the simulations paint themselves. */
  :root {
    color-scheme: light;
    --paper: #fff;     /* stays pure white — a warm paper was tried and rejected */
    --ink: #0f1419;
    --ink-2: #536471;
    --ink-3: #8b98a5;
    --line: #eff3f4;   /* dividers between posts */
    --line-2: #cfd9de; /* outlines you are meant to see */
    --blue: #1d9bf0;
    --board: #111a2c;
    --cell: #f7e9c6;   /* DOM stand-ins for a live cell — matches COL_CELL_HEX */
    --cell-glow: 247,233,198;  /* the black the engines paint on — never drifts from COL_BG */
  }
  /* Two languages live side by side in this one file; <html lang> picks one.
     Only the losing side is ever touched, so nothing here can fight a layout
     rule the way `display: revert` would. */
  html[lang="en"] [data-lang]:not([data-lang="en"]),
  html[lang="zh-CN"] [data-lang]:not([data-lang="zh"]) { display: none; }
  /* ---- the chrome ---------------------------------------------------------
     Top left: the way out. It never moves — that habit is older than this page.
     Top right: the two things a reader opens on purpose, contents and language.
     Left margin (wide screens only): the spine — not a menu but a picture of the
     document, its four blocks cut to the real scroll heights of the opening and
     the three chapters, the lit one filling as you read. A phone has no margin,
     so there it is a 3px rule at the top edge and the contents live behind the
     corner button instead. Every jump is instant: a 24-screen page sliding past
     you is a reason to feel sick, not a flourish. */
  .back-home {
    position: fixed; top: 14px; left: 14px; z-index: 80;
    font-size: 12.5px; color: var(--ink-2); text-decoration: none; white-space: nowrap;
    background: rgba(255,255,255,.86); border: 1px solid var(--line-2);
    border-radius: 999px; padding: 7px 13px;
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  }
  .back-home:hover { color: var(--ink); border-color: var(--blue); }

  .corner { position: fixed; top: 14px; right: 14px; z-index: 80; display: flex; gap: 7px; }
  .corner-btn, .lang-switch > summary {
    display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px;
    border: 1px solid var(--line-2); border-radius: 999px;
    background: rgba(255,255,255,.86); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    color: var(--ink-2); font: inherit; font-size: 12.5px; cursor: pointer; list-style: none;
  }
  .lang-switch > summary::-webkit-details-marker { display: none; }
  .corner-btn:hover, .lang-switch > summary:hover { color: var(--ink); border-color: var(--blue); }
  .corner-btn[aria-expanded="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
  .lang-switch { position: relative; }
  .lang-switch > summary { width: 32px; padding: 0; justify-content: center; }
  .lang-menu { position: absolute; top: calc(100% + 7px); right: 0; min-width: 118px;
    display: grid; gap: 2px; padding: 6px; background: var(--paper);
    border: 1px solid var(--line-2); border-radius: 12px;
    box-shadow: 0 12px 26px rgba(15,20,25,.13); }
  .lang-switch:not([open]) .lang-menu { display: none; }   /* say it, don't rely on containment */
  .lang-menu a { display: block; padding: 7px 11px; border-radius: 8px;
    color: var(--ink-2); text-decoration: none; font-size: 12.5px; white-space: nowrap; }
  .lang-menu a:hover { background: var(--line); color: var(--ink); }

  /* ---- the contents sheet (phones) ---- */
  .toc { position: fixed; inset: 0; z-index: 70; overflow-y: auto;
    background: var(--paper); padding: 60px 18px 44px; -webkit-overflow-scrolling: touch; }
  .toc-ch { display: block; width: 100%; margin: 20px 0 6px; padding: 0; border: 0;
    background: none; text-align: left; cursor: pointer;
    display: flex; align-items: baseline; gap: 9px; }
  .toc-ch:first-child { margin-top: 0; }
  .toc-ch .n { flex: none; display: grid; place-items: center; min-width: 26px; height: 21px;
    border-radius: 6px; background: var(--line); color: var(--ink-2);
    font: 700 10.5px/1 ui-monospace, SFMono-Regular, Menlo, monospace; }
  .toc-ch .n .px-num { height: 11px; }
  .toc-ch .t { color: var(--ink); font-size: 16px; font-weight: 700; line-height: 1.35; }
  .toc-ch.on .n { background: var(--ink); color: #fff; }
  .toc ol { list-style: none; margin: 0 0 4px; padding: 0 0 0 33px; }
  .toc ol button { display: block; width: 100%; padding: 8px 0; border: 0; background: none;
    color: var(--ink-2); font: inherit; font-size: 13px; line-height: 1.45; text-align: left;
    cursor: pointer; border-top: 1px solid var(--line); }
  .toc ol li:first-child button { border-top: 0; }
  .toc ol li.on button { color: var(--ink); font-weight: 700; }
  .toc ol li.on button::before { content: "▸ "; color: var(--blue); }

  /* ---- the spine ---- */
  .spine { position: fixed; z-index: 60; display: flex; font-size: 12px; }
  .spine-track { display: flex; list-style: none; }
  .spine-track li { position: relative; }
  .spine-seg { position: relative; display: block; width: 100%; height: 100%; padding: 0;
    border: 0; background: var(--line-2); cursor: pointer; overflow: hidden; transition: background .15s; }
  .spine-seg::after { content: ""; position: absolute; inset: 0; background: var(--ink);
    transform-origin: 0 0; }
  .spine-seg:hover { background: var(--ink-3); }
  .spine-list { display: none; margin: 0; padding: 0; list-style: none; }
  .spine.open .spine-list { display: block; }
  .spine-list button { display: block; width: 100%; padding: 5px 0; border: 0; background: none;
    color: var(--ink-2); font: inherit; font-size: 11.5px; line-height: 1.5; cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .spine-list button:hover { color: var(--blue); }
  .spine-list li.on button { color: var(--ink); font-weight: 700; }
  .spine-list li.on button::before { content: "▸ "; color: var(--blue); }

  @media (min-width: 1160px) {
    .corner-btn, .toc { display: none; }        /* the margin already shows all of it */
    .spine { top: 50%; left: calc(50% - 310px - 52px); transform: translateY(-50%);
      flex-direction: column; align-items: flex-start; gap: 14px; width: 9px; }
    .spine-track { flex-direction: column; gap: 5px; height: min(56vh, 400px); width: 9px; }
    .spine-track li { width: 9px; }
    .spine-seg { border-radius: 5px; }
    .spine-seg::after { transform: scaleY(var(--fill, 0)); }
    .spine-name { position: absolute; right: 21px; top: 50%; transform: translateY(-50%);
      width: 190px; display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
      background: none; border: 0; padding: 0; cursor: pointer; text-align: right; }
    .spine-name .n { font: 700 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
      color: var(--ink-3); letter-spacing: .06em; }
    .spine-name .t { color: var(--ink-3); font-size: 12.5px; line-height: 1.35; transition: color .15s; }
    .spine-name:hover .t, .spine-name:hover .n { color: var(--blue); }
    .spine-track li.on .spine-name .n { color: #fff; background: var(--ink);
      border-radius: 5px; padding: 4px 6px; }
    .spine-name .n .px-num { height: 11px; }
    .spine-track li.on .spine-name .t { color: var(--ink); font-weight: 700; font-size: 14px; }
    .spine-track li.lead .spine-name { display: none; }
    .spine-panel { display: none; }
    .spine-list { position: absolute; right: 21px; top: var(--listTop, 50%);
      transform: translateY(-50%); width: 210px; max-height: 62vh; overflow-y: auto;
      background: var(--paper); border: 1px solid var(--line-2); border-radius: 12px;
      box-shadow: 0 14px 34px rgba(15,20,25,.13); padding: 10px 13px; text-align: right; }
    .spine.open .spine-name { visibility: hidden; }
    .spine.open .spine-track li.on .spine-name { visibility: visible; }
  }
  @media (max-width: 1159px) {
    /* Nothing of the spine shows on a phone: the banner runs to the top edge and
       the three controls float on it. The contents live behind the corner button. */
    .spine { display: none; }
    /* The column is full width here, so the fixed corner pills sit on the text —
       they kept landing on the "open in the lab / copy link" row under each post.
       While the reader scrolls down they get out of the way; a scroll up brings
       them back (2026-09-07). */
    .back-home, .corner { transition: transform .22s ease, opacity .22s ease; }
    body.chrome-hide .back-home, body.chrome-hide .corner {
      transform: translateY(-64px); opacity: 0; pointer-events: none; }
  }
  /* While the black banner is still under them the controls are white on it; once
     it has scrolled past they go back to ink on paper. A fixed control has to
     survive both grounds, so it owns two looks rather than one compromise. */
  .over-dark .back-home,
  .over-dark .corner-btn,
  .over-dark .lang-switch > summary {
    background: color-mix(in srgb, var(--board) 62%, transparent);
    border-color: rgba(255,255,255,.44); color: #fff;
  }
  .over-dark .back-home:hover,
  .over-dark .corner-btn:hover,
  .over-dark .lang-switch > summary:hover { border-color: #fff; color: #fff; }
  .over-dark .corner-btn[aria-expanded="true"] {
    background: #fff; border-color: #fff; color: var(--ink); }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto !important; } }  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    background: var(--paper); color: var(--ink);
    font-family: system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
    text-autospace: normal;
  }

  /* ---- the feed shell: one column, hairline rails, like any profile ---- */
  .feed { max-width: 620px; margin: 0 auto; border-inline: 1px solid var(--line); min-height: 100vh; }

  /* ---- the profile block: whose account this is ----
     The header image is a board like every other board on the page, so it is
     mounted the same way (a .post-media the banner Station paints into) and
     only loses the rounded corners. */
  .pf-banner .post-media { margin-top: 0; border-radius: 0; }
  /* the same hairline that separates every two posts, so the profile reads as the
     first card in the stack instead of something floating above it */
  header.profile { border-bottom: 1px solid var(--line); }
  .pf-body { padding: 0 16px 14px; }
  /* the avatar rides up over the banner, and the banner's media box is
     positioned — so this row has to be positioned too, or it paints underneath */
  .pf-row { position: relative; z-index: 2;
    display: flex; align-items: flex-end; justify-content: space-between;
    margin-top: -38px; margin-bottom: 10px; }
  /* .avatar is declared further down, so this one has to out-specify it rather
     than out-order it */
  .avatar.pf-avatar { width: 82px; height: 82px; border: 4px solid var(--paper); }
  .avatar.pf-avatar svg { width: 62%; height: 62%; }
  /* No display name under the avatar: the banner already spells the subject in
     cells, and this account has no biography to sign. The heading still has to
     exist for the outline and for screen readers, so it carries the words the
     banner draws — as text, off screen. */
  .pf-title { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
  .pf-bio { font-size: 14.5px; line-height: 1.7; color: var(--ink); margin-top: 2px; }
  .pf-meta { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 11px;
    font-size: 13.5px; color: var(--ink-2); }
  .pf-meta span { display: inline-flex; align-items: center; gap: 5px; }
  .pf-meta svg { width: 16px; height: 16px; flex: none; stroke: currentColor; fill: none;
    stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  .pf-meta a { color: var(--blue); text-decoration: none; }
  .pf-meta a:hover { text-decoration: underline; }
  /* No follower counts, no follow button, no tab row: nobody can follow this
     account, nobody counted those numbers, and three of the four tabs would go
     nowhere. What is left is what is true — a name, a bio, a link. */


  /* Chapter three uses the same timeline columns, never a viewport breakout. */
  .exhibit-controls, .exhibit-controls-inner { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
  .exhibit-controls-inner { margin-top: 0; }
  .exhibit-controls button { min-height: 34px; padding: 5px 11px; border: 1px solid var(--line-2); border-radius: 16px; background: var(--paper); color: var(--ink-2); font: inherit; font-size: 12px; cursor: pointer; }
  .exhibit-controls button:hover { color: var(--ink); border-color: var(--ink-3); }
  .exhibit-controls button:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
  .exhibit-caption { margin-top: 8px; color: var(--ink-2); font-size: 13px; line-height: 1.65; }
  .exhibit-details { margin-top: 10px; color: var(--ink-3); font-size: 12px; line-height: 1.65; }
  .exhibit-details summary { cursor: pointer; width: fit-content; }
  .exhibit-details[open] > div { margin-top: 8px; }
  .exhibit-details .post-text { font-size: 13px; color: var(--ink-2); }
  .exhibit-details a { color: var(--blue); }
  .local-media canvas { touch-action: none; cursor: crosshair; }
  #elementary canvas { cursor: default; }
  .exhibit-controls button[aria-pressed="true"] { color: var(--ink); background: #e6f5f0; border-color: #70ac99; }
  .exhibit-status { min-height: 1.65em; font-variant-numeric: tabular-nums; }

  /* ---- one post ---- */
  section.post {
    position: relative; padding: 15px 16px 11px; border-bottom: 1px solid var(--line);
    display: grid; grid-template-columns: 44px minmax(0, 1fr); column-gap: 12px;
    scroll-margin-top: 52px; /* deep links land below the sticky bar */
  }
  section.post > * { grid-column: 2; min-width: 0; }
  section.post > .avatar { grid-column: 1; grid-row: 1; }
  section.post > .reply { grid-column: 1 / -1; }

  /* the avatar is still a little black board — same rule as the media boxes, at
     44px — but what is drawn on it is bun, not a Life pattern */
  .avatar { width: 44px; height: 44px; border-radius: 50%; flex: none;
    background: var(--board); border: 1px solid var(--board); display: grid; place-items: center; }
  .avatar svg { width: 68%; height: 68%; shape-rendering: crispEdges; display: block; }
  .av-host { color: #ecbec9; }
  /* the only account with nothing running in it yet is you */
  .av-you { background: var(--paper); border: 1px dashed var(--line-2); }

  /* the small grey line above a follow-up in the same thread */
  .rt-label { font-size: 12.5px; color: var(--ink-2); margin-top: 1px; }

  .post-text { font-size: 15px; line-height: 1.78; color: var(--ink);
    overflow-wrap: break-word; }
  .post-text p + p { margin-top: 10px; }
  .post-text b { font-weight: 700; }
  .chapter-bridge { padding: 18px 16px 18px 72px; border-bottom: 1px solid var(--line); }
  .controls button[aria-pressed="true"] { background: #1d4962; border-color: #4c94bb; color: #dff7ff; }
  .post-text .at { color: var(--blue); }

  /* One marked-up documentary crop, with no card UI around it. The surrounding
     page stays visible as context while the original offer is the sole focus. */
  .source-scan { margin-top: 12px; }
  .source-scan > a {
    display: block; overflow: hidden; border: 1px solid var(--line-2);
    background: var(--paper); text-decoration: none;
  }
  .source-scan > a:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
  .source-scan img { display: block; width: 100%; height: auto; }
  .source-scan figcaption { margin-top: 6px; color: var(--ink-3); font-size: 11.5px; line-height: 1.55; }

  /* the media box: black, like any video in a timeline. A canvas lives inside,
     and so does its own chrome — controls, hud, captions all ride on the board. */
  .post-media {
    position: relative; margin-top: 10px; border-radius: 16px;
    overflow: hidden; background: var(--board); aspect-ratio: var(--ar, 16/10);
  }
  .post-media canvas.stage { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
  .veil { position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(ellipse at 50% 42%, transparent 55%, rgba(8,13,25,.55) 100%); }

  .tip { margin-top: 8px; font-size: 13px; line-height: 1.65; color: var(--ink-2); }
  .tip b { color: var(--ink); font-weight: 700; }
  .tip .die { color: #cf3b52; }
  .tip .born { color: #0a8f4d; }
  /* Acorn explains itself while it runs. The caption is deliberately lighter
     than another card: one measured generation, one sentence, then back to the
     board. The history lives in the reply below. */
  .acorn-beat, .meta-beat {
    min-height: 39px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
    display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 10px;
    font-size: 12.5px; line-height: 1.55;
  }
  .acorn-beat b, .meta-beat b {
    color: var(--blue); font: 700 11px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  .acorn-beat span, .meta-beat span { color: var(--ink-2); }
  .source-note { margin-top: 7px; color: var(--ink-3); font-size: 12px; line-height: 1.6; }
  .source-note a { color: var(--blue); text-decoration: none; }
  .source-note a:hover { text-decoration: underline; }

  /* Chapter three leans on two sentences this account did not write, and they
     have to look borrowed: a rule down the left, and the attribution inside the
     component rather than trailing after it as a loose grey line. */
  .quote { margin-top: 12px; padding: 1px 0 1px 14px; border-left: 3px solid var(--line-2); }
  .quote p { font-size: 14.5px; line-height: 1.75; color: var(--ink); }
  .quote p + p { margin-top: 8px; }
  .quote .gloss { color: var(--ink-2); font-size: 13.5px; }
  .quote cite { display: block; margin-top: 8px; font-style: normal;
    font-size: 12px; line-height: 1.6; color: var(--ink-3); }
  .quote cite a { color: var(--blue); text-decoration: none; }
  .quote cite a:hover { text-decoration: underline; }
  /* the host may answer a quotation, and the answer is prose again, not a card */
  .quote + .post-text { margin-top: 12px; }

  /* The bar under a post carries actions, not applause. A reply count nobody
     replied to is a lie in small print; both of these do something. */
  .post-tools { margin-top: 11px; display: flex; flex-wrap: wrap; gap: 8px 20px; }
  .tool { display: inline-flex; align-items: center; gap: 7px; padding: 0;
    font: inherit; font-size: 13px; color: var(--ink-2); background: none; border: 0;
    text-decoration: none; cursor: pointer; }
  .tool[hidden] { display: none; }
  .tool svg { width: 16px; height: 16px; flex: none; stroke: currentColor; fill: none;
    stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  .tool:hover { color: var(--blue); }
  /* three states, because the clipboard can say no (old browser, denied
     permission) and a button must never claim something it did not do */
  .t-copy .ok, .t-copy .bar { display: none; }
  .t-copy.done, .t-copy.bar-only { color: var(--blue); }
  .t-copy.done .lbl, .t-copy.bar-only .lbl { display: none; }
  .t-copy.done .ok { display: inline; }
  .t-copy.bar-only .bar { display: inline; }

  /* OTCA is an exhibit, not a lesson. The only full-width square in the feed
     goes to the genuine pattern from its first frame; the words around it are
     keywords, and the one interaction is a zoom — scale is the whole point.
     The zoom waits behind the guess (the picture does not). */
  #s16 > .meta-media, #s16 > .meta-zoom, #s16 > .meta-beat, #s16 > .meta-punchline { grid-column: 1 / -1; }
  #s16 > .meta-media { margin-top: 13px; border-radius: 18px; }
  .meta-media canvas.stage { cursor: crosshair; }
  #s16:not(.guessed) > .meta-zoom, #s16:not(.guessed) > .meta-beat { display: none; }
  .meta-zoom { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 12px; }
  .meta-zoom label { display: flex; align-items: center; gap: 10px; flex: 1 1 240px; min-width: 0;
    font-size: 12.5px; color: var(--ink-2); }
  .meta-zoom input[type="range"] { flex: 1 1 auto; min-width: 0; accent-color: var(--blue); }
  .meta-zoom output { min-width: 4.5ch; text-align: right; color: var(--blue);
    font: 700 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace; }
  .meta-zoom button { border: 1px solid var(--line-2); border-radius: 18px; background: var(--paper); color: var(--ink);
    padding: 7px 12px; font: inherit; font-size: 13px; cursor: pointer; }
  .meta-zoom button:hover { border-color: var(--ink-3); }
  .meta-zoom button:focus-visible, .meta-zoom input:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
  .meta-hint { flex-basis: 100%; font-size: 12px; line-height: 1.5; color: var(--ink-3); }
  .meta-punchline { margin-top: 12px; color: var(--ink); font-size: 15px; line-height: 1.75; }
  .meta-punchline b { font-weight: 750; }
  /* keywords, not paragraphs: one chip per fact, read in any order */
  .meta-keys { list-style: none; display: flex; flex-wrap: wrap; gap: 6px 8px; margin-top: 10px; }
  .meta-keys li { padding: 4px 11px; border: 1px solid var(--line-2); border-radius: 999px; background: var(--paper);
    color: var(--ink-2); font-size: 12.5px; line-height: 1.5; }

  /* The opening is a nine-shot trailer, not a definition. Every tile runs the
     same B3/S23 rule; only the seed changes. Since 2026-09-08 the words above
     it name the example first (Conway's Game of Life, one cellular automaton),
     because a reader who cannot name what they are looking at cannot want it. */
  .opening-gallery { margin-top: 11px; }
  .opening-gallery-grid {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    width: min(100%, 390px); gap: 6px;
  }
  .opening-board {
    position: relative; min-width: 0; margin: 0; overflow: hidden; aspect-ratio: 1;
    border: 1px solid #202b3a; border-radius: 9px; background: var(--board);
  }
  .opening-board canvas { display: block; width: 100%; height: 100%; }
  .opening-gallery-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin-top: 10px;
  }
  .opening-gallery-foot > span { color: var(--ink-3); font-size: 11.5px; line-height: 1.5; }
  .opening-gallery-foot a {
    flex: none; padding: 7px 11px; border: 1px solid #b8d8ee; border-radius: 999px;
    color: #176b9f; background: #eaf5ff; font-size: 11.5px; font-weight: 700; text-decoration: none;
  }
  .opening-gallery-foot a:hover { border-color: var(--blue); background: #dcefff; }
  /* Every board is a promise, so every board is a door (2026-09-07, after a
     first-time reader tapped one and nothing happened). The link is a full
     overlay; the ↗ in the corner is the only mark left on the picture, and it
     always means the same thing: open this seed in the lab. */
  .opening-go { position: absolute; inset: 0; z-index: 2; border-radius: inherit; }
  .opening-go:focus-visible { outline: 2px solid #70bdf0; outline-offset: -2px; }
  .opening-go-mark {
    position: absolute; right: 5px; bottom: 5px; width: 16px; height: 16px;
    display: grid; place-items: center; border-radius: 999px;
    background: rgba(8,13,25,.78); border: 1px solid rgba(143,208,255,.24);
    color: #9bd7ff; font: 700 9px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
    transition: background .15s, color .15s;
  }
  .opening-board:hover .opening-go-mark { background: #9bd7ff; color: var(--board); }
  .opening-board:hover { border-color: #4c94bb; }

  /* where the cells are, one line under each exhibit's invitation */
  .exhibit-where { margin-top: 6px; color: var(--ink-3); font-size: 13px; line-height: 1.6; }

  /* The switch is drawn inside a reference circuit, and a reference circuit
     reads as a picture. Until it has been flipped once, its hit area breathes
     and a line under it says what to do; both stop at the first flip. */

  /* The half adder's reading key, as the same kind of table the reader has
     just used at the two switch posts: what is left on the board → the number. */
  .adder-legend { display: grid; grid-template-columns: minmax(0, 1fr) 44px; gap: 3px;
    margin-bottom: 12px; font: 11px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; color: #9da9b8; }
  .adder-legend span { border-radius: 6px; padding: 3px 6px; }
  .adder-legend .head { color: #707c8d; font-weight: 700; letter-spacing: .08em; }
  .adder-legend .num { text-align: center; color: #f5f8fb; background: rgba(84,118,153,.3); font-weight: 700; }
  .adder-legend + .adder-key { margin-bottom: 12px; font-size: 12px; color: #8b96a5; }

  /* #s8: at each appointed reading the board stops and asks; the reader's
     answer goes into the row of five, the board's verdict under it. */
  .guided-readings { flex-wrap: wrap; align-items: center; }   /* the row itself is styled with the guided board below */
  .guided-readings .read-slot { min-width: 1.4em; text-align: center; }
  .guided-readings .read-slot.right { color: #83e5a0; }
  .guided-readings .read-slot.wrong { color: #ffb347; text-decoration: line-through; }
  .read-ask { display: flex; justify-content: center; align-items: center; gap: 8px; margin-top: 2px; }
  .read-ask[hidden] { display: none; }
  .read-ask button { border: 1px solid #48627e; border-radius: 14px; background: #1b2b40; color: #e1e8f1;
    padding: 4px 11px; font: inherit; font-size: 12px; font-weight: 400; letter-spacing: 0; cursor: pointer; }
  .read-ask button:hover { background: #223047; border-color: #5a7697; }
  .read-ask button:focus-visible { outline: 2px solid #70bdf0; outline-offset: 2px; }
  .s8-reveal[hidden] { display: none; }

  /* a reply inside the same card */
  .reply { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 12px;
    display: grid; grid-template-columns: 36px minmax(0, 1fr); column-gap: 10px; }
  .reply .avatar { width: 36px; height: 36px; }
  .reply .r-body { min-width: 0; }
  .reply .post-text { font-size: 14.5px; }
  /* A real two-dimensional comparison: every x-axis mark is one of the twelve
     pentominoes and every bar is its measured transient. The scale stays linear
     because the nearly-flat first eleven bars are the comparison's conclusion. */
  .rpent-answer-number { margin: 1px 0 7px; color: var(--blue);
    font: 750 30px/1.15 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: -.045em; }
  .rpent-chart { margin: 12px 0 14px; padding: 15px 14px 12px; overflow: hidden;
    border-radius: 16px; background: var(--board); color: #e7edf3; }
  .rpent-chart-head { display: block; }
  .rpent-chart-head b { color: #edf2f6; font: 700 14px/1.45 Georgia, "Songti SC", serif; }
  .rpent-chart-head small { display: block; margin-top: 1px; color: #778596; font-size: 9.5px; line-height: 1.45; }
  .pento-chart { display: grid; grid-template-columns: 35px minmax(0, 1fr); grid-template-rows: 222px 34px;
    margin-top: 13px; }
  .pento-y { position: relative; grid-column: 1; grid-row: 1; color: #778596;
    font: 8.5px/1 ui-monospace, SFMono-Regular, Menlo, monospace; }
  .pento-y b { position: absolute; right: 5px; font: inherit; transform: translateY(50%); }
  .pento-y-title { position: absolute; top: -11px; right: 5px; color: #9aa7b5; font: 9px/1 sans-serif; }
  .pento-plot { position: relative; grid-column: 2; grid-row: 1; min-width: 0; }
  .pento-gridline { position: absolute; left: 0; right: 0; height: 1px; background: #202a38; }
  .pento-gridline.base { background: #3b4858; }
  .pento-bars { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
    align-items: end; gap: 4px; }
  .pento-column { position: relative; height: 100%; min-width: 0; }
  .pento-column:nth-child(1), .pento-glyph:nth-child(1) { --i: 0; }
  .pento-column:nth-child(2), .pento-glyph:nth-child(2) { --i: 1; }
  .pento-column:nth-child(3), .pento-glyph:nth-child(3) { --i: 2; }
  .pento-column:nth-child(4), .pento-glyph:nth-child(4) { --i: 3; }
  .pento-column:nth-child(5), .pento-glyph:nth-child(5) { --i: 4; }
  .pento-column:nth-child(6), .pento-glyph:nth-child(6) { --i: 5; }
  .pento-column:nth-child(7), .pento-glyph:nth-child(7) { --i: 6; }
  .pento-column:nth-child(8), .pento-glyph:nth-child(8) { --i: 7; }
  .pento-column:nth-child(9), .pento-glyph:nth-child(9) { --i: 8; }
  .pento-column:nth-child(10), .pento-glyph:nth-child(10) { --i: 9; }
  .pento-column:nth-child(11), .pento-glyph:nth-child(11) { --i: 10; }
  .pento-column:nth-child(12), .pento-glyph:nth-child(12) { --i: 11; }
  .pento-column > i { position: absolute; left: 50%; bottom: 0; width: min(14px, 62%);
    height: max(1px, calc(var(--h) * 1%)); border-radius: 3px 3px 0 0; background: #7c8998;
    opacity: .35; transform: translateX(-50%) scaleY(0); transform-origin: center bottom;
    transition: transform 720ms cubic-bezier(.2,.75,.25,1), opacity 300ms ease;
    transition-delay: calc(var(--i, 0) * 45ms); }
  .pento-column > b { position: absolute; left: 50%; bottom: calc(var(--h) * 1% + 5px);
    color: #aeb9c5; font: 700 8.5px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
    white-space: nowrap; opacity: 0; transform: translate(-50%, 4px);
    transition: opacity 260ms ease, transform 260ms ease;
    transition-delay: calc(var(--i, 0) * 45ms + 430ms); }
  .pento-column.outlier > i { background: var(--blue); box-shadow: 0 0 14px rgba(29,155,240,.26);
    transition-duration: 1450ms, 350ms; transition-delay: 760ms; }
  .pento-column.outlier > b { left: auto; right: 0; color: #55b6f7; font-size: 10px;
    transform: translateY(4px); transition-delay: 1850ms; }
  .rpent-chart.revealed .pento-column > i { opacity: 1; transform: translateX(-50%) scaleY(1); }
  .rpent-chart.revealed .pento-column > b { opacity: 1; transform: translate(-50%, 0); }
  .rpent-chart.revealed .pento-column.outlier > b { transform: none; }
  .pento-x { grid-column: 2; grid-row: 2; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 4px; padding-top: 5px; }
  .pento-glyph { display: block; width: min(22px, 88%); aspect-ratio: 1; margin: 0 auto;
    overflow: visible; color: #8e9aa8; opacity: .45; transition: color 350ms ease, opacity 350ms ease;
    transition-delay: calc(var(--i, 0) * 45ms + 180ms); }
  .rpent-chart.revealed .pento-glyph { opacity: 1; }
  .pento-glyph.outlier { color: var(--blue); filter: drop-shadow(0 3px 5px rgba(29,155,240,.2)); }
  .pento-scale-note { grid-column: 2; margin-top: 4px; color: #758395; font-size: 9px; line-height: 1.4; }
  .rpent-punchline { margin-top: 12px; padding-top: 10px; border-top: 1px solid #202a38;
    color: #aab6c2; font: 500 12px/1.55 Georgia, "Songti SC", serif; text-align: center; }
  .rpent-punchline b { color: #55b6f7; }
  @media (prefers-reduced-motion: reduce) {
    .pento-column > i, .pento-column > b, .pento-glyph { transition: none; }
    .uc-arrow { animation: none; }
  }

  /* Three gallery labels make the feed's route explicit without pretending to
     be posts. Each says what the next room is for, not what it will conclude. */
  /* The chapter breaks are the same dark surface as every board on the page:
     a white sheet, and the things that matter are dark blocks on it. No hairline
     under it — the colour change already is the separation. */
  .chapter-break {
    display: grid; grid-template-columns: 42px minmax(0, 1fr); gap: 12px;
    padding: 26px 16px 22px; background: var(--board);
  }
  /* Numbers cut from the same grid as the banner's letters. 14px tall = seven
     rows of exactly 2px, so the cells land on whole pixels and stay square. */
  /* The rule itself, in the running text. It used to live only behind the last
     step of the six-step tutor — and chapter three then told the reader they had
     learned it in chapter one, which was only true if they had clicked. */
  .rule-said { margin-left: 2px; padding: 2px 0 2px 13px; border-left: 3px solid var(--line-2); }
  .rule-said b { color: var(--ink); }
  .px-num { display: block; height: 14px; width: auto; fill: currentColor;
    shape-rendering: crispEdges; }
  .vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
  .chapter-no { color: var(--blue); padding-top: 4px; }
  .chapter-copy { display: flex; flex-direction: column; gap: 4px; }
  .chapter-copy b { color: #fff; font-size: 16px; line-height: 1.4; }
  .chapter-copy small { color: rgba(255,255,255,.66); font-size: 12.5px; line-height: 1.55; }

  /* 01 / 02 / 03 (#s1 #blinker #s2): the same board three times. Same 9×9
     grid, same clock, one pause button — so the only difference the reader
     can see is what the seed does. These three used to narrate the rule step
     by step; that job belongs to #definition's six cards, and here the
     behaviour is the whole point. */
  .loop-board {
    margin-top: 12px; padding: 14px 16px 16px; border-radius: 16px;
    background: var(--board); color: #e3eaf2;
  }
  .loop-label { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .loop-label small { color: #758296; font: 600 10px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; }
  .loop-gen { color: #edf2f7; font: 700 14px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; }
  .loop-grid {
    width: min(100%, 300px); aspect-ratio: 1; margin: 16px auto 2px;
    display: grid; grid-template-columns: repeat(9, 1fr); gap: 4px;
  }
  .loop-grid > span {
    border-radius: 5px; background: #151c28;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.035);
    transition: background .2s, transform .2s, box-shadow .2s;
  }
  .loop-grid > span.live { background: var(--cell); transform: scale(.92); box-shadow: 0 0 12px rgba(var(--cell-glow),.22); }
  /* it runs by itself and never stops, so a way to stop it is not optional */
  .loop-board:not(.guessed) .loop-pause { display: none; }
  @media (prefers-reduced-motion: reduce) { .loop-grid > span { transition: none; } }

  .rule-action, .rule-guess-btn {
    border: 1px solid #3a4b62; border-radius: 999px; background: #172131;
    color: #dbe5ef; padding: 8px 13px; font: inherit; font-size: 12px; font-weight: 600; line-height: 1.2; cursor: pointer;
  }
  .rule-action:hover, .rule-guess-btn:hover { background: #223047; border-color: #5a7697; }
  .rule-action:focus-visible, .rule-guess-btn:focus-visible { outline: 2px solid #70bdf0; outline-offset: 2px; }
  .rule-action:disabled { opacity: .35; cursor: default; }

  /* #definition: six cases as six paper cards on the page, not one dark slab —
     the reader asked for room to breathe and for the cards to feel like
     something you do. Each card holds a small dark board, a premise and two
     buttons; answering turns the board to the next generation, marks the card
     green or amber, and the foot keeps score. */
  .rule-lab { margin-top: 14px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .rule-key, .rule-foot { grid-column: 1 / -1; }
  .rule-key { display: grid; grid-template-columns: 62px minmax(0, 1fr); gap: 14px; align-items: center; padding: 0 2px 4px; }
  .rule-key p { margin: 0; color: var(--ink-2); font-size: 14px; line-height: 1.6; }
  .rule-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 6px; border-radius: 10px; background: var(--board); }
  .rule-cell {
    position: relative; aspect-ratio: 1; border: 1px solid #283448; border-radius: 5px; background: #141b27;
    transition: background .35s, border-color .35s, box-shadow .35s, opacity .35s;
  }
  .rule-cell.live { background: var(--cell); border-color: #fffaf0; box-shadow: 0 0 10px rgba(var(--cell-glow),.18); }
  .rule-cell.centre { border-color: #dd9c4b; box-shadow: inset 0 0 0 1px rgba(255,188,92,.22); }
  .rule-cell.centre::after {
    content: ""; position: absolute; inset: 50% auto auto 50%; width: 6px; height: 6px;
    border: 1px solid #ffb347; border-radius: 50%; transform: translate(-50%, -50%);
  }
  .rule-cell.centre.live::after { background: #8b541f; }
  .rule-cell.neighbour { border-color: #55708e; }
  .rule-cell.counted::before {
    content: attr(data-count); position: absolute; top: 2px; right: 3px;
    width: 13px; height: 13px; display: grid; place-items: center; border-radius: 50%;
    background: #1d9bf0; color: #fff; font: 700 8px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  /* Answered: the board shows the next generation. Only the centre changes;
     the neighbours fade, because what becomes of them depends on cells
     outside the card. */
  .rule-grid.next .rule-cell.neighbour { opacity: .3; }
  .rule-card {
    display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 14px; align-items: center;
    padding: 12px 14px 12px 12px; border: 1px solid var(--line-2); border-radius: 14px; background: var(--paper);
    transition: border-color .25s, box-shadow .25s;
  }
  .rule-card.is-right { border-color: #4cbf73; box-shadow: 0 0 0 3px rgba(76,191,115,.14); animation: rule-pop .38s ease-out; }
  .rule-card.is-wrong { border-color: #e0973a; box-shadow: 0 0 0 3px rgba(224,151,58,.14); animation: rule-shake .32s ease-in-out; }
  @keyframes rule-pop { 0% { transform: scale(1); } 45% { transform: scale(1.025); } 100% { transform: scale(1); } }
  @keyframes rule-shake { 0%, 100% { transform: translateX(0); } 30% { transform: translateX(-3px); } 70% { transform: translateX(3px); } }
  .rule-readout { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
  .rule-eyebrow { color: var(--ink-3); font: 600 10px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; text-transform: uppercase; }
  .rule-count { color: var(--ink); font-size: 15px; line-height: 1.3; }
  .rule-guess { display: flex; gap: 8px; margin-top: 2px; }
  .rule-guess[hidden] { display: none; }
  /* paper buttons: the shared board-button look is for dark boards */
  .rule-card .rule-guess-btn, .rule-foot .rule-action {
    min-width: 56px; background: var(--paper); color: var(--ink); border: 1px solid var(--line-2);
    border-radius: 18px; padding: 7px 14px; font-size: 13px; font-weight: 600;
  }
  .rule-card .rule-guess-btn:hover, .rule-foot .rule-action:hover { background: #f7f9f9; border-color: var(--ink-3); }
  .rule-mark { font: 700 10px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; text-transform: uppercase; }
  .rule-mark[hidden] { display: none; }
  .rule-mark.right { color: #2f9e57; }
  .rule-mark.wrong { color: #c77d1c; }
  .rule-verdict { color: var(--ink); font-size: 14px; line-height: 1.5; }
  .rule-verdict[hidden] { display: none; }
  .rule-verdict.die { color: #c2453a; }
  .rule-verdict.born { color: #2f9e57; }
  .rule-verdict.live { color: #8a6412; }
  .rule-verdict.still { color: var(--ink-2); }
  .rule-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 2px; }
  .rule-foot[hidden] { display: none; }
  .rule-tally { color: var(--ink-2); font-size: 14px; line-height: 1.5; }
  .rule-tally[hidden] { display: none; }
  .rule-tally.done { color: var(--ink); }
  .rule-tally b { color: var(--ink); }
  .rule-reset[hidden] { display: none; }
  @media (prefers-reduced-motion: reduce) {
    .rule-card.is-right, .rule-card.is-wrong { animation: none; }
    .rule-cell { transition: none; }
  }
  /* The whole-pattern lessons ask first. The question sits on the board; the
     checks, captions and controls appear once the reader has committed, and
     the demo then plays itself — a wrong guess is answered by the board. */
  .lesson-guess { display: flex; flex-direction: column; align-items: center; gap: 9px; margin: 12px 0 6px; text-align: center; }
  .lesson-guess[hidden] { display: none; }
  .lesson-guess-ask { color: #dbe3eb; font-size: 13px; line-height: 1.55; }
  .lesson-guess-btns { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
  .lesson-guess-btn {
    border: 1px solid #40516a; border-radius: 18px; background: #1b2a3e; color: #edf2f7;
    padding: 7px 13px; font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1.4; cursor: pointer;
  }
  .lesson-guess-btn:hover { background: #223047; border-color: #5a7697; }
  .lesson-guess-btn:focus-visible { outline: 2px solid #70bdf0; outline-offset: 2px; }
  .lesson-mark { margin: 10px 0 2px; text-align: center; font: 700 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .06em; }
  .lesson-mark[hidden] { display: none; }
  .lesson-mark.right { color: #83e5a0; }
  .lesson-mark.wrong { color: #ffb347; }
  .lesson-guess-slot.paper .lesson-guess { align-items: flex-start; text-align: left; margin: 10px 0 0; }
  .lesson-guess-slot.paper .lesson-guess-btns { justify-content: flex-start; }
  .lesson-guess-slot.paper .lesson-guess-ask { color: var(--ink-2); font-size: 14px; }
  .lesson-guess-slot.paper .lesson-guess-btn { background: var(--paper); color: var(--ink); border-color: var(--line-2); }
  .lesson-guess-slot.paper .lesson-guess-btn:hover { background: #f7f9f9; border-color: var(--ink-3); }
  .lesson-guess-slot.paper .lesson-mark { text-align: left; margin: 10px 0 0; }
  .lesson-guess-slot.paper .lesson-mark.right { color: #2f9e57; }
  .lesson-guess-slot.paper .lesson-mark.wrong { color: #c77d1c; }
  .guided-board.has-guess:not(.guessed) .lesson-controls, .guided-board.has-guess:not(.guessed) .guided-note,
  .guided-board.has-guess:not(.guessed) .guided-readings { display: none; }
  .fieldbook-card .lesson-guess { margin: 4px 0 0; gap: 6px; }
  .fieldbook-card .lesson-guess-btn { padding: 5px 9px; font-size: 11px; }
  .fieldbook-card .lesson-mark { margin: 4px 0 0; font-size: 10px; letter-spacing: .04em; }
  .reply[hidden] { display: none; }
  .rule-lab + .post-text, .guided-board + .post-text, .post-media + .post-text, .logic-card + .post-text, .logic-lab + .post-text, .behavior-map + .post-text { margin-top: 16px; }
  .lesson-extra > summary { cursor: pointer; font-size: 14px; line-height: 1.65; color: var(--ink-2); }
  .lesson-extra[open] > summary { margin-bottom: 14px; }
  .lesson-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 14px 0 8px; }
  .lesson-actions button, .lesson-head button {
    border: 1px solid #40516a; border-radius: 18px; background: #1b2a3e; color: #edf2f7;
    padding: 8px 13px; min-height: 38px; font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1.4; cursor: pointer;
  }
  .lesson-actions button:disabled { opacity: .4; cursor: default; }
  .lesson-actions button:focus-visible, .lesson-head button:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
  .lesson-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
  .lesson-review { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line-2); }
  .lesson-review summary { cursor: pointer; font-weight: 600; line-height: 1.65; }
  .lesson-review p { font-size: 14px; line-height: 1.7; margin-top: 10px; }
  .acorn-fieldbook { margin-top: 16px; }
  .acorn-fieldbook[hidden] { display: none; }
  .guided-board { margin-top: 16px; padding: 16px; background: var(--board); color: #e1e8f1; border-radius: 16px; }
  .guided-views { display: grid; grid-template-columns: repeat(var(--views, 1), minmax(0, 1fr)); gap: 12px; }
  .guided-views figure { margin: 0; min-width: 0; }
  .guided-views figcaption { font-size: 13px; line-height: 1.6; text-align: center; }
  .guided-views svg { display: block; width: 100%; margin: 8px auto; max-height: 340px; }
  .guided-note { min-height: 3.2em; font-size: 14px; line-height: 1.65; margin-top: 10px; }
  .guided-readings { display: flex; justify-content: center; gap: 12px; font: 700 22px/1.8 ui-monospace, monospace; letter-spacing: .1em; }
  .lesson-controls { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 12px; }
  .lesson-controls button, .adder-reveal { border: 1px solid #48627e; border-radius: 18px; background: #1b2b40; color: #e1e8f1; padding: 8px 12px; font: inherit; font-size: 13px; cursor: pointer; }
  .lesson-controls button:disabled, .adder-reveal:disabled { opacity: .4; cursor: default; }
  .lesson-controls button:focus-visible, .adder-reveal:focus-visible { outline: 2px solid #70bdf0; outline-offset: 3px; }
  .adder-key { font-size: 14px; line-height: 1.7; margin-bottom: 14px; }
  .interception-extra > .post-media { margin-top: 14px; }
  @media (max-width: 420px) { .guided-board { padding: 12px; } .guided-views { gap: 6px; } .guided-views figcaption { font-size: 12px; } }
  .fieldbook-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 12px; }
  .fieldbook-card { min-width: 0; padding: 12px 8px; background: var(--board); color: #e1e8f1; border-radius: 10px; }
  .fieldbook-card b, .fieldbook-card small { display: block; font-size: 12px; line-height: 1.6; }
  .fieldbook-card small { color: #aebed2; }
  .fieldbook-card svg { display: block; width: 100%; aspect-ratio: 1; margin: 8px 0; }
  .fieldbook-card rect { fill: var(--cell); }
  .fieldbook-card .origin { fill: none; stroke: #7892af; stroke-width: .07; stroke-dasharray: .15 .12; }
  @media (max-width: 420px) { .fieldbook-cards { grid-template-columns: 1fr; } .fieldbook-card { display: grid; grid-template-columns: minmax(0, 1fr) 88px; align-items: center; } .fieldbook-card svg { grid-column: 2; grid-row: 1 / 3; margin: 0; } }

  .behavior-map {
    margin-top: 16px; padding: 2px 0 4px; display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px;
  }
  .behavior-mode {
    min-width: 0; padding: 0 4px; display: flex; flex-direction: column;
    align-items: center; gap: 3px; text-align: center;
  }
  .behavior-mode small {
    width: 38px; height: 38px; margin-bottom: 6px; display: grid; place-items: center;
    border-radius: 50%; background: var(--board); color: #7cc2ff;
    font: 700 10px/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .04em;
  }
  /* The badge is the pattern itself, drawn from the same seed the post below
     runs (BLOCK / BLINKER / GLIDER) at the phase that board opens on, on a tile
     of the same board colour. A numeral spent 38 square pixels saying something
     the label under it already said. Static on purpose: the boards below ask
     the reader to guess what happens next, and a moving badge would answer. */
  .behavior-shape {
    display: block; width: 38px; height: 38px; margin-bottom: 6px;
    border-radius: 11px; background: var(--board);
  }
  .behavior-shape rect { fill: var(--cell); }
  .behavior-mode b { color: var(--ink); font-size: 14px; line-height: 1.4; }
  .behavior-mode em { color: var(--ink-3); font-size: 11.5px; font-style: normal; line-height: 1.5; }
  /* Chapter two reuses the three-part card as an anatomy label for the gun. */
  .behavior-mode i {
    position: relative; margin-top: 6px; padding-top: 17px;
    color: var(--ink); font-style: normal; font-size: 13.5px; font-weight: 700; line-height: 1.35;
  }
  .behavior-mode i::before {
    content: "\2193"; position: absolute; top: 1px; left: 50%; transform: translateX(-50%);
    color: var(--line-2); font-size: 13px; font-weight: 400;
  }

  /* the thread does not end in a fake composer. It hands the reader a real,
     blank board; the small grid is a preview of the place the link opens. */
  .handoff {
    margin: 18px 16px 0; padding: 17px 18px; border: 1px solid var(--line-2);
    border-radius: 16px; display: grid; grid-template-columns: 50px minmax(0, 1fr) 38px;
    align-items: center; gap: 14px; color: var(--ink); text-decoration: none;
    transition: border-color .2s, box-shadow .2s, transform .2s;
  }
  .handoff:hover { border-color: var(--blue); box-shadow: 0 8px 28px rgba(15,20,25,.08); transform: translateY(-1px); }
  .handoff-grid {
    position: relative; width: 50px; height: 50px; border-radius: 12px; overflow: hidden;
    background-color: var(--board);
    background-image: linear-gradient(#1b2432 1px, transparent 1px), linear-gradient(90deg, #1b2432 1px, transparent 1px);
    background-size: 10px 10px;
  }
  .handoff-grid::after {
    content: ""; position: absolute; width: 9px; height: 9px; left: 20px; top: 20px;
    background: var(--cell); box-shadow: 0 0 9px rgba(var(--cell-glow),.4);
  }
  .handoff-copy { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .handoff-copy b { font-size: 16px; line-height: 1.45; }
  .handoff-copy small { color: var(--ink-2); font-size: 13px; line-height: 1.5; }
  .handoff-arrow {
    width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
    color: #fff; background: var(--blue); font-size: 20px; line-height: 1;
  }

  /* ---- everything below rides on a black board, so it stays dark chrome ---- */

  /* controls + hud live inside the media box, like a player's own chrome */
  .controls {
    position: absolute; right: 10px; bottom: 10px; display: flex; gap: 6px; z-index: 5;
    align-items: center; flex-wrap: wrap; justify-content: flex-end; max-width: calc(100% - 20px);
  }
  .controls button {
    background: rgba(24,31,45,.88); color: #cfd8e4; border: 1px solid #2e3a50;
    border-radius: 9px; padding: 7px 11px; font-size: 12px; cursor: pointer; white-space: nowrap;
  }
  .controls button:hover { background: #263248; }
  .controls button:disabled { opacity: .42; cursor: default; }
  .controls button[hidden] { display: none; }
  .controls button.input-on { background: #1d4962; border-color: #4c94bb; color: #dff5ff; }
  .controls button.primary { background: #7a4a1d; border-color: #a86a2e; color: #ffe8cc; font-weight: 600; padding: 8px 16px; font-size: 13px; }
  .controls button.primary:hover { background: #8f5722; }
  .hud {
    position: absolute; top: 10px; right: 12px; text-align: right; z-index: 4;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px; color: #77828f; line-height: 1.7; pointer-events: none;
    text-shadow: 0 1px 6px rgba(0,0,0,.8);
  }
  .hud-seed { color: #7cc2ff; font-weight: 700; }
  .outcome { width: 100%; text-align: right; font-size: 12px; color: #ffb347; min-height: 16px; }

  /* The interception post is the one board with a right answer and a wrong one,
     so it gets what a game gets: a standing instruction that changes as the run
     changes. Top-left, opposite the generation counter. */
  .st-task {
    position: absolute; top: 10px; left: 12px; z-index: 4; max-width: 62%;
    font-size: 12px; line-height: 1.6; color: #9aa6b4; pointer-events: none;
    text-shadow: 0 1px 6px rgba(0,0,0,.85); transition: color .15s;
  }
  .st-task.now { color: #ffce8a; font-weight: 600; }
  .st-task:empty { display: none; }

  /* "About 25 squares away" is a number with no shape. The window is an
     interval, so it is drawn as one: the band is [CLEAN_MIN, CLEAN_MAX] and the
     ticks inside it are the silo's 8-generation beat — both read straight off
     the constants, never hand-placed. Paper side, because it is an instrument
     the reader aims with, not part of the world. */
  .timeline { margin-top: 9px; }
  .tl-track {
    position: relative; height: 8px; border-radius: 5px; background: var(--line);
    overflow: hidden;
  }
  .tl-band {
    position: absolute; top: 0; bottom: 0;
    left: var(--band-x, 20%); width: var(--band-w, 51%);
    background: #ffb84d;
    /* one tick per beat: only 1 generation in 8 can launch */
    background-image: repeating-linear-gradient(90deg,
      rgba(0,0,0,.34) 0 1px, transparent 1px var(--beat, 5.7%));
  }
  /* past the deadline the lead glider is already through the crossing, so a
     shot there can only make a mess — the tail says so before it happens */
  .tl-late {
    position: absolute; top: 0; bottom: 0; right: 0;
    left: calc(var(--band-x, 3%) + var(--band-w, 85%));
    background: repeating-linear-gradient(135deg,
      rgba(191,72,72,.32) 0 3px, transparent 3px 7px);
  }
  .tl-head {
    position: absolute; top: -3px; bottom: -3px; width: 2px; border-radius: 2px;
    background: var(--ink); left: var(--p, 0%); transform: translateX(-1px);
    transition: opacity .2s;
  }
  .timeline.done .tl-head { opacity: .35; }
  .tl-marks {
    margin-top: 5px; display: flex; font-size: 11.5px; color: var(--ink-3);
    line-height: 1.5;
  }
  .tl-marks .tl-win { margin-left: var(--band-x, 20%); color: #b07314; font-weight: 600; }
  .tl-marks .tl-beat { margin-left: auto; }


  /* jam caption: a subtitle along the bottom of the media box, clear of the
     top of the ring where the jam itself is happening */
  .jam-note {
    position: absolute; z-index: 6; bottom: 10px; left: 50%; transform: translateX(-50%);
    /* width:max-content, like .tw-note. Without it the shrink-to-fit width of a
       left:50% box is only the half of the media box to the right of that edge,
       so on a phone this caption wrapped to five lines and covered the road it
       is describing. */
    width: max-content; max-width: calc(100% - 24px); padding: 9px 15px;
    background: rgba(12,16,24,.9); border: 1px solid #2c3850; border-radius: 14px;
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    font-size: 13px; line-height: 1.55; color: #e8edf4; text-align: center;
    opacity: 0; transition: opacity .6s; pointer-events: none;
  }
  .jam-note.shown { opacity: 1; }

  /* rules tour (s1) */
  .tour-chip {
    position: absolute; z-index: 6; top: 10px; left: 50%; transform: translateX(-50%);
    display: flex; align-items: center; gap: 10px;
    max-width: calc(100% - 20px); padding: 8px 10px 8px 15px;
    background: rgba(12,16,24,.9); border: 1px solid #2c3850; border-radius: 14px;
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  }
  .tour-chip p { font-size: 13px; line-height: 1.5; color: #e8edf4; }
  .tour-chip button {
    flex: none; background: rgba(24,31,45,.85); color: #9aa5b3; border: 1px solid #2e3a50;
    border-radius: 999px; padding: 5px 12px; font-size: 12px; cursor: pointer;
  }
  .tour-chip button:hover { background: #263248; color: #cfd8e4; }
  .tour-chip.hidden { display: none; }

  /* #s9 is one machine, not a schematic plus a machine. The circuit symbols
     are drawn on the board at the places those parts really occupy, and the
     table under it is the switch: pick a row, and that is the lever thrown.
     One battery, one wire, one lamp — the split version had two, two, three. */
  .logic-lab { margin: 11px 0 0; padding: 13px 14px 12px; border-radius: 16px; background: var(--board); }
  .logic-lab .eyebrow { color: #707c8d; font-size: 10px; font-weight: 700; letter-spacing: .16em; }
  .logic-lab .post-media { margin: 7px 0 0; border-radius: 10px; }
  /* .controls is absolutely positioned so it can sit in a board's corner.
     In the slot it becomes an ordinary row; without this it escapes to the
     nearest positioned ancestor, which is the whole post. */
  .controls-slot .controls { position: static; margin-top: 11px; justify-content: center; max-width: 100%; }
  .truth-switch { margin-top: 11px; display: grid; gap: 5px; }
  .truth-switch .ts-head, .truth-switch .ts-row {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) 30px;
    gap: 10px; align-items: center;
  }
  /* two inputs: one row is still one whole setting of the machine */
  .truth-switch.cols-ab .ts-head, .truth-switch.cols-ab .ts-row {
    grid-template-columns: 26px 26px minmax(0, 1fr) 30px; gap: 12px;
  }
  .truth-switch.cols-ab .ts-row { padding: 8px 11px; }
  .truth-switch .ts-head {
    padding: 0 11px; color: #8592a3;
    font: 700 10px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .1em;
  }
  .truth-switch .ts-head span:last-child, .ts-row .ts-got { justify-self: end; }
  .ts-row {
    padding: 9px 11px; border: 1px solid #2b3749; border-radius: 10px;
    background: rgba(24,31,45,.55); color: #8b97a8; text-align: left; cursor: pointer;
    font: 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  .ts-row:hover { border-color: #4c94bb; background: rgba(31,43,64,.85); }
  .ts-row:focus-visible { outline: 2px solid #70bdf0; outline-offset: 2px; }
  .ts-row.current { border-color: #6e5626; background: rgba(58,45,20,.45); color: #f2f5f8; }
  .ts-got {
    display: inline-grid; place-items: center; width: 26px; height: 26px;
    border-radius: 50%; border: 1px solid #3a4759; color: #728094; font-size: 12px;
  }
  .ts-row:not(.current) .ts-got { opacity: 0; }
  /* until it has been thrown once, the position you are not in invites a click */
  @keyframes ts-pulse { 0%, 100% { border-color: #2b3749; } 50% { border-color: #7cc2ff; } }
  .ts-row.hint { animation: ts-pulse 1.6s ease-in-out infinite; }
  @media (prefers-reduced-motion: reduce) { .ts-row.hint { animation: none; border-color: #7cc2ff; } }
  .ts-hint { margin-top: 9px; text-align: center; color: #7c8a9c; font-size: 11.5px; line-height: 1.5; }
  .ts-hint[hidden] { display: none; }
  .ts-got.on { border-color: #ffd27a; background: rgba(255,188,92,.18); color: #ffe6b4; box-shadow: 0 0 15px rgba(255,188,92,.28); }

  /* The classic drawing is back, but as a key in the corner of the board it
     explains, not as a second box: same wire, same switch, same lamp, syncing
     off the same hooks. It takes no clicks — the table below is the control —
     so the reader never has two switches to choose between. */
  .circuit-inset {
    position: absolute; z-index: 3; left: 10px; top: 10px; width: min(30%, 168px);
    padding: 9px 10px 7px; border-radius: 10px;
    background: rgba(9,14,24,.86); border: 1px solid #23304a;
  }
  .circuit-inset .circuit { height: auto; }

  /* which corner is empty depends on the board: the AND current runs from the
     top-left corner down, so its key sits under the wire instead */
  .circuit-inset.at-bottom-left { top: auto; bottom: 10px; }
  @media (max-width: 700px) {
    .circuit-inset { width: min(52%, 168px); left: auto; right: 7px; top: auto; bottom: 7px; padding: 7px 8px 5px; }
    .circuit-inset.at-bottom-left { left: 7px; right: auto; }
  }

  /* logic chapter: the reference circuit is a widget pinned above the board.
     It is a picture of a machine, so it is black like the board it explains. */
  .logic-card {
    margin: 11px 0 0; background: var(--board);
    border-radius: 16px; padding: 13px 14px 12px;
  }
  .logic-card .eyebrow { color: #707c8d; font-size: 10px; font-weight: 700; letter-spacing: .16em; }
  .logic-card svg { display: block; width: 100%; height: 72px; margin: 3px 0 7px; overflow: visible; }
  .logic-card svg.circuit { height: 96px; }
  .circuit { display: block; width: 100%; overflow: visible; }
  .circuit .wire { fill: none; stroke: #6e7b8e; stroke-width: 2; }
  .circuit .gate { fill: #141b28; stroke: #b4c0cf; stroke-width: 2; }
  .circuit .node { fill: var(--board); stroke: #b4c0cf; stroke-width: 2; }
  .circuit text { fill: #cbd4df; font: 600 11px ui-monospace, SFMono-Regular, Menlo, monospace; }
  /* clickable switches inside the reference circuit: buttons that live on the diagram */
  .circuit .sw { cursor: pointer; }
  .circuit .sw .hit { fill: rgba(24,31,45,.55); stroke: #2e3a50; stroke-width: 1; }
  .circuit .sw:hover .hit { fill: rgba(31,43,64,.85); stroke: #4c94bb; }
  .circuit .sw.closed .hit { stroke: #6e5626; }
  .circuit .sw .lever { fill: none; stroke-width: 3; stroke-linecap: round; }
  .circuit .sw .sw-closed { stroke: #ffd27a; }
  .circuit .sw .sw-open { stroke: #8b96a5; }
  .circuit .sw:not(.closed) .sw-closed { display: none; }
  .circuit .sw.closed .sw-open { display: none; }
  .circuit .sw .sw-tag { text-anchor: middle; fill: #8b96a5; }
  .circuit .sw.closed .sw-tag { fill: #ffd27a; }
  .circuit .sw:hover .lever, .circuit .sw:focus-visible .lever { filter: brightness(1.35); }
  .circuit .sw:focus-visible { outline: 1px dashed #4c94bb; outline-offset: 2px; }
  .circuit .bulb .glass { fill: var(--board); stroke: #b4c0cf; stroke-width: 2; }
  .circuit .bulb .cross { fill: none; stroke: #b4c0cf; stroke-width: 2; }
  .circuit .bulb.lit .glass { fill: rgba(255,188,92,.22); stroke: #ffd27a; filter: drop-shadow(0 0 6px rgba(255,188,92,.75)); }
  .circuit .bulb.lit .cross { stroke: #ffd27a; }
  /* The real half-adder still runs underneath, but the lesson presents only
     the question a child needs here: how many gliders arrived, 0, 1, or 2? */
  .adder-try { margin-top: 10px; }
  .adder-row { display: flex; align-items: flex-end; gap: 10px; margin: 9px 0 7px; }
  .adder-input, .adder-total { display: grid; justify-items: center; gap: 4px; }
  .adder-input small, .adder-total small {
    color: #778596; font-size: 9px; line-height: 1.2; white-space: nowrap;
  }
  .adder-row .digit {
    width: 46px; height: 50px; border-radius: 10px; cursor: pointer;
    font: 700 24px ui-monospace, SFMono-Regular, Menlo, monospace;
    background: #182131; color: #dff5ff; border: 1px solid #3b5a78;
  }
  .adder-row .digit:hover { background: #1f2b40; border-color: #4c94bb; }
  .adder-row .op { align-self: center; margin-top: 13px; color: #8b96a5; font: 600 20px ui-monospace, SFMono-Regular, Menlo, monospace; }
  .adder-total { margin-left: 2px; }
  .adder-total b {
    display: grid; place-items: center; width: 54px; height: 50px;
    border-radius: 12px; border: 1px solid #3a4759; background: #0e1420;
    color: #728094; font: 700 28px ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  .adder-total b.set {
    color: #c9f6d4; border-color: #5cbe79; background: rgba(76,187,106,.16);
    box-shadow: 0 0 16px rgba(76,187,106,.22);
  }
  .adder-note { font: 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; color: #66738a; margin-bottom: 6px; min-height: 16px; }
  .adder-task.done { color: #9aebb0; font-weight: 600; }
  .truth { display: grid; gap: 3px; font: 11px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; color: #718093; }
  .truth.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .truth span { border-radius: 6px; padding: 2px 5px; text-align: center; }
  .truth .head { color: #9da9b8; font-weight: 700; }
  .truth .current { color: #f5f8fb; background: rgba(84,118,153,.3); }
  .logic-result { display: flex; gap: 8px; margin-top: 9px; }
  .logic-result .readout { flex: 1; color: #8090a3; font: 11px ui-monospace, SFMono-Regular, Menlo, monospace; }
  .logic-result .readout b { display: inline-grid; place-items: center; min-width: 24px; height: 24px; margin-left: 4px; border-radius: 50%; border: 1px solid #3a4759; color: #728094; }
  .logic-result .readout.on b { border-color: #5cbe79; background: rgba(76,187,106,.2); color: #bff6cc; box-shadow: 0 0 16px rgba(76,187,106,.3); }

  /* ?plain — headless/CI probe mode: skip effects that are brutal on software rasterizers */
  .plain .tour-chip { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(12,16,24,.95); }
  .plain .jam-note { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(12,16,24,.95); }
  .plain .veil { display: none; }
  @media (max-width: 720px) {
    /* The back link, the contents and the language switch are fixed to the top
       corners. On a phone the column is full width, so they float directly on the
       header board — nothing reserves space for them, and they turn white while
       that board is under them. Desktop is clear of it anyway: the column is
       620px inside a wider viewport. */
    .feed { border: none; }
    section.post { padding: 13px 12px 9px; column-gap: 10px; grid-template-columns: 40px minmax(0, 1fr); }
    .avatar { width: 40px; height: 40px; }
    .reply .avatar { width: 32px; height: 32px; }
    .reply { grid-template-columns: 32px minmax(0, 1fr); }
    .post-text { font-size: 14.5px; line-height: 1.72; }
    .pf-body { padding: 0 12px 10px; }
    .pf-row { margin-top: -30px; }
    .avatar.pf-avatar { width: 66px; height: 66px; border-width: 3px; }
    .controls { left: 10px; right: 10px; justify-content: center; }
    .handoff { margin-inline: 12px; padding: 14px; grid-template-columns: 46px minmax(0, 1fr) 34px; gap: 11px; }
    .handoff-grid { width: 46px; height: 46px; background-size: 9px 9px; }
    .handoff-grid::after { width: 8px; height: 8px; left: 19px; top: 19px; }
    .handoff-arrow { width: 34px; height: 34px; }
    .chapter-break { grid-template-columns: 36px minmax(0, 1fr); padding-inline: 12px; gap: 8px; }
    .rule-lab { grid-template-columns: 1fr; gap: 10px; }
    .rule-card { grid-template-columns: 80px minmax(0, 1fr); }
    .adder-row { gap: 7px; }
    .adder-row .digit { width: 40px; height: 44px; font-size: 21px; }
    .logic-card { padding: 10px 12px; }
    .logic-card svg { height: 56px; margin-bottom: 4px; }
    .logic-card svg.circuit { height: 88px; }
  }
  footer { max-width: 620px; margin: 0 auto; padding: 24px 16px 32px; text-align: center; font-size: 12px; color: var(--ink-3); }
  footer a { color: inherit; text-decoration: none; }
  footer a:hover { color: var(--ink-2); }
  /* It lives inside the spine now; no positioning of its own. */
  .back-home { flex: none; white-space: nowrap; text-decoration: none; color: var(--ink-2); }
  .back-home:hover { color: var(--ink); border-color: var(--blue); }

  .reading-extra,.reading-note{border-bottom:1px solid var(--line);}
  .play-extra:not([open])>:not(summary){display:none!important;}
  .reading-extra>summary,.reading-note>summary{cursor:pointer;color:var(--ink-2);padding:14px 16px 14px 72px;font-size:14px;list-style-position:inside;}
  section.post>.reading-note{grid-column:2;}.post>.reading-note>summary{padding:8px 0;font-size:13px;}
  .reading-extra .reading-extra>summary{padding-left:0;}
  .reading-note .reply{margin:0;padding:10px 0;display:block;}.reading-note .reply>.avatar{display:none;}
  .reading-finish{padding:24px 24px 26px 72px;border-bottom:1px solid var(--line);font-size:15px;}
  .reading-choices{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;}
  .reading-choices a{display:block;color:var(--ink-2);padding:10px 14px;border:1px solid var(--line-2);border-radius:24px;text-decoration:none;font-size:13px;}
  .reading-choices a:hover{color:var(--ink);border-color:var(--blue);}
  @media(max-width:600px){.reading-finish{padding:20px 16px 22px 58px}.reading-extra>summary{padding-left:58px}}

.play-header{padding:24px 24px 24px 72px;border-bottom:1px solid var(--line)}.play-header h1{font-size:28px;margin:8px 0}.play-header p{font-size:15px;color:var(--ink-2)}.play-nav{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:18px;font-size:13px}.play-nav a{color:var(--ink-2)}.play-extra>summary{padding:20px 24px 20px 72px;cursor:pointer;color:var(--ink-2);font-size:14px}.play-extra{border-top:1px solid var(--line)}@media(max-width:600px){.play-header{padding:20px 16px 20px 58px}.play-header h1{font-size:25px}.play-extra>summary{padding-left:58px}}
