/* ═══════════════════════════════════════════════════════════════════════
   The GORBIE system, on the web.

   Ported from GORBIE/src/themes.rs (commit 49e4d1d, "true-inversion RAL
   9010/9011 poles, measured-contrast tokens") and GORBIE/src/lib.rs
   (paint_reseau_grid). Every value below is derived, not chosen:

     blend(a, b, t) = a + t * (b - a)      -- themes.rs::blend

   The two themes are ONE decision, not two: the light page's ink is the
   dark page's surface. Both are RAL 9011 Graphite black. Everything else
   falls out of foreground/background alone.

   Do not move the surfaces back toward the middle of the range. The old
   pair (RAL 7047 #CFD0CF / RAL 7046 #82898E) sat only 2.29:1 apart; an
   exhaustive sRGB sweep found ZERO colours with usable chroma clearing
   3:1 on that dark surface, and RAL 7046 against #888888 measured 1.00:1
   -- grey text on the dark page was mathematically invisible. On RAL 9010
   and RAL 9011 the surfaces are 16.03:1 apart and 58 RAL colours clear
   3:1 on BOTH, so one palette finally serves both themes.

   The price: because the poles are 16.03:1 apart, NO colour clears 4.5:1
   on both -- the ceiling for any single value is sqrt(16.03) = 4.00:1.
   So all body text is `--fg`, and the hyperlink leans on its UNDERLINE
   for text-grade relief rather than on a second, per-theme blue.
   Underlines are therefore not optional.
   ═══════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'IosevkaGorbie';
  src: url('fonts/IosevkaGorbie-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IosevkaGorbie';
  src: url('fonts/IosevkaGorbie-Bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ── tokens ───────────────────────────────────────────────────────────
   Light pole. Every token is stated here, in the bare :root, before any
   media or [data-theme] block redefines it.                            */
:root {
  --bg:   #f7f9ef;   /* RAL 9010 Pure white ....... rel-lum 0.938 */
  --fg:   #1c1c1c;   /* RAL 9011 Graphite black ... rel-lum 0.012 */

  --faint:  #eef0e7;  /* blend(bg, fg, 0.04) -- table zebra, equal weight at both poles */
  --code-bg:#eaece2;  /* blend(bg, fg, 0.06) */
  --hover:  #e5e7de;  /* blend(bg, fg, 0.08) */
  --active: #d4d6cd;  /* blend(bg, fg, 0.16) -- "further from the page", not "darker" */
  --border: #7f7f7b;  /* blend(fg, bg, 0.45) -- 3.78 light / 5.70 dark */
  --weak:   #6d6e6a;  /* blend(fg, bg, 0.37) -- 4.83 light / 7.03 dark */

  /* Hairlines are deliberately LIGHTER than weak text: a rule should not
     outweigh the text it separates. */

  --reseau: #d5d7cf;  /* blend(bg, border, 0.28) -- a cross carries more ink
                         than a dot, so it sits further back than the 0.35
                         the dot field used, or it stops being quiet. */

  /* Theme-invariant. These are measured against the KEYCAP or sit at the
     inversion's fixed point, so they are one value at both poles. */
  --accent: #ff2300;  /* RAL 2005 Luminous orange */
  --link:   #3481b8;  /* RAL 5012 Light blue -- 3.97 light / 4.04 dark,
                         i.e. 99.1% / 100.9% of the 4.00:1 ceiling */
  --warn:   #fa842b;  /* RAL 2003 Pastel orange */
  --error:  #d47479;  /* RAL 3014 Antique pink */
  --shadow: #8a8b86;  /* blend(bg, fg, 0.50) -- t=0.50 is the fixed point of
                         the inversion: ONE hex at both poles */

  /* Geometry -- card_ctx.rs. A 768px column, twelve columns, a 12px
     gutter that is also the vertical module, so the grid is truly
     modular (square gutters). 51px columns: (768 - 24 - 11*12) / 12. */
  --col:    768px;
  --gutter: 12px;
  --module: 12px;
  --colw:   51px;
  --pad:    12px;

  --radius-control:   2px;
  --radius-container: 0;   /* containers are square. Always. */
  --anim: 0.12s;

  /* The réseau tile: two column pitches across, twelve modules down.
     pitch_x = 2 * (51 + 12) = 126.  pitch_y = 12 * 12 = 144.
     arm = module / 2 = 6, so each cross is exactly one module wide. */
  --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%23d5d7cf' stroke-width='1'/%3E%3C/svg%3E");
}

