/* firehose web surface — lean, readable, light/dark. No build step, no JS. */
:root {
  --bg: #fbfbf9; --fg: #1c1c1a; --muted: #6b6b63; --rule: #e4e3dd;
  --link: #1a5fb4; --accent: #b5651d; --card: #f4f3ee; --code: #efeee8;
  --maxw: 58rem;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16161a; --fg: #e6e6df; --muted: #9a9a90; --rule: #2c2c31;
    --link: #86b7ff; --accent: #e0975a; --card: #1e1e23; --code: #22222a;
  }
}
* { box-sizing: border-box; }
/* Root scale. rem-based throughout, so this is the site's zoom knob: bumping it scales
   text AND the rem measures together, keeping the ~96ch reading measure while enlarging
   the type. 20px reads as the old ~120% browser zoom, which the operator judged right. */
html { font-size: 20px; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  line-height: 1.6;
}
.topnav {
  display: flex; align-items: baseline; gap: 1.25rem; flex-wrap: wrap;
  padding: 0.85rem 1.25rem; border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; background: var(--bg); z-index: 10;
}
/* brand as a terminal prompt: firehose> #domain ▊ */
.topnav .brand {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-weight: 600; letter-spacing: -0.02em; color: var(--fg); text-decoration: none;
  display: inline-flex; align-items: baseline; gap: .12rem;
}
.topnav .brand:hover { text-decoration: none; }
.brand .b-prog  { color: var(--fg); }
.brand .b-caret { color: var(--accent); font-weight: 700; }
.brand .b-dom   { color: var(--link); }
.brand .b-cur {
  display: inline-block; width: .5ch; height: 1em; margin-left: .18rem;
  background: var(--accent); transform: translateY(.12em);
  animation: b-blink 1.1s steps(1) infinite;
}
@keyframes b-blink { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .brand .b-cur { animation: none; opacity: .55; } }
.topnav nav { display: flex; gap: 1rem; }
.topnav nav a { color: var(--muted); text-decoration: none; font-size: 0.92rem; }
.topnav nav a:hover { color: var(--link); }
main.prose { max-width: var(--maxw); margin: 2rem auto 4rem; padding: 0 1.5rem; }
/* use more screen where it's a browse surface, keep reading pages comfortable */
.page-home main.prose, .page-list main.prose { max-width: 76rem; }
/* Reading measure. The old 68rem ran ~130 characters per line — roughly double the
   comfortable range; capping it frees horizon for the rail (below) rather than stretching
   text. 48rem holds ~96ch at the 20px root, which the operator judged right by reading at
   it. (68rem was never fixable by zoom: rem scales with zoom, so the lines only shrank.) */
.page-distillate main.prose, .page-concept main.prose { max-width: 48rem; }
.prose h1 { font-size: 1.9rem; line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 1rem; }
.prose h2 { font-size: 1.3rem; margin: 2.2rem 0 0.6rem; padding-bottom: 0.2rem; border-bottom: 1px solid var(--rule); }
.prose h3 { font-size: 1.08rem; margin: 1.6rem 0 0.4rem; }
.prose a { color: var(--link); text-decoration: none; }
.prose a:hover { text-decoration: underline; }
.prose blockquote {
  margin: 1rem 0; padding: 0.5rem 1rem; border-left: 3px solid var(--accent);
  background: var(--card); color: var(--muted); border-radius: 0 4px 4px 0;
}
.prose code { background: var(--code); padding: 0.1em 0.35em; border-radius: 3px; font-size: 0.88em; }
.prose pre { background: var(--code); padding: 0.9rem; border-radius: 6px; overflow-x: auto; }
.prose pre code { background: none; padding: 0; }
.prose hr { border: none; border-top: 1px solid var(--rule); margin: 2.5rem 0; }
.prose ul { padding-left: 1.3rem; }
.prose li { margin: 0.25rem 0; }
/* altitude tags on claims (pattern→principle ontology): principle = durable truth,
   best practice = contextual/provisional, observation = noted. Scannable, colored. */
