/* layout.css — Affine.Earth, ONE responsive system (Release 6, 2026-10-01). The card: docs/AFFINE_LAYOUT.md.
 *
 * ONE FILE FOR EVERY SERVED PAGE. On 2026-10-02 no served page loads it: the pages that link ui.css are to
 * get it by an @import on ui.css line 1, every other page (atlas too) by a <link> before its own <style>.
 * No build step, no network font.
 * Layout is CSS: every default below holds with no script. Delivery JavaScript only sizes surfaces (surface.js),
 * records the visitor's choice (data-observer="open|closed" on .page) and tells the shell a hosted page's shape.
 * It computes no verdict and never writes a pixel of a law's frame.
 *
 * SIZE CLASSES — up as well as down, each with its reason:
 *   phone   <  640    one column; the rail is a folded drawer; Franklin is a bottom sheet in its own grid row;
 *                     main is the one scroller between the bar and the sheet.
 *   narrow  640–1023  one column; a stage gets 48dvh (the 768 stage gave its projection 80 px of 1024).
 *   laptop  1024–1439 the first width that holds a 280 px rail + 72ch of 16 px + a 44 px observer tab.
 *   desk    1440–1919 the rail grows with the width (22vw); the tab stays folded.
 *   wide    1920–2559 Franklin's column is open unless the visitor closed it: 82–96 % of these screens were empty.
 *   ultra   >= 2560   the ONE large-screen type step.
 *   ultrawide shape   no media query: the reading column sits beside its figure when MAIN is 80rem wide (a
 *                     container query).
 *   wall    a visitor's choice (localStorage "affine.density"), never a query: CSS cannot tell a 34-inch
 *           ultrawide at 1 dppx from a television at 1 dppx.
 */

:root {
  color-scheme: dark light;

  /* palette — ui.css :root's literals (and the Mac app's colour enum): dark renders the same RGB as before */
  --bg: #070b15; --surface: #0e1526; --surface-2: #0b1020;
  --line: #1d2a46; --line-soft: rgba(255,255,255,0.06);
  --ink: #f1f6fb; --ink-2: #9eb0cc; --ink-3: #6b7d99;
  --accent: #6bb3ff; --accent-2: #b394ff; --cyan: #54d9f5; --mint: #6be3b0; --amber: #fac261; --rose: #fa859e;
  --on-accent: #04121a;

  /* fonts — system stacks covering the scripts of all 25 languages; nothing waits for a network */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Helvetica Neue", Arial,
          "Noto Sans Arabic", "Geeza Pro", "Noto Sans Hebrew", "Arial Hebrew", "Noto Nastaliq Urdu",
          "Noto Sans Devanagari", "Kohinoor Devanagari", "Nirmala UI", "Noto Sans Bengali", "Kohinoor Bangla",
          "Noto Sans Thai", "Thonburi", "Leelawadee UI", "PingFang SC", "Microsoft YaHei", "Hiragino Sans",
          "Yu Gothic UI", "Apple SD Gothic Neo", "Malgun Gothic", Tahoma, sans-serif;
  --serif: ui-serif, "Iowan Old Style", Georgia, "Noto Serif", "Times New Roman", serif;
  --mono: ui-monospace, Menlo, Consolas, "Noto Sans Mono", monospace;

  /* type — fluid, bounded at BOTH ends; one step at >= 2560 (below). px at 390 / 1440 / 1920 / 2560+ */
  --fs-small: clamp(0.75rem,  0.7rem  + 0.2vw,  0.875rem);   /* 12  / 14   / 14   / 15 */
  --fs-ui:    clamp(0.8125rem,0.75rem + 0.25vw, 1rem);       /* 13  / 15.6 / 16   / 17 */
  --fs-body:  clamp(1rem,     0.85rem + 0.25vw, 1.25rem);    /* 16  / 17.2 / 18.4 / 21 */
  --fs-h3:    clamp(1.125rem, 1rem    + 0.5vw,  1.5rem);     /* 18  / 23.2 / 24   / 26 */
  --fs-h2:    clamp(1.375rem, 1.1rem  + 0.9vw,  2.25rem);    /* 22  / 30.6 / 34.9 / 40 */
  --fs-h1:    clamp(1.75rem,  1.2rem  + 1.6vw,  3rem);       /* 28  / 42.2 / 48   / 52 */
  --fs-hero:  clamp(2.125rem, 1.25rem + 2.8vw,  4.5rem);     /* 34  / 60.3 / 72   / 80 */
  --lh: 1.6; --lh-tight: 1.08;

  /* spacing — rem, one scale */
  --sp-1: .25rem; --sp-2: .5rem; --sp-3: .75rem; --sp-4: 1rem; --sp-5: 1.5rem; --sp-6: 2rem; --sp-7: 3rem; --sp-8: 4rem;
  --gutter: clamp(1rem, 2vw, 3rem);
  --radius: 14px; --radius-sm: 8px;
  --safe-s: env(safe-area-inset-left, 0px); --safe-e: env(safe-area-inset-right, 0px);   /* inline start / end */

  /* the grid */
  --bar: 3.5rem;                                   /* 56 px, every page, every width */
  --rail: clamp(17.5rem, 22vw, 26.25rem);          /* 280 → 420 px: the column that froze at 300–380 px */
  --observer: 0px;                                 /* Franklin's column: 0 on phones, a 44 px tab, then open */
  --observer-open: clamp(18rem, 18vw, 26rem);      /* 288 → 416 px */
  --observer-tab: 2.75rem;                         /* 44 px */
  --reading: 72ch;                                 /* the reading measure — INSIDE main, never a page cap */
  --stage-max-h: calc(100dvh - var(--bar) - 7rem); /* a stage never outgrows the screen under the bar */
  --strip-h: 3.25rem;                              /* the phone sheet, closed: 52 px */
  --tap: 36px;                                     /* fine pointers at >= 1024 (WCAG 2.5.8 floor is 24) */
}
@media (pointer: coarse), (max-width: 1023.98px) { :root { --tap: 44px; } }
[dir="rtl"] { --safe-s: env(safe-area-inset-right, 0px); --safe-e: env(safe-area-inset-left, 0px); }