/* Dark pole: the exact inversion. Only the tokens move. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:   #1c1c1c;
    --fg:   #f7f9ef;
    --faint:  #252524;
    --code-bg:#292929;
    --hover:  #2e2e2d;
    --active: #3f3f3e;
    --border: #949690;
    --weak:   #a6a7a1;
    --reseau: #3e3e3c;
    --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%233e3e3c' stroke-width='1'/%3E%3C/svg%3E");
  }
}
:root[data-theme="dark"] {
  --bg:   #1c1c1c;
  --fg:   #f7f9ef;
  --faint:  #252524;
  --code-bg:#292929;
  --hover:  #2e2e2d;
  --active: #3f3f3e;
  --border: #949690;
  --weak:   #a6a7a1;
  --reseau: #3e3e3c;
  --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%233e3e3c' stroke-width='1'/%3E%3C/svg%3E");
}

/* ── base ─────────────────────────────────────────────────────────── */
* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: var(--nav-height, 120px);
}

body {
  font-family: 'IosevkaGorbie', 'Iosevka', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 19px;          /* themes.rs Body = 20.0 */
  line-height: 1.55;
  color: var(--fg);
  background-color: var(--bg);

  /* Réseau fiducials in the page margin.

     An Apollo Hasselblad carried a glass réseau plate in front of the
     film, etched with a sparse grid of crosses. Every frame came back
     marked, so the photograph could be measured and the measurement
     trusted. A dot field says "graph paper -- you may draw here"; a
     réseau says "this has been measured".

     The pitch is shared with the layout; the phase is not. Rhythm, not
     registration. */
  background-image: var(--reseau-img);
  background-position: 0 0;
}

::selection { background: var(--active); }

a {
  color: var(--link);
  text-decoration: underline;   /* not optional -- see the header note */
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}
a:hover { color: var(--accent); text-decoration-color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

h1, h2, h3 { font-weight: 700; text-wrap: balance; }
h1 { font-size: 39px; line-height: 1.1; letter-spacing: -0.01em; }  /* themes.rs Heading */
h2 { font-size: 27px; line-height: 1.2; }
h3 { font-size: 19px; }

strong { font-weight: 700; }

code {
  font-family: inherit;
  font-size: 18px;                    /* themes.rs Monospace = 19.0 */
  background: var(--code-bg);
  padding: 0.1em 0.35em;
}

pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  padding: calc(var(--module) * 1.5);
  overflow-x: auto;
  font-size: 15px;
  line-height: 1.5;
}
pre code { background: none; padding: 0; font-size: inherit; }

/* Syntax roles. Status colour is never the sole carrier of meaning. */
pre .kw  { color: var(--accent); }
pre .ty  { color: var(--link); }
pre .st  { color: var(--fg); }
pre .cm  { color: var(--weak); }

hr { border: 0; border-top: 1px solid var(--border); }

/* ── the page column ──────────────────────────────────────────────
   Opaque, so the réseau stays in the MARGIN where it belongs, and the
   column's two hairlines are the only thing separating page from
   workspace. Panels are the page; plane separation is the hairline. */
.page {
  max-width: var(--col);
  margin: 0 auto;
  padding: 0 var(--pad);
  background: var(--bg);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
}