.alt {
  display: inline-block; font-size: .64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; padding: .12em .5em; border-radius: 999px; vertical-align: .1em;
  margin: 0 .12em; white-space: nowrap;
}
.alt-principle     { background: #1a5fb422; color: var(--link); }
.alt-best_practice { background: #b5651d22; color: var(--accent); }
.alt-observation   { background: var(--code); color: var(--muted); }

/* computed backlinks block */
.prose h2#linked-from { font-size: 1.05rem; color: var(--muted); border: none; }
.site-foot {
  max-width: var(--maxw); margin: 0 auto; padding: 1.5rem 1.25rem 3rem;
  border-top: 1px solid var(--rule); color: var(--muted); font-size: 0.82rem;
}
.site-foot code { background: var(--code); padding: 0.05em 0.3em; border-radius: 3px; }

/* ── source-provenance panel ─────────────────────────────────────────────
   A distillate is derived; the operator recognizes the SOURCE. Lead with it. */
.source { margin: 0 0 1.5rem; }
.source-video .thumb {
  position: relative; display: block; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--rule); line-height: 0; background: var(--card);
}
.source-video .thumb img { width: 100%; height: auto; display: block; transition: transform .3s ease; }
.source-video .thumb:hover img { transform: scale(1.02); }
.source-video .thumb .play {
  position: absolute; inset: 0; margin: auto; width: 64px; height: 64px;
  display: grid; place-items: center; font-size: 26px; color: #fff;
  background: rgba(0,0,0,.55); border-radius: 50%; padding-left: 4px;
}
.source-video .thumb .dur {
  position: absolute; right: 8px; bottom: 8px; font-size: .78rem;
  color: #fff; background: rgba(0,0,0,.8); padding: 1px 6px; border-radius: 4px;
}
.source .meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  margin-top: .6rem; font-size: .9rem; color: var(--muted);
}
.source .meta .chan { font-weight: 600; color: var(--fg); }
.source .meta .dot { color: var(--rule); }
.source .meta .out { margin-left: auto; font-weight: 600; }
.source-link { padding: .8rem 1rem; background: var(--card); border: 1px solid var(--rule); border-radius: 8px; }
.source-link .meta { margin: 0; }
.badge {
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: .12em .5em; border-radius: 4px; background: var(--code); color: var(--muted);
}
.badge-video { background: #e8443722; color: #c0392b; }
.badge-repo { background: #6e549422; color: #6e5494; }
.badge-article, .badge-paper { background: #1a5fb422; color: var(--link); }
.badge-warn { background: #e8a33d22; color: #b5651d; }

/* screengrab strip — the frames the model actually saw */
.frames { margin: 0 0 1.5rem; }
.frames > figcaption { font-size: .82rem; color: var(--muted); margin-bottom: .5rem; }
.frames .strip {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: .5rem;
}
.frames .fr { position: relative; display: block; border-radius: 6px; overflow: hidden; border: 1px solid var(--rule); line-height: 0; }
.frames .fr img { width: 100%; height: auto; display: block; aspect-ratio: 16/9; object-fit: cover; }
.frames .fr span {
  position: absolute; left: 4px; bottom: 4px; font-size: .7rem; color: #fff;
  background: rgba(0,0,0,.75); padding: 0 4px; border-radius: 3px;
}
.frames .fr:hover { outline: 2px solid var(--link); }

/* transcript — collapsed by default, no JS */
.transcript { margin: 0 0 1.75rem; border: 1px solid var(--rule); border-radius: 8px; background: var(--card); }
.transcript > summary { cursor: pointer; padding: .6rem .9rem; font-weight: 600; font-size: .9rem; color: var(--muted); }
.transcript[open] > summary { border-bottom: 1px solid var(--rule); }
.transcript .tx { max-height: 22rem; overflow-y: auto; padding: .6rem .9rem; font-size: .9rem; }
.transcript .tx p { margin: .2rem 0; }
.transcript .tx .t { display: inline-block; min-width: 3.2em; color: var(--muted); font-variant-numeric: tabular-nums; }

/* internal graph links read differently from outbound links */
.prose a[href$=".html"] { border-bottom: 1px dashed color-mix(in srgb, var(--link) 45%, transparent); }
/* outbound arrow only on prose text links (not image/thumb/frame/storyboard links) */
.prose p > a[href^="http"]::after,
.prose li > a[href^="http"]::after { content: " \2197"; font-size: .8em; opacity: .6; }

/* ── digest sort/filter control bar (progressive enhancement, JS-built) ──── */
.controls {
  display: flex; align-items: center; flex-wrap: wrap; gap: .6rem 1.1rem;
  margin: 1rem 0 .5rem; padding: .7rem .9rem; font-size: .85rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: 10px;
}
.controls .ctl { color: var(--muted); }
.controls select {
  font: inherit; color: var(--fg); background: var(--bg);
  border: 1px solid var(--rule); border-radius: 6px; padding: .2rem .4rem; margin-left: .3rem;
}
.chipgroup { display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.chiplabel { color: var(--muted); margin-right: .1rem; }
.chip {
  font: inherit; font-size: .78rem; cursor: pointer; color: var(--muted);
  background: var(--bg); border: 1px solid var(--rule); border-radius: 999px; padding: .12rem .6rem;
  text-transform: capitalize; transition: all .15s ease;
}
.chip.active { color: #fff; background: var(--link); border-color: var(--link); }
.chip:hover { border-color: var(--link); }
.ctl-count { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; }
.cardlist { display: block; }

/* home: promote the digest intro (week · budget) into a masthead band */
.page-home main.prose > blockquote {
  margin: 0 0 1.75rem; padding: .85rem 1.1rem; border-left: 3px solid var(--accent);
  background: var(--card); color: var(--fg); border-radius: 0 8px 8px 0; font-size: .92rem;
}
.page-home main.prose > blockquote p { margin: 0; }
.page-home main.prose > blockquote strong { color: var(--accent); }

/* ── This Week digest cards ───────────────────────────────────────────────
   headline + triage byline (rank · score · stance) on top; media (fixed 16:9)
   left + summary right. Summary clamps to a hook; "More" reveals the rest. */
.card { margin: 1.6rem 0; padding-bottom: 1.5rem; border-bottom: 1px solid var(--rule); }
.card > h3 { margin: 0 0 .35rem; font-size: 1.28rem; line-height: 1.25; }
.card > h3 a { color: var(--fg); border: none; }
.card > h3 a:hover { color: var(--link); }

/* triage byline: rank · score · stance — compact, scannable, not a wall of numbers */
.card > h3 + p { margin: 0 0 .85rem; display: flex; align-items: center; flex-wrap: wrap; gap: .45rem; }
.crank {
  font-weight: 800; font-size: .85rem; font-variant-numeric: tabular-nums;
  color: var(--accent); letter-spacing: -.02em;
}
.cscorechip {
  font-size: .74rem; font-weight: 700; font-variant-numeric: tabular-nums; cursor: help;
  color: var(--muted); background: var(--code); border-radius: 5px; padding: .1em .45em;
}
.cstance {
  font-size: .67rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: .14em .55em; border-radius: 999px; background: var(--code); color: var(--muted);
}
/* Resting: you reacted, so it stepped out of the ranking until its return date. Quieter than
   held (which is still competing) but never hidden — a mis-press must stay visible + reversible. */
.card.resting { opacity: .62; }
.card.resting:hover, .card.resting:focus-within { opacity: 1; }
.cverb {
  font-size: .67rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: .14em .55em; border-radius: 999px; background: var(--code); color: var(--muted);
}
.creturns { font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.stance-contradicts { background: #e8443722; color: #c0392b; }
.stance-refines     { background: #6e549422; color: #8a6db8; }
.stance-builds_on   { background: #1a5fb422; color: var(--link); }
.stance-corroborates{ background: #2f6f4f22; color: #3a9c66; }
.stance-novel       { background: #b5651d22; color: var(--accent); }
.stance-duplicates  { background: var(--code); color: var(--muted); text-decoration: line-through; }
.cnov { font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }

.cardbody { display: flex; gap: 1.3rem; align-items: flex-start; }
@media (max-width: 620px) { .cardbody { flex-direction: column; } }
/* media column: fixed width, consistent 16:9 — no more full-height stretch */
.cthumb { flex: 0 0 260px; border: none; }
.cthumb, .cthumb p, .cthumb > a { display: block; margin: 0; line-height: 0; }
.cthumb img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: 8px; border: 1px solid var(--rule); transition: filter .2s ease;
}
.cthumb:hover img { filter: brightness(1.05); }
@media (max-width: 620px) { .cthumb { flex-basis: auto; width: 100%; } }
/* quiet placeholder for media-less items (article / repo / paper): muted + typed, not a shouting block */
.cthumb .ph {
  display: flex; align-items: center; justify-content: center;
  width: 100%; aspect-ratio: 16 / 9; border-radius: 8px;
  font-weight: 700; font-size: .72rem; text-transform: uppercase; letter-spacing: .07em;
  background: var(--card); border: 1px solid var(--rule); border-left: 3px solid var(--muted);
}
.ph-repo    { color: #8a6db8; border-left-color: #8a6db8; }
.ph-article { color: var(--link); border-left-color: var(--link); }
.ph-paper   { color: #3a9c66; border-left-color: #3a9c66; }
.ph-video   { color: #c0392b; border-left-color: #c0392b; }
.ph:hover { border-color: var(--muted); }

/* summary: capped measure, clamped to a hook until "More" (progressive enhancement) */
.csum { flex: 1 1 auto; min-width: 0; position: relative; }
.csum > p { margin: 0 0 .6rem; max-width: 42rem; }
.csum.clamp { max-height: 7.8em; overflow: hidden; }
.card.open .csum.clamp { max-height: none; }
.csum.clamp::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2.6em;
  background: linear-gradient(transparent, var(--bg)); pointer-events: none;
}
.card.open .csum.clamp::after { display: none; }
.card-more {
  font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer; margin-top: .35rem;
  color: var(--link); background: none; border: none; padding: .1rem 0;
}
.card-more:hover { text-decoration: underline; }

/* reaction bar: quiet until you want it. The verbs damp a real score factor, so they read as
   restrained text buttons, not calls to action — nothing here should invite a reflex press.
   `wrong` is the only one tinted, because it flags the distillate for re-distill. */
.creact {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin: .8rem 0 0; padding-top: .6rem; border-top: 1px dashed var(--rule);
  opacity: .55; transition: opacity .15s ease;
}
.card:hover .creact, .card:focus-within .creact { opacity: 1; }
.rbtn {
  font: inherit; font-size: .74rem; cursor: pointer; color: var(--muted);
  background: var(--bg); border: 1px solid var(--rule); border-radius: 999px;
  padding: .12rem .6rem;
}
.rbtn:hover:not(:disabled) { color: var(--fg); border-color: var(--link); }
.rbtn:disabled { cursor: default; opacity: .5; }
.rbtn-wrong:hover:not(:disabled) { color: #c0392b; border-color: #c0392b; }
.rbtn-reset { border-style: dashed; }
.creact-msg { font-size: .74rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* end-of-read reaction box on the distillate page — where the *content* verdict is earned.
   Unlike the card bars (hover-revealed triage), this is a settled prompt: fully visible,
   because you got here by reading. The verbs still read as restrained text buttons. */
.creact-page {
  margin: 2.75rem 0 0; padding: 1rem 1.1rem;
  border: 1px solid var(--rule); border-radius: 10px; background: var(--card);
}
.creact-head {
  margin: 0 0 .55rem; font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted);
}
.creact-page .creact { margin: 0; padding: 0; border: none; opacity: 1; }

/* Stars — the one POSITIVE signal, marked where it was earned (star primitive, phase 2).
   A star DAMPS nothing; it amplifies relevance, so it reads as a quiet accent, not a chrome.
   A restrained left margin-rule beside an emphasised passage; a noted star hangs a ★ in the
   margin and shows its note on hover. Orphaned stars (quote no longer matches after a re-distill)
   get a loud notice at the top of the read — flagged, never dropped (mirror of the build log). */
.fh-starred {
  position: relative;
  border-left: 2px solid var(--accent);
  padding-left: .9rem;
  margin-left: -1.1rem;          /* pull the rule into the margin so the text stays on the measure */
}
.fh-noted { cursor: help; }
.fh-noted::before {
  content: "★"; position: absolute; left: -1.55rem; top: 0;
  color: var(--accent); font-size: .72em; line-height: 1.9;
}
.fh-orphans {
  margin: 0 0 1.6rem; padding: .7rem .95rem;
  border: 1px solid var(--accent); border-radius: 10px; background: var(--card);
  font-size: .85rem;
}
.fh-orphans-head {
  margin: 0 0 .35rem; font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--accent);
}
.fh-orphan { margin: .25rem 0; color: var(--muted); }

/* Star widget (phase 3) — the floating affordance a prose selection raises. A small popover
   pinned near the selection (position:fixed, placed by JS); accent-bordered because it belongs to
   the positive gesture, matching the ★ margin-rule it will draw. The note field is optional and
   the button reads as the same restrained text-button as the reaction verbs. */
.fh-starpop {
  position: fixed; z-index: 40; display: flex; align-items: center; gap: .4rem;
  padding: .35rem .4rem; background: var(--card);
  border: 1px solid var(--accent); border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
}
.fh-starpop-note {
  font: inherit; font-size: .78rem; color: var(--fg);
  background: var(--bg); border: 1px solid var(--rule); border-radius: 5px;
  padding: .18rem .45rem; width: 13rem; max-width: 40vw;
}
.fh-starpop-note::placeholder { color: var(--muted); }
.fh-starpop-go {
  font: inherit; font-size: .76rem; white-space: nowrap; cursor: pointer;
  color: var(--accent); background: var(--bg);
  border: 1px solid var(--accent); border-radius: 999px; padding: .12rem .7rem;
}
.fh-starpop-go:hover:not(:disabled) { color: var(--bg); background: var(--accent); }
.fh-starpop-go:disabled { cursor: default; opacity: .5; }
.fh-starpop-undo { color: var(--muted); border-color: var(--rule); border-style: dashed; }
.fh-starpop-undo:hover:not(:disabled) { color: var(--fg); background: var(--bg); }
.fh-starpop-msg { font-size: .76rem; color: var(--muted); }

/* concepts as pills, not a run-on of underlined links */
.cconcepts { font-size: .8rem; color: var(--muted); margin: .8rem 0 0; line-height: 2; }
.cconcepts a {
  display: inline-block; color: var(--muted); background: var(--code);
  border: 1px solid var(--rule); border-radius: 999px; padding: .06em .55em; margin: 0 .2rem .25rem 0;
}
.cconcepts a:hover { color: var(--link); border-color: var(--link); text-decoration: none; }

/* held cards: over the attention budget — rendered in full, but denser + quieter so the
   Surfaced/Held triage hierarchy still reads (demoted, not dropped — no silent caps) */
.page-home main.prose > h2#held { margin-top: 3rem; }
.card.held { margin: 1.1rem 0; padding-bottom: 1.1rem; }
.card.held > h3 { font-size: 1.08rem; }
.card.held > h3 a { color: var(--muted); }
.card.held > h3 a:hover { color: var(--link); }
.card.held .cthumb { flex: 0 0 168px; }
.card.held .csum > p { font-size: .94rem; }
.card.held .csum.clamp { max-height: 4.8em; }      /* tighter hook than surfaced */
.card.held .cconcepts { margin-top: .5rem; }
/* scoring notes + held: demoted, still visible (no silent caps) */
.scoringnotes { margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--rule); font-size: .82rem; color: var(--muted); }
.scoringnotes h2 { font-size: 1rem; border: none; }

/* ── storyboard carousel: one frame at a time, click ‹ › to page ──────────── */
.storyboard { margin: 1.5rem 0 2rem; }
.storyboard > h2 { font-size: 1.15rem; }
.carousel .track {
  display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  border: 1px solid var(--rule); border-radius: 10px; background: var(--card);
}
.carousel .shot {
  flex: 0 0 100%; scroll-snap-align: center; margin: 0; padding: 1.3rem;
  display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; align-items: start;
}
@media (max-width: 640px) { .carousel .shot { grid-template-columns: 1fr; } }
.carousel .shot-img { display: block; line-height: 0; border: none; }
.carousel .shot-img img { width: 100%; border-radius: 8px; border: 1px solid var(--rule); cursor: zoom-in; }
.carousel .shot-tx { margin: 0; font-size: 1rem; line-height: 1.6; }
.shot-nav { display: flex; align-items: center; gap: .6rem; margin-top: .9rem; }
.shot-nav .nav {
  font-size: 1.2rem; line-height: 1; text-decoration: none; color: var(--fg);
  border: 1px solid var(--rule); border-radius: 6px; padding: .1rem .5rem; background: var(--bg);
}
.shot-nav .nav:hover { border-color: var(--link); color: var(--link); }
.shot-nav .pos { font-size: .8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.shot-nav .shot-jump { margin-left: auto; font-size: .8rem; color: var(--muted); border: none; }
.shot-nav .shot-jump:hover { color: var(--link); }

/* CSS-only lightbox (no JS): the shot links to #lb-…, which this :target reveals */
.lightbox {
  display: none; position: fixed; inset: 0; z-index: 100; padding: 2.5vh 2.5vw;
  background: rgba(0,0,0,.92); place-items: center; border: none;
}
.lightbox:target { display: grid; }
.lightbox img { max-width: 95vw; max-height: 95vh; border-radius: 6px; }
.lightbox::after {
  content: "\00d7 close"; position: fixed; top: 1rem; right: 1.5rem;
  color: #fff; font-size: 1rem; opacity: .8;
}

/* --- reading rail (distillate + concept pages) ---------------------------- */
/* The measure is capped at 48rem, so on a wide screen the leftover horizon is dead
   margin. Spend it on navigation that stays put — sections you can jump to without
   scrolling to find them. JS wraps main.prose in .reading and appends the rail; with
   no JS the page is exactly what it was, a centred column. */
.reading { max-width: 64rem; margin: 2rem auto 4rem; padding: 0 1.5rem; }
.reading main.prose { max-width: none; margin: 0; padding: 0; }
@media (min-width: 62rem) {
  .reading { display: grid; grid-template-columns: minmax(0, 48rem) 15rem; gap: 3rem; align-items: start; }
}
/* Below 62rem — a split pane, a laptop, a phone — the rail would steal from the
   measure it exists to protect. Drop it; the headings are still in the body. */
@media (max-width: 61.99rem) { .rail { display: none; } }

.rail { position: sticky; top: 1.5rem; align-self: start; font-size: .84rem; line-height: 1.45; }
.rail h2 {
  font: inherit; font-size: .68rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); margin: 0 0 .6rem; padding: 0 0 .4rem; border-bottom: 1px solid var(--rule);
}
.rail ol { list-style: none; margin: 0; padding: 0; }
.rail li { margin: 0; }
.rail a {
  display: block; padding: .28rem .5rem; margin-left: -.5rem; border-radius: 4px;
  color: var(--muted); text-decoration: none; border-left: 2px solid transparent;
}
.rail a:hover { color: var(--link); background: var(--card); }
.rail a.here { color: var(--fg); border-left-color: var(--accent); }
.rail a:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
/* rail groups: Concepts (pills) · On this page (index + scrollspy) · Linked from (list).
   Concepts + backlinks are navigation, so they live here — mirrored from the body, not
   moved (the body copies survive for no-JS + the narrow width where the rail is hidden). */
.rail-group + .rail-group { margin-top: 1.6rem; }
.rail ul { list-style: none; margin: 0; padding: 0; }
.rail .pills { display: flex; flex-wrap: wrap; gap: .3rem; }
.rail .pills a {
  display: inline-block; margin: 0; padding: .1em .55em; border-radius: 999px;
  color: var(--muted); background: var(--code); border: 1px solid var(--rule);
}
.rail .pills a:hover { color: var(--link); background: var(--card); border-color: var(--link); }
/* When the rail is present it mirrors "Linked from"; drop the redundant body copy — but
   ONLY at the width where the rail actually shows (below it, the body copy is all there is). */
@media (min-width: 62rem) { .reading .lifted { display: none; } }

/* --- toggle headings (distillate + concept pages) ------------------------- */
/* progressive enhancement: surface.js turns each h2 into a collapsible section.
   No JS → plain headings, full text (no content hidden on load). */
.prose h2.toggle {
  cursor: pointer; user-select: none; position: relative; padding-left: 1.15em;
}
.prose h2.toggle::before {
  content: "\25BE"; position: absolute; left: 0; top: .06em;
  color: var(--muted); font-size: .78em; transition: transform .15s ease;
}
.prose h2.toggle.collapsed::before { transform: rotate(-90deg); }
.prose h2.toggle:hover { color: var(--link); }
.prose h2.toggle:hover::before { color: var(--link); }
.prose h2.toggle:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; border-radius: 3px; }
.toggle-body { }
.prose h2.toggle.collapsed + .toggle-body { display: none; }

/* --- concept graph (graph.html) ------------------------------------------ */
.page-graph main.prose { max-width: none; margin: 0; padding: 0; }
.graphview {
  width: 100%; height: calc(100vh - 3.6rem); min-height: 30rem;
  background:
    radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--card) 55%, transparent), transparent 70%),
    var(--bg);
}
.graph-controls {
  position: absolute; top: 4.4rem; left: 1rem; z-index: 5;
  display: flex; flex-direction: column; gap: .5rem;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border: 1px solid var(--rule); border-radius: 10px; padding: .7rem .8rem;
  backdrop-filter: blur(6px); max-width: 15rem; font-size: .82rem;
}
.graph-controls .gc-title { font-weight: 700; letter-spacing: -.01em; margin: 0 0 .1rem; }
.graph-controls .gc-hint { color: var(--muted); font-size: .74rem; margin: 0; }
.graph-controls .gc-group { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .15rem; }
.graph-controls .gc-lab { color: var(--muted); font-size: .68rem; text-transform: uppercase; letter-spacing: .06em; width: 100%; }
.gchip {
  border: 1px solid var(--rule); background: var(--card); color: var(--fg);
  border-radius: 999px; padding: .12em .6em; font-size: .74rem; cursor: pointer;
  display: inline-flex; align-items: center; gap: .32em;
}
.gchip .sw { width: .62em; height: .62em; border-radius: 3px; display: inline-block; }
.gchip.off { opacity: .4; text-decoration: line-through; }
.gchip:hover { border-color: var(--muted); }
.graph-controls input.gsearch {
  width: 100%; padding: .3em .5em; border: 1px solid var(--rule); border-radius: 6px;
  background: var(--bg); color: var(--fg); font-size: .8rem;
}
.graph-empty { padding: 3rem 1.5rem; color: var(--muted); text-align: center; max-width: 40rem; margin: 0 auto; }