/* light — ui.css's light literals. A page that still writes its own dark colours carries data-theme="dark" */
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { color-scheme: light;
  --bg: #f4f6fa; --surface: #ffffff; --surface-2: #eef1f7; --line: #dfe4ee; --line-soft: rgba(15,23,42,0.06);
  --ink: #131a26; --ink-2: #4a5670; --ink-3: #75809a; --accent: #1d4ed8; --accent-2: #6d3fd4; --cyan: #0e7490;
  --mint: #047857; --amber: #a16207; --rose: #be123c; --on-accent: #ffffff; } }
:root[data-theme="light"] { color-scheme: light;
  --bg: #f4f6fa; --surface: #ffffff; --surface-2: #eef1f7; --line: #dfe4ee; --line-soft: rgba(15,23,42,0.06);
  --ink: #131a26; --ink-2: #4a5670; --ink-3: #75809a; --accent: #1d4ed8; --accent-2: #6d3fd4; --cyan: #0e7490;
  --mint: #047857; --amber: #a16207; --rose: #be123c; --on-accent: #ffffff; }

/* the ONE large-screen step (ultra) */
@media (min-width: 2560px) {
  :root { --fs-small: .9375rem; --fs-ui: 1.0625rem; --fs-body: 1.3125rem; --fs-h3: 1.625rem; --fs-h2: 2.5rem;
          --fs-h1: 3.25rem; --fs-hero: 5rem; --gutter: 3rem; }
}
/* the wall — the visitor's toggle; every size at or past the top of its scale (body 22, hero 88, targets 56 px) */
:root[data-density="wall"] { --fs-small: 1rem; --fs-ui: 1.125rem; --fs-body: 1.375rem; --fs-h3: 1.75rem;
  --fs-h2: 2.75rem; --fs-h1: 3.5rem; --fs-hero: 5.5rem; --tap: 56px; --reading: 80ch; --observer-open: 30rem; --rail: 30rem; }

/* ── base ── */
*, *::before, *::after { box-sizing: border-box; }
html { font-size: 100%; -webkit-text-size-adjust: 100%; }   /* rem is the visitor's own setting */
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 var(--fs-body)/var(--lh) var(--font); }
h1, h2, h3 { margin: 0; line-height: var(--lh-tight); letter-spacing: -.015em; font-weight: 700; }
h1 { font-size: var(--fs-h1); } h2 { font-size: var(--fs-h2); } h3 { font-size: var(--fs-h3); }
p { margin: 0 0 var(--sp-4); }
a { color: var(--accent); }
small, .small { font-size: var(--fs-small); }
.ui { font-size: var(--fs-ui); }
.mono, code, kbd, samp, .digest, .receipt { font-family: var(--mono); }
img, video, svg, canvas, iframe { max-inline-size: 100%; }
:is(.figure, .stage, .portrait) :is(img, video, canvas, iframe) { display: block; }
/* fillText inherits direction: under dir=rtl a label drawn at x=6 ran off the edge (measured) */
canvas { direction: ltr; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* scripts that need more leading than Latin — on BODY under the ROOT's language only: the per-element form
   gave the hero's inline span 105.56 px of leading inside a 62.73 px heading */
:root:is(:lang(ar), :lang(ur), :lang(fa), :lang(he)) body { line-height: 1.75; }
:root:is(:lang(th), :lang(hi), :lang(bn)) body { line-height: 1.8; }
:root:is(:lang(ar), :lang(ur), :lang(fa)) body { font-size: calc(var(--fs-body) * 1.04); }

/* a line not yet in the page's language keeps its own direction in a right-to-left page */
[dir="rtl"] :is(p, li, h1, h2, h3, dd, dt, figcaption, summary, .lede, .say, button, .btn, .chip, .stage-caption > span, .say-short) { unicode-bidi: plaintext; }
/* machine facts keep their own order in any direction */
:is(.receipt, .digest, code, kbd, samp) { unicode-bidi: isolate; }

/* an unbreakable token never widens a column */
code, kbd, td, dd, .digest, .receipt, .wrap-any { overflow-wrap: anywhere; }
.table-scroll { inline-size: 100%; overflow-x: auto; overscroll-behavior-x: contain; }
.table-scroll table { min-inline-size: 100%; border-collapse: collapse; }
.digest, .receipt { font-size: var(--fs-small); color: var(--ink-2); }

/* ── the page grid ── */
.page {
  display: grid;
  min-block-size: 100dvh;
  grid-template-columns: [full-start] var(--gutter) [main-start] minmax(0, 1fr) [main-end] var(--gutter) [full-end];
  grid-template-rows: var(--bar) auto 1fr auto;
  grid-template-areas: "bar bar bar" ". rail ." ". main ." "strip strip strip";
}
.bar { grid-area: bar; }
.rail { grid-area: rail; min-inline-size: 0; }
.main { grid-area: main; min-inline-size: 0; }
.observer { grid-area: strip; min-inline-size: 0; }

/* phone + narrow: one column; MAIN is the one scroller between the bar and Franklin's sheet. The lock is only for
   a document that HOLDS the grid: unscoped, a page that merely linked this file could not scroll (measured) */
@media (max-width: 1023.98px) {
  :where(html:has(.page)), :where(html:has(.page)) > body { block-size: 100dvh; overflow: hidden; }
  .page { block-size: 100dvh; grid-template-rows: var(--bar) auto minmax(0, 1fr) auto; }
  .main { overflow: auto; overscroll-behavior: contain; padding-inline: var(--safe-s) var(--safe-e); }
  .rail-drawer { margin-block: var(--sp-2) 0; }
  .rail-drawer:not(:has(.rail-check:checked)) > .rail-body { display: none; }
  /* open: half the screen at most, and never more than the bar, the row, 9rem and the folded sheet leave */
  .rail-drawer > .rail-body { overflow: auto;
    max-block-size: max(3rem, min(50dvh, 100dvh - var(--bar) - var(--strip-h) - var(--tap) - 9rem)); }
  .bar .brand-sub { display: none; }
  .bar select { max-inline-size: 8.5rem; }
}

/* laptop and up: rail · main · observer; the DOCUMENT scrolls; bar and observer stick */
@media (min-width: 1024px) {
  :root { --observer: var(--observer-tab); --gutter: clamp(1.25rem, 2vw, 3rem); }
  .page {
    grid-template-columns: [full-start] var(--gutter) [rail-start] var(--rail) [rail-end main-start] minmax(0, 1fr)
                           [main-end observer-start] var(--observer) [observer-end] var(--gutter) [full-end];
    grid-template-rows: var(--bar) 1fr;
    grid-template-areas: "bar bar bar bar bar" ". rail main observer .";
    column-gap: 0;
  }
  .main { padding-inline: var(--sp-6); }
  .rail { align-self: start; }
  .page[data-observer="open"] { --observer: var(--observer-open); }
  .observer { grid-area: observer; position: sticky; inset-block-start: var(--bar); align-self: start; max-block-size: calc(100dvh - var(--bar)); }
}
@media (min-width: 1920px) { .main { padding-inline: var(--sp-7); }
  .page:not([data-observer="closed"]) { --observer: var(--observer-open); } }

/* ── the bar: 56 px, one row, never wraps; what does not fit is in More ── */
.bar { display: flex; align-items: center; gap: var(--sp-3); block-size: var(--bar);
  padding-inline: max(var(--gutter), var(--safe-s)) max(var(--gutter), var(--safe-e));
  background: color-mix(in srgb, var(--bg) 90%, transparent); border-block-end: 1px solid var(--line);
  position: sticky; inset-block-start: 0; z-index: 30; backdrop-filter: blur(10px); }
.bar .brand { display: inline-flex; align-items: center; min-block-size: var(--tap); font-weight: 800; letter-spacing: -.02em;
  font-size: var(--fs-h3); white-space: nowrap; color: var(--ink); text-decoration: none; }
.bar .brand .dot { color: var(--mint); }
/* the brand is a Latin name: its three children read 'Earth.Affine' under dir=rtl (measured) */
.bar .brand { direction: ltr; unicode-bidi: isolate; }
.bar .brand-sub { color: var(--ink-3); font-size: var(--fs-small); white-space: nowrap; }
.bar-nav { display: flex; gap: var(--sp-1); flex: 1 1 auto; min-inline-size: 0; overflow: hidden; }
.bar-nav > a { white-space: nowrap; flex: 0 0 auto; padding: 0 .9em; border-radius: 999px; color: var(--ink-2);
  font-size: var(--fs-ui); text-decoration: none; min-block-size: var(--tap); display: inline-flex; align-items: center; }
.bar-nav > a:hover, .bar-nav > a[aria-current] { color: var(--ink); background: var(--surface); }
/* the count that fits per class; More holds every entry. 7 at 1440: 6 left 341 px of the nav empty */
.bar-nav > a { display: none; }
@media (min-width: 640px)  { .bar-nav > a:nth-child(-n+2) { display: inline-flex; } }
@media (min-width: 1024px) { .bar-nav > a:nth-child(-n+4) { display: inline-flex; } }
@media (min-width: 1440px) { .bar-nav > a:nth-child(-n+7) { display: inline-flex; } }
@media (min-width: 1920px) { .bar-nav > a:nth-child(-n+9) { display: inline-flex; } }
.bar-end { display: flex; align-items: center; gap: var(--sp-2); flex: 0 0 auto; margin-inline-start: auto; }
.bar select, .bar .btn { min-block-size: var(--tap); font: inherit; font-size: var(--fs-ui); color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding-inline: .9em; }
.more { position: relative; }
.more > summary { list-style: none; cursor: pointer; min-block-size: var(--tap); min-inline-size: var(--tap); display: inline-flex;
  align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
  font-size: var(--fs-ui); padding-inline: .8em; white-space: nowrap; }
.more > summary::-webkit-details-marker { display: none; }
.more-menu { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 6px); min-inline-size: 16rem;
  max-inline-size: min(22rem, 92vw); max-block-size: calc(100dvh - var(--bar) - 1rem); overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--sp-2);
  display: grid; gap: 2px; z-index: 40; box-shadow: 0 20px 50px rgba(0,0,0,.45); }