/* ── nav ──────────────────────────────────────────────────────────
   No dark instrument panel. The nav IS the page, carried by one
   hairline, consistent with window_shadow = Shadow::NONE. */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.site-nav-inner {
  max-width: var(--col);
  margin: 0 auto;
  padding: var(--module) var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gutter);
  flex-wrap: wrap;
}
.site-nav-home {
  display: flex;
  align-items: center;
  gap: 0.5em;
  color: var(--fg);
  text-decoration: none;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.04em;
}
.site-nav-home img { width: 22px; height: 22px; display: block; }
.site-nav-home:hover { color: var(--accent); }
.site-nav-links {
  display: flex;
  gap: var(--gutter);
  flex-wrap: wrap;
  align-items: center;
}
.site-nav-links a {
  color: var(--weak);
  text-decoration: none;
  font-size: 13px;                    /* themes.rs Small */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 0;
  border-bottom: 1px solid transparent;
}
.site-nav-links a:hover,
.site-nav-links a.active { color: var(--fg); border-bottom-color: var(--accent); }

/* ── sections ─────────────────────────────────────────────────────
   One hairline rule per section. Nothing else separates them: no
   cards, no shadows, no fills. The page reads as one continuous
   record with entries added below entries. */
.section {
  padding: calc(var(--module) * 4) 0;
  border-top: 1px solid var(--border);
}
.section:first-of-type { border-top: none; }

.section-label {
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--weak);
  margin-bottom: calc(var(--module) * 2);
  display: flex;
  align-items: center;
  gap: 0.6em;
}

/* The réseau cross, promoted from margin texture to a landmark. It is
   the same mark the page is measured with, which is the point: a
   section is another measured frame. */
.reticle {
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  color: var(--accent);
}

.lede { font-size: 22px; line-height: 1.45; margin-top: var(--module); }
.lede-weak { color: var(--weak); }

p + p { margin-top: var(--module); }

/* ── spec list — inline entries, NEVER cards ──────────────────────
   Term in the left four columns, definition in the right eight, one
   hairline between entries. The shape of an instrument's spec sheet,
   which is what a list of guarantees is. */
/* The section's own rule closes the list, so the last entry does not draw
   its own -- two rules with a gap between them is a seam, not a boundary. */
.spec { border-top: 1px solid var(--border); margin-top: calc(var(--module) * 2); }
.spec-row:last-child { border-bottom: none; padding-bottom: 0; }
.spec-row {
  display: grid;
  grid-template-columns: calc(var(--colw) * 4 + var(--gutter) * 3) 1fr;
  gap: var(--gutter);
  padding: calc(var(--module) * 2) 0;
  border-bottom: 1px solid var(--border);
}
.spec-row h3 { font-size: 19px; line-height: 1.35; }
.spec-row p  { color: var(--weak); font-size: 17px; }
.spec-row .links { margin-top: var(--module); display: flex; gap: var(--gutter); flex-wrap: wrap; font-size: 15px; }

.spec-mark {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.5em;
}
.spec-mark img { flex: 0 0 22px; width: 22px; height: 22px; }
.spec-mark h3 { min-width: 0; }

/* ── buttons — a bordered plate, never a pill ─────────────────────
   12/8 padding and a 34px interact size, from themes.rs spacing. */
.btn {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 8px 12px;
  font-family: inherit;
  font-size: 17px;
  font-weight: 700;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--anim), border-color var(--anim);
}
.btn:hover { background: var(--hover); border-color: var(--fg); color: var(--fg); }
.btn:active { background: var(--active); }
.btn-primary { border-width: 2px; border-color: var(--fg); }
.btn-primary:hover { border-color: var(--accent); color: var(--accent); }

.btn-row { display: flex; gap: var(--gutter); flex-wrap: wrap; margin-top: calc(var(--module) * 2); }

/* ── code panels ──────────────────────────────────────────────── */
.panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
  margin-top: calc(var(--module) * 2);
}
.panel { min-width: 0; }
.panel-header {
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--weak);
  border: 1px solid var(--border);
  border-bottom: none;
  padding: 6px 12px;
  background: var(--faint);
}
.panel pre { margin: 0; font-size: 13px; }

/* ── footer ───────────────────────────────────────────────────── */
footer {
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.footer-inner {
  max-width: var(--col);
  margin: 0 auto;
  padding: calc(var(--module) * 3) var(--pad);
  font-size: 15px;
  color: var(--weak);
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em var(--gutter);
}
footer a { color: var(--weak); }
footer a:hover { color: var(--accent); }
.footer-sub { width: 100%; color: var(--weak); }
.content-credit { color: var(--fg); }

/* ── entrance ─────────────────────────────────────────────────────
   Visible at rest. The page must read on its first frame, before any
   script runs; the class is added by JS, so no-JS and pre-JS both see
   a finished page. */
.reveal { opacity: 1; transition: opacity 0.4s ease-out; }
.js-reveal .reveal { opacity: 0; }
.js-reveal .reveal.visible { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  .js-reveal .reveal { opacity: 1; }
}

/* ── responsive ───────────────────────────────────────────────── */
@media (max-width: 800px) {
  .page { border-left: none; border-right: none; }
}
@media (max-width: 640px) {
  body { font-size: 17px; }
  h1 { font-size: 30px; }
  h2 { font-size: 23px; }
  .lede { font-size: 19px; }
  .spec-row { grid-template-columns: 1fr; gap: var(--module); }
  .panels { grid-template-columns: 1fr; }
  .site-nav-inner { gap: 6px var(--gutter); }
}

/* ── emphasis ─────────────────────────────────────────────────────
   The old sites swapped the text colour for emphasis. That cannot work
   here: no colour clears 4.5:1 on both poles, so a coloured word is a
   word made harder to read. Emphasis is therefore a MARK, not a hue --
   the accent underlines the word and the word stays at full contrast.
   Same move the hyperlink makes, for the same measured reason. */
.hl {
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.14em;
}

/* ═══ components for faculties.sh ══════════════════════════════════ */

/* ── faculty table ────────────────────────────────────────────────
   Twelve tools that each do one thing is a spec sheet, not twelve
   cards in twelve colours. `--faint` was derived in themes.rs as the
   table zebra -- a real, equal-weight stripe at both poles (1.08 light
   / 1.11 dark) -- so this is the token doing the job it was made for. */
.ftable {
  width: 100%;
  border-collapse: collapse;
  margin-top: calc(var(--module) * 2);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  font-size: 17px;
}
.ftable tr:nth-child(even) { background: var(--faint); }
.ftable td { padding: 7px var(--gutter); vertical-align: baseline; }
.ftable td:first-child { width: 34%; font-weight: 700; white-space: nowrap; }
.ftable td:last-child { color: var(--weak); }
.ftable code { background: none; padding: 0; font-size: inherit; }

/* ── terminals ───────────────────────────────────────────────────
   No traffic-light dots: those belong to a different design language,
   and this is an instrument, not a window. A bordered plate with a
   labelled header, same as the code panels. */
.terminals {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
  margin-top: calc(var(--module) * 2);
}
.terminal { min-width: 0; border: 1px solid var(--border); background: var(--code-bg); }
.terminal-title {
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--weak);
  background: var(--faint);
  border-bottom: 1px solid var(--border);
  padding: 6px var(--gutter);
}
.terminal-body {
  padding: var(--gutter);
  height: 268px;
  overflow-y: auto;
  scrollbar-width: none;
  font-size: 13px;
  line-height: 1.5;
}
.terminal-line { white-space: pre-wrap; word-break: break-word; padding-left: 8px; border-left: 2px solid transparent; }
/* A line one agent read from what the OTHER just wrote to the same
   file. The accent marks the channel, not the text -- consistent with
   emphasis everywhere else here being a mark rather than a hue. */