.more-menu a, .more-menu button { display: flex; align-items: center; min-block-size: var(--tap); padding-inline: .8em;
  border-radius: var(--radius-sm); color: var(--ink); text-decoration: none; font-size: var(--fs-ui); background: none;
  border: 0; text-align: start; font-family: inherit; }
.more-menu a:hover { background: var(--surface-2); }
.more-menu .group { font-size: var(--fs-small); color: var(--ink-3); text-transform: uppercase; letter-spacing: .08em; padding: var(--sp-2) .8em 2px; }

/* ── the rail: the product's map, on the width scale; it flows (never a second scroller) ── */
.rail { padding-block: var(--sp-5); font-size: var(--fs-ui); }
.rail-drawer { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
/* the drawer needs no script: its row is a label over a checkbox; below 1024 the body shows only while it is
   checked (the phone block above); from 1024 the row goes and the body always shows */
.rail-summary { position: relative; padding-inline: var(--sp-4); min-block-size: var(--tap); display: flex; align-items: center; font-weight: 600; }
.rail-check { appearance: none; position: absolute; inset-block: 0; inset-inline: 0; margin: 0; cursor: pointer; border-radius: var(--radius); }
.rail-drawer > .rail-body { padding: var(--sp-3) var(--sp-4); }
@media (min-width: 1024px) { .rail-summary { display: none; } }
.rail h2 { font-size: var(--fs-small); letter-spacing: .08em; text-transform: uppercase; color: var(--mint); margin: var(--sp-5) 0 var(--sp-2); }
.rail h2:first-child { margin-block-start: 0; }
.rail ul { list-style: none; margin: 0; padding: 0; }
.rail li a { display: flex; align-items: center; min-block-size: var(--tap); padding-inline: .6em; border-radius: var(--radius-sm);
  color: var(--ink-2); text-decoration: none; border-inline-start: 2px solid transparent; }
.rail li a:hover { color: var(--ink); background: var(--surface-2); border-inline-start-color: var(--accent); }
.rail li a.lead { color: var(--ink); font-weight: 600; }
.rail details > summary { cursor: pointer; font-size: var(--fs-small); color: var(--ink-3); min-block-size: var(--tap); display: flex; align-items: center; }
/* A link standing alone in a list item of a rendered page, and every link in Franklin's strip, keep the same tap floor
   as the rail (WCAG 2.5.8). Measured 2026-10-03 on hel-00 after the Release 6 ship: the strip's "game context ↗" at
   76 × 15 px and a rendered wiki list link at 305 × 21 px were the only front-door targets under the floor. */
.main li > a, #companion-strip a { display: inline-flex; align-items: center; min-block-size: var(--tap); }
/* A link inside running text keeps its line: vertical padding on an inline box widens what the pointer can hit (and
   what getBoundingClientRect reports) without moving the line box. Measured on nbg-00 the same day: a paragraph link
   "Affine.Earth × Affine IDE β" at 305.1 × 21 px in the front door's shuffled wiki page. */
.main :is(p, td, th, dd, figcaption, blockquote) a { padding-block: .15em; }
.rail .facts { display: grid; gap: var(--sp-1); margin: 0; }
.portrait { margin: 0 0 var(--sp-2); aspect-ratio: 4 / 5; display: grid; place-items: center; background: #000; border-radius: var(--radius-sm); overflow: hidden; }
.portrait-cap { color: var(--ink-3); margin-block-end: var(--sp-5); }
.rail .facts dt { color: var(--ink-3); font-size: var(--fs-small); }
.rail .facts dd { margin: 0 0 var(--sp-2); color: var(--ink); }

/* ── main: the reading measure inside; stages, cards, tables and galleries span ── */
.main { padding-block: var(--sp-5) var(--sp-8); }
.reading, .main > p, .main .lede { max-inline-size: var(--reading); }
.eyebrow { letter-spacing: .2em; font-size: var(--fs-small); font-weight: 700; color: var(--accent); text-transform: uppercase; }
.hero { font-size: var(--fs-hero); max-inline-size: 17ch; line-height: 1.04; letter-spacing: -.025em; margin-block: var(--sp-4) 0; }
.hero .grad { background: linear-gradient(90deg, var(--mint), var(--accent)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.lede { font-size: calc(var(--fs-body) * 1.12); color: var(--ink-2); margin-block: var(--sp-4) 0; }
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-block: var(--sp-3) 0; }
.chip { display: inline-flex; align-items: center; min-block-size: var(--tap); padding-inline: .9em; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); font: inherit; font-size: var(--fs-ui); cursor: pointer; }
.chip.on { background: linear-gradient(90deg, var(--mint), var(--accent)); color: var(--on-accent); border-color: transparent; font-weight: 700; }
.card { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); padding: var(--sp-4); container: card / inline-size; }
.cards { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); margin-block: var(--sp-5) 0; }
.card h3 { margin-block-end: var(--sp-2); }
.card .row { display: grid; gap: var(--sp-2); }
@container card (min-width: 28rem) { .card .row { grid-template-columns: 1fr auto; align-items: center; } }
.field { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.field input { flex: 1 1 12rem; min-inline-size: 0; min-block-size: var(--tap); font: inherit; font-size: var(--fs-ui); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding-inline: .8em; }
.btn { display: inline-flex; align-items: center; justify-content: center; min-block-size: var(--tap); min-inline-size: var(--tap);
  padding-inline: 1em; border-radius: 10px; border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font: inherit; font-size: var(--fs-ui); cursor: pointer; text-decoration: none; }
.btn.primary { background: linear-gradient(90deg, var(--mint), var(--accent)); color: var(--on-accent); font-weight: 700; border-color: transparent; }

/* the reading column beside its figure WHEN MAIN ITSELF IS WIDE ENOUGH — a container query (measured: at 1920
   with the observer open a media rule left the figure 200 px wide). The grid is an inner .lead-figure, never
   main itself: a container query styles descendants */
.main { container: main / inline-size; }
@container main (min-width: 80rem) {
  .lead-figure { display: grid; grid-template-columns: minmax(0, var(--reading)) minmax(0, 1fr); column-gap: var(--sp-7); align-items: start; }
  .lead-figure > * { grid-column: 1; }
  .lead-figure > .figure { grid-column: 2; grid-row: 1 / span var(--lead-rows, 6); position: sticky; inset-block-start: calc(var(--bar) + var(--sp-4)); margin-block: 0; }
  .lead-figure > .span-all { grid-column: 1 / -1; }
}
.figure { margin: var(--sp-5) 0 0; }
.figure img { inline-size: 100%; block-size: auto; border-radius: var(--radius); border: 1px solid var(--line); }
.figure canvas { border-radius: var(--radius); outline: 1px solid var(--line); outline-offset: -1px; }   /* an outline: a border would take 2 px from the picture */
.figure figcaption { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); padding-block: var(--sp-2); font-size: var(--fs-small); color: var(--ink-2); }