.terminal-line.shared { border-left-color: var(--accent); background: var(--hover); }
.terminal-line .prompt { color: var(--weak); }
.terminal-line .cmd { color: var(--fg); font-weight: 700; }
.terminal-line .output { color: var(--weak); }
.terminal-cursor {
  display: inline-block; width: 7px; height: 1em;
  background: var(--accent); vertical-align: text-bottom;
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }

/* ── the shared file ─────────────────────────────────────────────
   Authorship is carried by a MARK and a name, never by colour alone. */
.substrate { border: 1px solid var(--border); margin-top: var(--gutter); }
.substrate-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--gutter); flex-wrap: wrap;
  font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--weak); background: var(--faint);
  border-bottom: 1px solid var(--border); padding: 6px var(--gutter);
}
.substrate-legend { display: flex; gap: var(--gutter); align-items: center; }
.substrate-legend span { display: inline-flex; align-items: center; gap: 5px; }
.mark { width: 9px; height: 9px; border: 1px solid var(--fg); flex: 0 0 9px; }
.mark-ana { background: var(--fg); }
.mark-ben { background: transparent; }
.substrate-facts {
  padding: var(--gutter);
  min-height: 112px;
  display: flex; flex-wrap: wrap; gap: 6px;
  align-content: flex-start;
  font-size: 13px;
}
.fact {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border); padding: 3px 8px;
  background: var(--bg);
}
.fact::before { content: ""; width: 9px; height: 9px; border: 1px solid var(--fg); flex: 0 0 9px; }
.fact.ana::before { background: var(--fg); }
.fact-type { color: var(--weak); text-transform: uppercase; letter-spacing: 0.06em; }

/* ── install tabs ────────────────────────────────────────────── */
.tabs { display: flex; gap: var(--gutter); flex-wrap: wrap; margin-top: calc(var(--module) * 2); }
.tabs button {
  font-family: inherit; font-size: 15px; font-weight: 700;
  min-height: 34px; padding: 8px 12px;
  color: var(--weak); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-control);
  cursor: pointer; transition: color var(--anim), border-color var(--anim);
}
.tabs button:hover { color: var(--fg); }
.tabs button.active { color: var(--fg); border-color: var(--fg); border-width: 2px; }

.pre-wrap { position: relative; margin-top: var(--gutter); }
/* Keep the first code line clear of the copy button. */
.pre-wrap pre { padding-right: 76px; }
.copy-btn {
  position: absolute; top: 8px; right: 8px;
  font-family: inherit; font-size: 13px;
  color: var(--weak); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-control);
  padding: 3px 8px; cursor: pointer;
}
.copy-btn:hover { color: var(--fg); border-color: var(--fg); }

/* ── callout ─────────────────────────────────────────────────────
   Two rules and the page's own ground: an aside, not a card. */
.callout {
  border-top: 2px solid var(--fg); border-bottom: 1px solid var(--border);
  padding: var(--module) 0; margin-top: calc(var(--module) * 2);
  font-size: 17px;
}

/* ── screenshots ─────────────────────────────────────────────── */
.shots { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter);
          margin-top: calc(var(--module) * 2); align-items: start; }
.shot { border: 1px solid var(--border); min-width: 0; }
.shot img { width: 100%; display: block; }
.shot-caption {
  font-size: 13px; color: var(--weak); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 5px var(--gutter); border-top: 1px solid var(--border); background: var(--faint);
}

@media (max-width: 640px) {
  .terminals, .shots { grid-template-columns: 1fr; }
  .terminal-body { height: 210px; }
  .terminal-body::-webkit-scrollbar { display: none; }
  .ftable { font-size: 15px; }
  .ftable td:first-child { width: 40%; }
}

/* ═══ marketing layer ═══════════════════════════════════════════════
   The notebook rules ("one dominant page/column; margins are
   marginalia") are written in design.md under *Implications for GORBIE
   (Notebook UI)*. A marketing page is not a notebook. What carries over
   is the aesthetic, not the furniture: typography as the ornament,
   scarce meaningful saturation, single-line dividers over boxes in
   boxes, no gradients or blurs, the grid as ontology.

   The one structural idea: FULL-BLEED BANDS THAT ALTERNATE THE POLES.
   Only a true inversion can do this. A graphite band and a bone band
   are the same design inverted, so the page changes pace without a
   single component being recoloured. ────────────────────────────── */

.band {
  background: var(--bg);
  color: var(--fg);
  border-top: 1px solid var(--border);
  padding: clamp(48px, 9vw, 132px) var(--pad);
}
.band:first-of-type { border-top: none; }
.band-inner { max-width: 1120px; margin: 0 auto; }
.band-inner--narrow { max-width: 780px; }

/* The inverted band carries the opposite pole's tokens. Defined for
   both themes so the flip survives a theme change in either direction. */
.invert {
  --bg: #1c1c1c; --fg: #f7f9ef;
  --faint: #252524; --code-bg: #292929; --hover: #2e2e2d; --active: #3f3f3e;
  --border: #949690; --weak: #a6a7a1; --reseau: #3e3e3c;
  --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%233e3e3c' stroke-width='1'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .invert {
    --bg: #f7f9ef; --fg: #1c1c1c;
    --faint: #eef0e7; --code-bg: #eaece2; --hover: #e5e7de; --active: #d4d6cd;
    --border: #7f7f7b; --weak: #6d6e6a; --reseau: #d5d7cf;
    --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%23d5d7cf' stroke-width='1'/%3E%3C/svg%3E");
  }
}
:root[data-theme="dark"] .invert {
  --bg: #f7f9ef; --fg: #1c1c1c;
  --faint: #eef0e7; --code-bg: #eaece2; --hover: #e5e7de; --active: #d4d6cd;
  --border: #7f7f7b; --weak: #6d6e6a; --reseau: #d5d7cf;
  --reseau-img: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='126' height='144'%3E%3Cpath d='M57 72.5h12M63.5 66v12' stroke='%23d5d7cf' stroke-width='1'/%3E%3C/svg%3E");
}

/* Typography is the ornament — so the scale does the work, not decoration. */
.display {
  font-size: clamp(38px, 7.2vw, 96px);
  line-height: 0.98;
  letter-spacing: -0.03em;
  font-weight: 700;
  text-wrap: balance;
}
.display--sm { font-size: clamp(30px, 4.6vw, 58px); line-height: 1.04; letter-spacing: -0.02em; }
.standfirst {
  font-size: clamp(17px, 1.7vw, 23px);
  line-height: 1.5; color: var(--weak);
  max-width: 34em; margin-top: clamp(16px, 2vw, 28px);
}

/* Uppercase label plate — the recurring device, bordered not filled. */
.plate {
  display: inline-flex; align-items: center; gap: 0.55em;
  font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--weak); border: 1px solid var(--border);
  padding: 5px 10px; margin-bottom: clamp(20px, 3vw, 40px);
}
.plate b { color: var(--accent); font-weight: 700; }

/* The hero band carries the réseau as a live field, not margin texture. */
.hero-band {
  position: relative;
  min-height: min(82vh, 760px);
  display: flex; align-items: center;
  background-color: var(--bg);
  background-image: var(--reseau-img);
  overflow: hidden;
}
.hero-band .band-inner { position: relative; }

/* Three-across claims. Short lines, not paragraphs — the whole point of
   moving off the spec sheet. */
.claims {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3.4vw, 56px);
  margin-top: clamp(32px, 4.5vw, 64px);
}
.claim { border-top: 2px solid var(--fg); padding-top: 14px; }
.claim h3 { font-size: clamp(19px, 1.9vw, 25px); line-height: 1.18; margin-bottom: 8px; }
.claim p { color: var(--weak); font-size: 16px; line-height: 1.5; }
.claim-n {
  display: block; font-size: 13px; letter-spacing: 0.12em;
  color: var(--accent); margin-bottom: 10px;
}
@media (max-width: 860px) { .claims { grid-template-columns: 1fr; gap: 28px; } }