/* ── stages: the verified frame fills its box at an integer scale; the law's bytes are untouched ── */
.stage-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-6); }
.stage-head .lede { margin: 0; flex: 1 1 32ch; }
.stage { position: relative; inline-size: 100%; margin-block: var(--sp-4) 0; border: 1px solid var(--line); border-radius: var(--radius);
  background: #000; overflow: hidden; display: grid; place-items: center; container: stage / inline-size;
  block-size: clamp(14rem, var(--stage-h, 60dvh), var(--stage-max-h)); }
/* a declared surface takes the size surface.js measured; until then it is as wide as its box */
canvas[data-surface] { inline-size: var(--surface-w, 100%); block-size: var(--surface-h, auto); }
canvas[data-surface="frame"] { image-rendering: pixelated; }
iframe[data-surface] { inline-size: 100%; border: 0; }
.stage-caption { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); align-items: center; padding-block: var(--sp-2); font-size: var(--fs-small); color: var(--ink-2); }
.stage-controls { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-block: var(--sp-3) 0; }
@media (max-width: 639.98px) { .stage { --stage-h: 56dvh; } }
@media (min-width: 640px) and (max-width: 1023.98px) { .stage { --stage-h: 48dvh; } }
/* stage pages below 1024: title, frame, caption, controls; the lede folds to two lines */
@media (max-width: 1023.98px) {
  .page[data-shape="stage"] .main { display: flex; flex-direction: column; }
  .page[data-shape="stage"] .stage-head { order: 1; }
  .page[data-shape="stage"] .stage { order: 2; }
  .page[data-shape="stage"] .stage-caption { order: 3; }
  .page[data-shape="stage"] .stage-controls { order: 4; }
  .page[data-shape="stage"] .stage-head .lede { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; font-size: var(--fs-ui); }
}
/* stage pages from 1024: the page is one screen; the stage takes what the head leaves */
@media (min-width: 1024px) {
  .page[data-shape="stage"] { block-size: 100dvh; grid-template-rows: var(--bar) minmax(0, 1fr); }
  .page[data-shape="stage"] .main { display: flex; flex-direction: column; min-block-size: 0; padding-block: var(--sp-4); }
  .page[data-shape="stage"] .stage { flex: 1 1 0; block-size: auto; min-block-size: 14rem; }
  html.hosted .page[data-shape="stage"] { grid-template-rows: 0 minmax(0, 1fr); }
}

/* ── Franklin, the observer — one element (#companion-strip), a grid track at every width ── */
.observer { font-size: var(--fs-ui); }
.observer-panel { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); display: grid;
  grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr auto; max-block-size: calc(100dvh - var(--bar) - var(--sp-5));
  container: observer / inline-size; }
.observer-panel > * { min-inline-size: 0; }
.observer-head { display: flex; align-items: center; gap: var(--sp-2); padding-inline: var(--sp-4); min-block-size: var(--strip-h);
  border-block-end: 1px solid var(--line); font-weight: 700; }
.observer-head .name { color: var(--ink); }
.observer-head .role { color: var(--ink-3); font-weight: 400; font-size: var(--fs-small); white-space: nowrap; }
.observer-toggle { margin-inline-start: auto; min-block-size: var(--tap); min-inline-size: var(--tap); border: 1px solid var(--line);
  background: none; color: var(--ink-2); border-radius: 999px; cursor: pointer; font: inherit; }
/* the receipt list is the ONE sanctioned inner scroller of the strip */
.observer-body { overflow: auto; overscroll-behavior: contain; padding: var(--sp-3) var(--sp-4); display: grid; gap: var(--sp-3); align-content: start; }
.observer-body .say { font-size: var(--fs-body); color: var(--ink); margin: 0; }
.observer-body .trail { color: var(--ink-3); font-size: var(--fs-small); }
.observer-body .fact { display: grid; gap: 2px; padding-inline-start: var(--sp-3); border-inline-start: 2px solid var(--line); }
.observer-body .fact.ok { border-inline-start-color: var(--mint); }
.observer-body .fact.refused { border-inline-start-color: var(--amber); }
.observer-body .fact .when { color: var(--ink-3); font-size: var(--fs-small); }
.observer-foot { padding: var(--sp-3) var(--sp-4); border-block-start: 1px solid var(--line); display: flex; gap: var(--sp-2); }
.observer-foot .btn { white-space: nowrap; flex: 0 0 auto; }
.observer-foot input { flex: 1 1 auto; min-inline-size: 0; min-block-size: var(--tap); font: inherit; font-size: var(--fs-ui); color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding-inline: .8em; }
/* a narrow open column (288 px): the question field takes its own line above the button */
@container observer (max-width: 19rem) { .observer-foot { flex-wrap: wrap; } .observer-foot input { flex-basis: 100%; } }
.observer-tab { display: none; }
/* from 1024, folded: a 44 px tab in its own column; open: a panel of constant, capped block-size, so a full
   ring of receipts scrolls inside the list */