/* An LCD readout — the instrument speaking, straight from themes.rs:
   fill RAL 6027 on the dark well, teal outline, inset shadow. */
.lcd {
  display: inline-block; background: #1c1c1c; color: #81c0bb;
  border: 1px solid rgba(129,192,187,0.45);
  font-weight: 700; letter-spacing: 0.1em; font-size: 15px;
  padding: 8px 16px; text-shadow: 0 0 8px rgba(129,192,187,0.45);
  box-shadow: inset 0 1px 4px rgba(0,0,0,0.5);
}

.band .btn-row { margin-top: clamp(28px, 4vw, 48px); }
.band .btn { font-size: 16px; }

@media (max-width: 640px) {
  .hero-band { min-height: auto; padding-block: clamp(64px, 16vw, 96px); }
}

/* ═══ instrument layer ══════════════════════════════════════════════
   "It should feel like space tech" (JP). The feel has to come from
   STRUCTURE, not scenery — design.md: glitch and texture should emerge
   from constraints, never be pasted on, and when unsure add a
   constraint rather than decoration.

   So: no stars, no gradients, no nebulae. The réseau is already real
   Apollo hardware — a glass plate etched with crosses so the frame
   could be MEASURED. Everything here extends that one idea: marks that
   register, bezels that bound, readouts that display true values. ── */

/* Registration brackets. NOTE: these must never be put on a grid or flex
   container — the pseudo-elements become items and stretch into full-height
   rules instead of corner marks. Wrap the thing being marked. */
.frame { position: relative; display: block; }
.frame::before, .frame::after,
.frame > .frame-b::before, .frame > .frame-b::after {
  content: ""; position: absolute; width: 14px; height: 14px;
  border: 1px solid var(--accent); pointer-events: none; z-index: 1;
}
.frame::before { top: -4px; left: -4px; border-right: 0; border-bottom: 0; }
.frame::after  { top: -4px; right: -4px; border-left: 0; border-bottom: 0; }
.frame > .frame-b { position: static; }
.frame > .frame-b::before { bottom: -4px; left: -4px; border-right: 0; border-top: 0; }
.frame > .frame-b::after  { bottom: -4px; right: -4px; border-left: 0; border-top: 0; }

/* Measurement decals — RESTORED 2026-09-17, but earning their place this
   time. The first version was cut because it was a tick rail that measured
   nothing: decoration in an instrument's coat. JP liked the look, so the
   fix is not to re-add a ruler, it is to make the ruler READ SOMETHING TRUE.

   It now dimensions the band the way an engineering drawing would:
     - fine ticks at 12px, the layout's real module (GRID_ROW_MODULE)
     - a heavy tick every 144px, the réseau's real vertical pitch
     - a readout of the band's MEASURED height, written by script at load
   Every number on it is read off the rendered page, not authored. With no
   JS the rail still reads as a scale; it just loses the numeric callout. */
.bezel { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: clamp(16px, 2.4vw, 40px); }
.bezel-rail {
  position: relative;
  border-right: 1px solid var(--border);
  background-image:
    repeating-linear-gradient(to bottom, var(--border) 0 1px, transparent 1px 144px),
    repeating-linear-gradient(to bottom, var(--border) 0 1px, transparent 1px 12px);
  background-position: right, right;
  background-size: 13px 100%, 6px 100%;
  background-repeat: no-repeat, no-repeat;
}
.bezel-id, .bezel-dim {
  position: absolute; right: 17px;
  writing-mode: vertical-rl;
  font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--weak); white-space: nowrap;
}
.bezel-id { top: 0; }
.bezel-dim { bottom: 0; color: var(--accent); }
/* The datum arrows that close a dimension line. */
.bezel-rail::before, .bezel-rail::after {
  content: ""; position: absolute; right: -1px; width: 13px; height: 1px;
  background: var(--accent);
}
.bezel-rail::before { top: 0; }
.bezel-rail::after { bottom: 0; }

@media (max-width: 860px) {
  .bezel { grid-template-columns: 1fr; gap: 0; }
  .bezel-rail { display: none; }
}

/* Spec strip — label/value pairs, hairline separated. Every value here
   is read out of the source, not invented for the page. */
.strip {
  display: grid; grid-template-columns: repeat(6, 1fr);
  border: 1px solid var(--border);
  margin-top: clamp(28px, 4vw, 48px);
}
.strip div { padding: 12px 14px; border-left: 1px solid var(--border); }
.strip div:first-child { border-left: 0; }
.strip dt {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--weak); margin-bottom: 6px;
}
.strip dd { font-size: 15px; font-weight: 700; letter-spacing: 0.02em; }
@media (max-width: 860px) {
  .strip { grid-template-columns: repeat(2, 1fr); }
  .strip div { border-top: 1px solid var(--border); }
  .strip div:nth-child(odd) { border-left: 0; }
  .strip div:first-child, .strip div:nth-child(2) { border-top: 0; }
}

/* The phosphor well. Scanlines belong HERE and nowhere else: a lit
   readout is the one place a CRT artifact is honest rather than pasted
   on the page. themes.rs treats the LCD the same way — the one place a
   dark_mode branch is legitimate, because it is a lit surface. */
.lcd {
  position: relative; overflow: hidden;
  background: #1c1c1c; color: #81c0bb;
  border: 1px solid rgba(129,192,187,0.45);
}
.lcd::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: repeating-linear-gradient(
    to bottom, rgba(0,0,0,0.22) 0 1px, transparent 1px 3px);
}
@media (prefers-reduced-motion: reduce) { .lcd::after { display: none; } }

/* Horizontal dimension callout. A SECOND kind of measurement, on the other
   axis and against a different object, so the decals read as an instrument
   annotating what matters rather than a border repeated down the page.
   JP, 2026-09-17: "you don't have to put them everywhere, but I like the
   technical look." An annotation that appears on everything annotates
   nothing — scarcity is what keeps it reading as measurement. */
.dim-x {
  display: flex; align-items: center; gap: 10px;
  margin-top: 14px;
  font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--weak);
}
.dim-x::before, .dim-x::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--border);
  position: relative;
}
.dim-x span { color: var(--accent); white-space: nowrap; }
/* Datum ticks at each end of the dimension line. */
.dim-x-wrap { position: relative; }
.dim-x-wrap::before, .dim-x-wrap::after {
  content: ""; position: absolute; bottom: 0; width: 1px; height: 9px;
  background: var(--accent);
}
.dim-x-wrap::before { left: 0; }
.dim-x-wrap::after { right: 0; }

/* Section rails carry the designation, replacing the numbered header plates.
   JP, 2026-09-17: "we could maybe remove the 01 THE PROBLEM like header boxes
   if we have the name of the section on the measure bar?" — which is a net
   REMOVAL: one device doing two jobs instead of two devices doing one each,
   and the label now lives on the instrument instead of floating beside it.

   The hierarchy is what stops it becoming wallpaper. The hero is the measured
   object and keeps the full instrument (12/144 ticks, datum arrows, dimension
   readout). A section rail is an annotation, not a measurement: fine ticks and
   a name, nothing that pretends to read a value it is not reading. */
.bezel-rail--light {
  background-image: repeating-linear-gradient(
    to bottom, var(--border) 0 1px, transparent 1px 12px);
  background-size: 6px 100%;
}
.bezel-rail--light::before, .bezel-rail--light::after { display: none; }
.bezel-rail--light .bezel-id { color: var(--weak); }
.bezel-id b { color: var(--accent); font-weight: 700; letter-spacing: 0.2em; }