@media (min-width: 1024px) {
  .observer { padding-block: var(--sp-5); }
  .observer-panel { block-size: calc(100dvh - var(--bar) - var(--sp-5) * 3); }
  /* one line down the column, cut with an ellipsis */
  .observer-tab { writing-mode: vertical-rl; block-size: var(--observer-tab);
    max-inline-size: calc(100dvh - var(--bar) - var(--sp-7)); padding-block: 0; padding-inline: 1em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--ink-2); cursor: pointer;
    font: inherit; font-size: var(--fs-small); line-height: calc(var(--observer-tab) - 2px); }
  .observer-head .say-short { display: none; }
}
/* folded: below 1920 unless opened; from 1920 only when closed */
@media (min-width: 1024px) and (max-width: 1919.98px) {
  .page:not([data-observer="open"]) .observer-panel { display: none; }
  .page:not([data-observer="open"]) .observer-tab { display: block; }
}
@media (min-width: 1920px) {
  .page[data-observer="closed"] .observer-panel { display: none; }
  .page[data-observer="closed"] .observer-tab { display: block; }
}
/* phone / narrow: the sheet — the last grid row, in flow; folded 52 px with his sentence; open 60dvh */
@media (max-width: 1023.98px) {
  .observer { border-block-start: 1px solid var(--line); background: var(--surface); padding-block-end: env(safe-area-inset-bottom); }
  .observer-panel { border: 0; border-radius: 0; max-block-size: 60dvh; }
  .page:not([data-observer="open"]) .observer-panel { grid-template-rows: auto; }
  .page:not([data-observer="open"]) .observer-body, .page:not([data-observer="open"]) .observer-foot { display: none; }
  .observer-head { border-block-end: 0; padding-inline: max(var(--sp-4), var(--safe-s)) max(var(--sp-4), var(--safe-e)); }
  .observer-head .role { display: none; }
  .observer-head .say-short { font-weight: 400; color: var(--ink-2); font-size: var(--fs-small); min-inline-size: 0; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
  .page[data-observer="open"] .observer-head .say-short { display: none; }
  /* drawer AND sheet open: 50 + 60dvh + the bar put the sheet's foot 190 px under an 844 px screen;
     together: the sheet 40dvh, the drawer what 16rem leave */
  .page[data-observer="open"]:has(.rail-check:checked) .observer-panel { max-block-size: 40dvh; }
  .page[data-observer="open"] .rail-drawer > .rail-body { max-block-size: max(3rem, 60dvh - var(--bar) - var(--tap) - 16rem); }
}
/* a short screen (a phone sideways): the open sheet takes what the bar and the drawer's row leave (70dvh put
   its foot 42 px under a 390 px screen); main drops its 88 px of padding */
@media (max-width: 1023.98px) and (max-height: 520px) { .observer-panel { max-block-size: calc(100dvh - var(--bar) - 11rem); }
  .main { padding-block: var(--sp-2); } }

/* ── the shell: ONE bar, ONE observer, ONE scroll; hosted pages drop their chrome ── */
html.hosted .bar, html.hosted .observer { display: none; }
html.hosted .page { --observer: 0px; }
@media (max-width: 1023.98px) { html.hosted .page { grid-template-rows: 0 auto minmax(0, 1fr) 0; } }
@media (min-width: 1024px) { html.hosted .page { min-block-size: 0; grid-template-rows: 0 minmax(0, 1fr); } }
/* a hosted DOCUMENT is as tall as its content; a hosted STAGE fills the frame */
html.hosted.shape-document, html.hosted.shape-document body { block-size: auto; overflow: visible; }
html.hosted.shape-document .page { block-size: auto; min-block-size: 0; grid-template-rows: 0 auto auto 0; }
@media (min-width: 1024px) { html.hosted.shape-document .page { grid-template-rows: 0 auto; } }
html.hosted.shape-document .main { overflow: visible; }
/* in a hosted document 1dvh is the FRAME's height; the shell writes --top-vh, the visitor's 1vh */
html.hosted.shape-document { --stage-max-h: calc(100 * var(--top-vh, 1dvh) - 7rem); }
/* the shell itself: 100dvh; its MAIN is the one scroller at every width */
html.shell, html.shell body { block-size: 100dvh; overflow: hidden; }
html.shell .page { block-size: 100dvh; grid-template-rows: var(--bar) 0 minmax(0, 1fr) auto; }   /* bar · (no rail) · main · sheet */
@media (min-width: 1024px) { html.shell .page { grid-template-rows: var(--bar) minmax(0, 1fr); }
  html.shell .observer { max-block-size: calc(100dvh - var(--bar)); } }
html.shell .main { overflow: auto; overscroll-behavior: contain; padding: 0; grid-column: full; }
@media (min-width: 1024px) { html.shell .main { grid-column: full-start / main-end; } }
.shell-frame { inline-size: 100%; border: 0; display: block; background: var(--bg); }
.shell-frame[data-shape="document"] { block-size: var(--frame-h, 100vh); }
.shell-frame[data-shape="stage"] { block-size: 100%; }
html.shell .main:has(> .shell-frame[data-shape="stage"]) { overflow: hidden; }

/* ── reduced motion, print ── */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
  transition-duration: .01ms !important; scroll-behavior: auto !important; } }
/* print — the lesson pages: no bar, rail, strip or controls; 11 pt; 80ch; links printed */
@media print {
  :root:not(#_) { color-scheme: light; --fs-small: 9pt; --fs-ui: 10pt; --fs-body: 11pt; --fs-h3: 13pt; --fs-h2: 16pt;
    --fs-h1: 20pt; --fs-hero: 26pt; --reading: 80ch; --ink: #000; --ink-2: #222; --ink-3: #444; --line: #bbb; --surface: #fff;
    --surface-2: #fff; --bg: #fff; --accent: #00429d; --mint: #00573d; --cyan: #005a70; --amber: #6b4100; --rose: #8a0f2c; }
  html, body { block-size: auto; overflow: visible; background: #fff; color: #000; }
  .page { display: block; block-size: auto; min-block-size: 0; }
  .bar, .rail, .observer, #companion-strip, .stage-controls, .more, .chips, .field, button, .btn { display: none !important; }
  .main { padding: 0; overflow: visible; max-inline-size: var(--reading); }
  a { color: inherit; }
  a[href]:not([href^="#"])::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; overflow-wrap: anywhere; }
  .card, .figure, figure, table, pre, img, canvas { break-inside: avoid; }
  h1, h2, h3 { break-after: avoid; }
}
