/* archetypes.ai — design system
 *
 * Direction: "Data table". Monospace for everything structural (slot names, column
 * heads, labels, numbers), serif for everything that is an argument. The site's
 * central claim is that structure and vocabulary are separable; the type says so.
 *
 * Rationale and the alternatives considered: ../docs/DESIGN.md
 */

:root {
  /* Ink and paper. Warm-neutral paper, near-black ink — printed-table register. */
  --paper:      hsl(60 25% 98%);
  --paper-sunk: hsl(60 12% 95%);
  --panel:      hsl(210 12% 93%);   /* app surface for the interactive component */
  --ink:        hsl(220 13% 9%);
  --ink-soft:   hsl(216 11% 27%);
  --ink-mute:   hsl(219 8% 41%);
  --rule:       hsl(217 14% 81%);
  --rule-hair:  hsl(218 17% 91%);

  /* One accent. Teal reads as instrument rather than brand, and holds contrast
     on both paper and sunk paper (>= 4.5:1 against --paper). */
  --accent:     hsl(175 77% 26%);
  --accent-bg:  hsl(171 43% 90%);
  --accent-rule:hsl(172 38% 64%);
  /* The LaBSE chip between the two forms: the accent hue, most of the way to
     paper. It marks a measurement without becoming a third signal colour. */
  --metric-bg:  hsl(171 40% 95%);
  --metric-rule:hsl(172 30% 80%);

  /* Highlight for the slot->word link. Deliberately not the accent: the accent
     means "selected column", this means "the word under your cursor". */
  --hot:        hsl(41 86% 72%);   /* under the pointer: the cell AND the word it puts in the passage */
  --hot-rule:   hsl(41 65% 47%);
  --row-lit:    hsl(42 71% 93%);   /* the rest of the hovered row's instantiations */
  --index-lit:  hsl(249 71% 93%);   /* the hovered row's index cell — structural, so neutral */
  --index-focus:      hsl(215 43% 90%);   /* index column in focus  — the blue of --accent-bg */
  --index-ink:        hsl(215 77% 26%);   /* role name on that ground — the blue of --accent */
  --index-focus-rule: hsl(215 38% 64%);
  /* 84%, not the domain's 72%: at hue 249 an L of 72% carries a relative luminance
     of 0.26 against the amber's 0.65, so numeric parity in HSL reads far darker.
     Matched by eye-luminance instead, which is what the policy is actually for.
     Light text would be the wrong fix -- 3.3:1 against 9.5:1 for dark. */
  --index-hot:        hsl(249 86% 84%);   /* index cell under the pointer — --hot at the index hover hue */
  --index-hot-rule:   hsl(249 65% 47%);

  /* Sans for everything readable. This is a blog post about a paper, not the paper:
     a serif body made it read as an offprint. Mono is kept, but only for structural
     labels — column heads, slot names, nav — never for running text. */
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, 'Helvetica Neue', Arial, sans-serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, 'DejaVu Sans Mono', monospace;

  /* 680px. Deliberately rem, not em/ch: a custom property resolves em against the
     font-size of whatever element uses it, so 34em would cap the 3.6rem h1 near
     2000px while paragraphs got 680. rem is stable across every element.
     680px at the 20px body is ~68 characters — the long-form band. It was 36rem
     = 576px = 58 characters, because rem tracks the 16px root, not the body. */
  --measure: 42.5rem;
  --gutter:  clamp(1.2rem, 4vw, 3rem);
  --stack:   1.6rem;     /* rhythm unit */
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 20px;
  line-height: 1.6;
  text-rendering: optimizeLegibility;
}

/* ------------------------------------------------------------------ chrome */

.site-header {
  max-width: 92rem; margin: 0 auto;
  display: flex; align-items: baseline; gap: 2rem; flex-wrap: wrap;
  padding: 1.1rem var(--gutter);
  border-bottom: 1px solid var(--ink);
}
.wordmark {
  font-family: var(--mono);
  font-size: 1.05rem; font-weight: 600; letter-spacing: .02em;
  color: var(--ink); text-decoration: none;
}
.site-nav { display: flex; gap: 1.4rem; flex-wrap: wrap; margin-left: auto; }
.site-nav a {
  font-family: var(--mono); font-size: .78rem; letter-spacing: .02em;
  color: var(--ink-mute); text-decoration: none; padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover { color: var(--ink); border-bottom-color: var(--rule); }
.site-nav a[aria-current='page'] { color: var(--ink); border-bottom-color: var(--accent); }

/* Documentation layout: a whole-site contents list on the left, content beside it.
   The left margin now holds navigation instead of nothing, which is the point --
   a centred column with empty margins reads as a printed offprint. */
.shell {
  display: grid;
  grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  max-width: 92rem; margin: 0 auto;
  padding: 0 var(--gutter);
}
.page { padding: clamp(2rem, 5vw, 3.6rem) 0 6rem; min-width: 0; }
.page > * { max-width: var(--measure); margin-left: 0; margin-right: 0; }

.sidebar {
  position: sticky; top: 0; align-self: start;
  max-height: 100vh; overflow-y: auto;
  padding: clamp(2rem, 5vw, 3.6rem) 0 2rem;
  font-size: .8rem; line-height: 1.35;
  scrollbar-width: thin;
}
.sidebar-head {
  font-family: var(--mono); font-size: .62rem; text-transform: uppercase;
  letter-spacing: .12em; color: var(--ink-mute); margin: 0 0 .8rem;
}
.site-toc, .toc-subs { list-style: none; margin: 0; padding: 0; }
.site-toc > li + li { margin-top: .15rem; }
.toc-page-link {
  display: block; padding: .3rem .7rem; color: var(--ink-soft);
  text-decoration: none; font-weight: 600;
  border-left: 2px solid var(--rule-hair);
}
.toc-page-link:hover { color: var(--ink); background: var(--paper-sunk); }
.toc-page.is-current > .toc-page-link { color: var(--ink); border-left-color: var(--accent); }
.toc-subs { margin-bottom: .4rem; }
.toc-subs a {
  display: block; padding: .22rem .7rem .22rem 1.4rem; color: var(--ink-mute);
  text-decoration: none; border-left: 2px solid var(--rule-hair); font-size: .95em;
}
.toc-subs .lvl3 a { padding-left: 2.1rem; font-size: .9em; }
.toc-subs a:hover { color: var(--ink); background: var(--paper-sunk); }
/* Only the current page's subsections are worth the vertical space. */
.toc-page:not(.is-current) > .toc-subs { display: none; }

/* Exhibits need more room than prose. */
.page > .scroll-x, .page > .we, .page > .unready, .page > .cr { max-width: 100%; }
.page > .fig { max-width: 56rem; }
.page > .fig-img { max-width: min(100%, 60rem); }

.site-footer {
  max-width: 92rem; margin: 0 auto;
  border-top: 1px solid var(--rule);
  padding: 1.4rem var(--gutter) 3rem;
  font-family: var(--mono); font-size: .74rem; color: var(--ink-mute);
}
.site-footer a { color: var(--ink-mute); }

/* ---------------------------------------------------------------- typography */

h1, h2, h3 { line-height: 1.2; font-weight: 600; }

/* The hero: three negations then the positive (docs/MESSAGING.md § Tagline). */
h1 {
  font-size: clamp(2.2rem, 6vw, 3.6rem);
  font-weight: 700; letter-spacing: -.025em; line-height: 1.08; margin: 0 0 .35em;
}
.page > h1 + h3 {
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  font-weight: 400; color: var(--ink-soft); line-height: 1.4;
  margin: -.15em 0 1.8em;   /* auto, not 0 — .page > * centres every block */
}
h2 {
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  font-weight: 650; letter-spacing: -.012em; color: var(--ink);
  margin: calc(var(--stack) * 2.4) 0 var(--stack);
}
h3 { font-size: 1.15rem; margin: calc(var(--stack) * 1.5) 0 .5rem; }

p { margin: 0 0 var(--stack); }
strong { font-weight: 600; }
a { color: var(--accent); text-underline-offset: .16em; text-decoration-thickness: .06em; }
a:hover { text-decoration-thickness: .12em; }

hr { border: 0; border-top: 1px solid var(--rule-hair); margin: calc(var(--stack) * 2) 0; max-width: var(--measure); }

blockquote {
  margin: var(--stack) 0; padding: .1rem 0 .1rem 1.3rem;
  border-left: 2px solid var(--accent-rule);
  color: var(--ink-soft); font-size: 1.02rem;
}
blockquote p:last-child { margin-bottom: 0; }

ul { margin: 0 0 var(--stack); padding-left: 1.15rem; }
li { margin-bottom: .4em; }

code {
  font-family: var(--mono); font-size: .86em;
  background: var(--paper-sunk); padding: .1em .32em; border-radius: 2px;
  /* Paths and identifiers have no spaces to break at, so a long one pushes the
     whole page sideways on a phone — `reproduce/data/probe_K_20260529T014133Z`
     was 415px wide in a 320px viewport. Break anywhere rather than scroll the
     document; `anywhere` (not `break-word`) also lets it shrink a flex/grid item. */
  overflow-wrap: anywhere;
}
pre {
  background: var(--paper-sunk); border: 1px solid var(--rule-hair);
  padding: 1rem 1.1rem; overflow-x: auto; font-size: .82rem; line-height: 1.5;
}
pre code { background: none; padding: 0; font-size: inherit; }

/* Every table is framed the way the interactive one is: a tinted surface with the
   table sitting on paper inside it. The exhibits then read as one family — the same
   object whether or not it happens to respond to the pointer.

   The tinted padding IS the frame, so the table itself takes no radius. A rounded
   table would need its corner cells clipped, and the leaderboards paint colour to
   the very edge of the first and last cells — the paper's own heatmap. */
.scroll-x, .constructs-fig {
  overflow-x: auto;
  margin: 0 0 var(--stack);
  background-color: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: .7rem;
}
.scroll-x > table, .constructs-fig > table { background: var(--paper); }
/* The figure's caption belongs inside its frame, set on the tint rather than the
   paper so it reads as a label on the object rather than a row of the table. */
.constructs-fig > figcaption { padding: .7rem .2rem 0; }

/* -------------------------------------------------------------------- tables */

table { border-collapse: collapse; width: 100%; }

/* Booktabs, as the paper sets them: a rule above, a rule under the header, a rule at the
   foot, and nothing between rows or columns. Headers are bold roman, not small caps. */
.md-table {
  font-size: .86rem; font-variant-numeric: tabular-nums;
  border-top: 1.4px solid var(--ink); border-bottom: 1.4px solid var(--ink);
}
.md-table th, .md-table td { padding: .34em .8em; text-align: left; border: 0; }
.md-table thead th {
  font-weight: 650; color: var(--ink); vertical-align: bottom;
  border-bottom: .8px solid var(--ink); padding-bottom: .42em;
}
.md-table tbody tr:first-child td { padding-top: .5em; }
.md-table tbody tr:last-child td { padding-bottom: .5em; }
/* Numeric columns: the manuscript right-aligns them with ---: */
.md-table th[align="right"], .md-table td[align="right"] { text-align: right; }
.md-table th[align="center"], .md-table td[align="center"] { text-align: center; }

.tbl-caption {
  font-size: .84rem; line-height: 1.45; color: var(--ink-soft);
  max-width: none; margin: 0 0 .7rem;
}

/* Leaderboard. E and G sit beside T because a single ranked column hides the finding. */
.lb { font-size: .9rem; }
.lb caption {
  caption-side: top; text-align: left; font-family: var(--mono); font-size: .7rem;
  letter-spacing: .04em; color: var(--ink-mute); padding-bottom: .7rem;
}
.lb th, .lb td { padding: .5em .7em; border-bottom: 1px solid var(--rule-hair); }
.lb thead th {
  font-family: var(--mono); font-size: .72rem; font-weight: 600; text-align: left;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-mute);
  border-bottom: 1.5px solid var(--ink);
}
.lb .num {
  font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right;
  width: 1%; white-space: nowrap;   /* shrink to content; the model column takes the slack */
}
.lb .model { width: auto; }
.lb .strong { font-weight: 600; color: var(--ink); }
.lb .ci { font-size: .76rem; color: var(--ink-mute); white-space: nowrap; }
/* The heat table encodes value in the cell background, so the council row tint
   must not paint over it — seat membership there is carried by the dot and the
   bold model name instead. */
.lb:not(.heat) tr.council td { background: var(--accent-bg); }
.lb .seat, .lb .seat-none { display: inline-block; width: 1em; color: var(--accent); font-size: .7em; vertical-align: .15em; }
.lb .model-name { font-family: var(--mono); font-size: .82rem; }
.lb .provider { display: block; font-size: .72rem; color: var(--ink-mute); padding-left: 1em; }
.lb .anchor-mark {
  font-family: var(--mono); font-size: .6rem; text-transform: uppercase; letter-spacing: .08em;
  border: 1px solid var(--accent-rule); color: var(--accent); padding: .05em .3em; border-radius: 2px;
}

/* ------------------------------------------------------- unready placeholder */

/* A view the site does not have yet. Courier on grey so it can never be mistaken
   for finished design, and it carries the copy's own description of the job. */
.unready {
  display: block; margin: 0 auto var(--stack);
  background: hsl(0 0% 93%); border: 1px dashed hsl(0 0% 66%); border-radius: 2px;
  padding: 1rem 1.1rem;
  font-family: 'Courier New', Courier, monospace;
  font-size: .82rem; line-height: 1.55; color: hsl(0 0% 20%);
}
.unready-tag {
  display: block; font-size: .66rem; text-transform: uppercase; letter-spacing: .12em;
  color: hsl(0 0% 42%); margin-bottom: .45rem;
}
.unready-text { display: block; }

.draft-chip {
  display: inline-block; font-family: var(--mono); font-size: .62rem; text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink-mute); border: 1px solid var(--rule);
  padding: .1em .4em; border-radius: 2px; vertical-align: .25em; margin-left: .6rem;
}

/* -------------------------------------------------------- the worked example */

/* An app surface, not a figure: the panel is tinted, the table and the passages sit
   on paper inside it. */
.we {
  margin: 0 0 var(--stack);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: .7rem;
}
.we-scroll { overflow-x: auto; }
/* Each labelled region of the component is a panel on paper, inside the tinted app
   surface: the metanym table, then the two forms of the parallel context. */
.we-panel {
  background: var(--paper); border: 1px solid var(--rule-hair);
  border-radius: 6px; padding: .7rem .8rem .8rem;
}
.we table { font-size: .82rem; }
.we th, .we td {
  padding: .45em .65em; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--rule-hair);
}
.we thead th { padding: 0; border-bottom: 1.5px solid var(--ink); }
/* Real buttons: focus, Enter/Space and screen-reader semantics come from the
   platform. They fill the header cell so the whole column head stays the target. */
.we-col {
  display: block; width: 100%; text-align: left; cursor: pointer;
  font-family: var(--mono); font-size: .74rem; font-weight: 600; color: inherit;
  background: none; border: 0; padding: .45em .65em; white-space: nowrap;
  transition: background .12s;
}
.we-col small { display: block; font-weight: 400; font-size: .88em; color: var(--ink-mute); }
.we-col:hover { background: var(--paper-sunk); }
.we-col[aria-pressed="true"] { background: var(--accent-bg); box-shadow: inset 0 3px 0 var(--accent); }
.we th.slotname {
  font-family: var(--mono); font-size: .68rem; font-weight: 500; letter-spacing: .02em;
  color: var(--ink); white-space: nowrap;
}
.we .colon { background: var(--accent-bg); }
/* The index column is a column like the others, but it holds roles rather than a
   domain's vocabulary — so when it is the one in focus it reads blue, not teal. */
.we th.slotname.colon { background: var(--index-focus); }
.we .slotname.head .we-col[aria-pressed="true"] {
  background: var(--index-focus); box-shadow: inset 0 3px 0 var(--index-focus-rule);
}
.we thead th.colon { box-shadow: inset 0 3px 0 var(--accent); }
/* Three levels of lighting, in order of specificity:
   the row's instantiations, the row's index cell, and the cell under the pointer. */
.we tr.rowhot td { background: var(--row-lit); }
/* The index cell names the slot rather than instantiating it, so it lights in its own
   neutral rather than in the instantiation colour. */
.we tr.rowhot th.slotname { background: var(--index-lit); }
/* Row and column meet here. This is exactly the colour the same keyword takes in the
   passage below, so the eye joins the cell to the word without being told to. */
.we tr.rowhot td.colon { background: var(--hot); }
/* Identical policy for the index column, one hue over: pale when its row is hovered,
   saturated where the pointer actually is. */
.we tr.rowhot th.slotname.colon { background: var(--index-hot); }
.we tbody td, .we tbody th.slotname { cursor: default; }

/* Two forms of one parallel context. The two panels keep the full width between them —
   the measure of their agreement floats in the gap rather than taking a column of its
   own, which would squeeze the passages to pay for it. */
.we-forms {
  display: grid; grid-template-columns: 1fr 1fr; gap: .7rem;
  margin-top: .7rem; align-items: start;
  position: relative;
}
.we-metric {
  position: absolute; z-index: 1;
  left: 50%; transform: translateX(-50%);
  top: .78rem;                  /* on the labels' line, in the space they leave */
  text-align: center; pointer-events: none;
}
.we-metric .lab-metric { pointer-events: auto; }

/* The measure floats at the centre of the forms, so the two labels reserve that space
   rather than centring across it — each re-centres in what is left. Reserved equally on
   both, so the labels stay symmetric with each other and neither is ever truncated. */
.we-forms > .we-panel:first-of-type .we-label { padding-right: 7.5rem; }
/* 'Idiomatic Rewrite' is the shorter label, so centring it in the same reserved space
   left it further from the chip than its neighbour. The outer padding pulls it back in
   until both gaps match. */
.we-forms > .we-panel:last-of-type  .we-label { padding-left: 7.5rem; padding-right: 8.1rem; }
.we-forms.solo { grid-template-columns: 1fr; }
.we-label {
  display: flex; align-items: baseline; justify-content: center; gap: .5rem; flex-wrap: wrap;
  margin-bottom: .6rem; padding-bottom: .45rem;
  border-bottom: 1px solid var(--rule-hair);
}
.lab-metric {
  display: flex; align-items: center; justify-content: center;
  /* Up from .72rem. It is a result, not a caption — it was set smaller than the two
     labels it sits between and read as an annotation on them. The reserved space in
     both labels above grows by the same ratio, or the chip starts truncating them. */
  font-family: var(--mono); font-size: .82rem; color: var(--ink-soft);
  cursor: help;
}
.lab-metric[hidden] { display: none; }
.lab-metric .metric-text {
  /* A very discreet hue — the accent at a fraction of its saturation. Enough to lift
     the chip off the panel and say "this is a measurement", not enough to compete
     with the lit column in the table above it. */
  border: 1px solid var(--metric-rule); border-radius: 3px; padding: .22em .5em;
  background: var(--metric-bg); white-space: nowrap;
}

.we-foot {
  margin: .7rem 0 0; padding: .6rem .2rem 0;
  border-top: 1px solid var(--rule-hair);
  font-size: .78rem; line-height: 1.5; color: var(--ink-mute);
}
.we-foot a { color: var(--ink-mute); }
.lab-title {
  font-family: var(--mono); font-size: .92rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em; color: var(--ink);
}
.we-passage { margin: 0; font-size: .96rem; line-height: 1.8; }
.we-empty { color: var(--ink-mute); font-style: italic; }
.we .mn {
  background: var(--accent-bg); color: var(--accent);
  padding: .05em .28em; border-radius: 2px;
  box-shadow: inset 0 -1px 0 var(--accent-rule);
  transition: background .12s, color .12s;
}
/* A slotted keyword always carries the colour of the column it came from: teal for a
   domain, blue for the index column whose "vocabulary" is the role names themselves. */
.we .mn.role {
  font-family: var(--mono); font-size: .82em; letter-spacing: .01em;
  background: var(--index-focus); color: var(--index-ink);
  box-shadow: inset 0 -1px 0 var(--index-focus-rule);
}
.we .mn.hot { background: var(--hot); color: var(--ink); box-shadow: inset 0 -1px 0 var(--hot-rule); }
/* A keyword under the pointer always matches the cell it came from, so a role name
   takes the index hue rather than the domain one. */
.we .mn.role.hot {
  background: var(--index-hot); color: var(--ink);
  box-shadow: inset 0 -1px 0 var(--index-hot-rule);
}

@media (max-width: 900px) {
  .we-forms { grid-template-columns: 1fr; gap: 1.2rem; }
  /* Stacked: nothing to float between, so it returns to the flow and the labels get
     their full width back. */
  .we-metric { position: static; transform: none; text-align: center; }
  .we-forms > .we-panel .we-label { padding-left: 0; padding-right: 0; }
  .we-forms > div + div { border-top: 1px dashed var(--rule); padding-top: 1.1rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* A draft page says what it is for, in the placeholder register, until it is published. */
.page-purpose { margin-bottom: calc(var(--stack) * 2); }

/* Narrow screens: the nav becomes one scrollable row rather than wrapping onto a
   second line, which cost a third of the first screen on a phone. */
@media (max-width: 640px) {
  .site-header { flex-wrap: nowrap; gap: 1rem; align-items: center; }
  .wordmark { flex: none; }
  .site-nav {
    flex-wrap: nowrap; gap: 1rem; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .site-nav::-webkit-scrollbar { display: none; }
  .site-nav a { white-space: nowrap; }
}


/* --------------------------------------------------------------------- figures
 *
 * Server-rendered SVG, no chart library. Encoding rules: one hue for magnitude,
 * light to dark; identity never carried by colour alone (council seats are filled
 * and ringed, so the distinction survives greyscale and CVD); no dual axes; no
 * value printed on every mark — selective labels, a <title> per mark, and a table
 * underneath for the digits.
 */

.fig { margin: 0 auto var(--stack); padding: 0; }
.fig-svg { display: block; width: 100%; height: auto; }
.fig figcaption {
  font-size: .86rem; line-height: 1.6; color: var(--ink-soft);
  border-top: 1px solid var(--rule-hair); padding-top: .7rem; margin-top: .3rem;
}
.fig-legend {
  display: flex; gap: 1.2rem; flex-wrap: wrap; margin: .2rem 0 .5rem;
  font-family: var(--mono); font-size: .7rem; color: var(--ink-mute);
}
.fig-legend .key { display: inline-flex; align-items: center; gap: .35rem; }

.fig-svg .grid  { stroke: var(--rule-hair); stroke-width: 1; }
.fig-svg .axis  { stroke: var(--rule); stroke-width: 1; }
.fig-svg .diag  { stroke: var(--rule); stroke-width: 2; stroke-dasharray: 4 4; }
.fig-svg .tick, .fig-svg .axlabel, .fig-svg .ptlabel {
  font-family: var(--mono); fill: var(--ink-mute);
}
.fig-svg .tick    { font-size: 11px; }
.fig-svg .ty      { text-anchor: end; }
.fig-svg .tx      { text-anchor: middle; }
.fig-svg .axlabel { font-size: 11.5px; letter-spacing: .04em; }
.fig-svg .ptlabel { font-size: 11px; fill: var(--ink-soft); }

/* 2px surface ring so overlapping marks stay countable. */
.pt { fill: none; stroke: var(--accent); stroke-width: 2; }
.pt.filled { fill: var(--accent); stroke: var(--paper); stroke-width: 2; }

.fig-table { margin-top: .8rem; }
.fig-table summary {
  font-family: var(--mono); font-size: .72rem; color: var(--ink-mute);
  cursor: pointer; padding: .2rem 0;
}
.fig-table summary:hover { color: var(--ink); }

/* Heatmap: one hue, light to dark. --v is the correlation, 0..1. */
.heat .rho {
  font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right;
  background: color-mix(in oklab, var(--accent) calc(var(--v, 0) * 62%), var(--paper));
}
.heat .rho.na { background: repeating-linear-gradient(45deg, hsl(60 6% 94%) 0 4px, hsl(60 6% 90%) 4px 8px);
  color: var(--ink-mute); font-style: italic; }
.heat .rho.mean { background: none; border-top: 1.5px solid var(--ink); color: var(--ink-mute); }
.heat tr.panel td { font-family: var(--mono); font-size: .76rem; }
.heat thead th.fa { color: var(--ink-mute); font-weight: 400; }
.heat thead th.nf { color: var(--ink); }
.heat tr.council td.model { font-weight: 600; }

/* Constructs: which of the two tasks demands each ability. */
.constructs { font-size: .86rem; }
.constructs th, .constructs td {
  padding: .55em .7em; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--rule-hair);
}
.constructs thead th {
  font-family: var(--mono); font-size: .72rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-mute); border-bottom: 1.5px solid var(--ink);
}
.constructs thead th small {
  display: block; text-transform: none; letter-spacing: 0; font-size: .92em;
  /* No opacity here. --ink-mute already clears 4.5:1 on paper; multiplying it by
     .75 to make the sub-label recede pushed it to ~3.4:1. Recede by size and
     weight, which cost nothing, rather than by transparency, which costs contrast. */
  font-weight: 400;
}
.constructs th.construct { font-weight: 600; width: 34%; }
.constructs th.construct small {
  display: block; font-weight: 400; font-size: .8em; color: var(--ink-mute); margin-top: .15em;
}
.constructs td.yes { color: var(--ink-soft); }
.constructs td.yes .dot { color: var(--accent); margin-right: .4em; font-size: .8em; }
.constructs td.no { background: var(--paper-sunk); }

.vis-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}


/* ------------------------------------------------------------------- a11y */

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

.skip-link {
  position: absolute; left: -9999px; top: 0;
  font-family: var(--mono); font-size: .8rem;
  background: var(--ink); color: var(--paper); padding: .6em 1em; z-index: 10;
}
.skip-link:focus { left: .5rem; top: .5rem; }

/* The anchor is the reference, not a competitor: above the rule, no ordinal. */
.lb tr.anchor-row td { border-bottom: 1.5px solid var(--ink); }
.lb .refmark {
  font-family: var(--mono); font-size: .68rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-mute);
}


/* The paper's own exhibits, shown as images. */
.fig-img { margin: calc(var(--stack) * 1.6) 0; }
.fig-img img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule-hair); border-radius: 3px; background: hsl(0 0% 100%);
}
.fig-img figcaption {
  font-size: .82rem; line-height: 1.5; color: var(--ink-mute);
  border: 0; padding-top: .7rem; margin-top: 0;
}

/* ------------------------------------------------- the council, in its own words */

.cr { margin: 0 auto var(--stack); }
.cr-case + .cr-case { margin-top: calc(var(--stack) * 2.4); }
.cr-title {
  display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  font-size: 1.15rem; margin: 0 0 .3rem;
}
.cr-tag {
  font-family: var(--mono); font-size: .66rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--accent); border: 1px solid var(--accent-rule); border-radius: 2px;
  padding: .15em .45em; white-space: nowrap;
}
.cr-framing { color: var(--ink-mute); font-size: .95rem; margin: 0 0 1rem; }
.cr-passage {
  font-size: .88rem; line-height: 1.6; color: var(--ink-soft);
  border-left: 3px solid var(--rule); padding: .1rem 0 .1rem 1rem; margin: 0 0 1.3rem;
}
.cr-judges { list-style: none; margin: 0 0 1.1rem; padding: 0; display: grid; gap: .1rem; }
.judge { border-top: 1px solid var(--rule-hair); padding: .8rem 0; }
.judge-head { display: flex; align-items: center; gap: .6rem; margin-bottom: .3rem; }
.judge-name { font-family: var(--mono); font-size: .78rem; color: var(--ink); }
.judge-score {
  font-family: var(--mono); font-size: .78rem; font-weight: 600;
  min-width: 1.9em; text-align: center; padding: .1em .3em; border-radius: 2px;
  background: var(--accent-bg); color: var(--accent);
}
.judge-comment { margin: 0; font-size: .93rem; line-height: 1.55; color: var(--ink-soft); }
.cr-takeaway {
  font-size: .95rem; line-height: 1.6;
  border-top: 2px solid var(--ink); padding-top: .8rem; margin: 0;
}


/* The sidebar carries navigation on wide screens, so the header need not repeat it.
   Below the breakpoint the sidebar is gone and the header nav takes over. */
@media (min-width: 62.01rem) { .site-nav { display: none; } }
@media (max-width: 62rem) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar { display: none; }
}

/* ------------------------------------------- constructs table, with popovers */

.constructs-fig { position: relative; }
.constructs tr { position: relative; }

/* The row under the pointer lights, whole. Same amber as the metanym table's hovered
   row, because it means the same thing there: this is the row you are on. It must
   come after .constructs td.no, which also paints a cell background — equal
   specificity would have left the empty cells unlit and the row looking broken.
   Rows only, never the header. */
.constructs tbody tr:hover > th,
.constructs tbody tr:hover > td { background: var(--row-lit); }
.constructs th.construct { position: relative; cursor: help; }
.constructs th.construct:hover .construct-name,
.constructs th.construct:focus-visible .construct-name { text-decoration: underline dotted; }

/* The construct's own text, to the left of the column it belongs to. CSS-only:
   hover or keyboard focus, no script, and the text is in the row either way. */
/* BELOW the row, not beside it.
 *
 * This was specified as "to the left of the construct column", and that was right at
 * the time — the page then had an empty left margin. Reintroducing the contents list
 * took that margin: the table now starts 19px from the sidebar's edge, so a panel
 * placed left lands on top of the navigation, including the entry the scroll-spy is
 * lighting. Placing it right instead only moves the problem — it fits at 1600px and
 * runs off the viewport at 1280.
 *
 * Under the row is the one position that is correct at every width, and it keeps the
 * panel touching the lit row it belongs to. */
.pop {
  position: absolute; z-index: 5;
  left: 0; top: calc(100% - .3rem);
  width: min(34rem, 100%);
  display: none;
  padding: .85rem .95rem;
  /* The row's own ground, not paper: the panel and the lit row are one object, and
     a paper-white panel floating beside an amber row read as two. */
  background: var(--row-lit); color: var(--ink-soft);
  border: 1px solid var(--hot-rule); border-radius: 6px;
  box-shadow: 0 6px 22px hsl(220 20% 20% / .16);
  font-family: var(--sans); font-size: .84rem; line-height: 1.5;
  text-transform: none; letter-spacing: 0; font-weight: 400;
  white-space: normal;
}
/* Hovering ANYWHERE in the row opens it, not just the construct cell. That was the
   original specification — "when the pointer hovers over a row" — and the narrower
   trigger meant the popover missed whenever the pointer approached from the right,
   across the two columns that take up most of the table's width. */
.constructs tbody tr:hover .pop,
.constructs th.construct:hover .pop,
.constructs th.construct:focus-within .pop,
.constructs th.construct:focus .pop { display: block; }
.pop-title { display: block; font-weight: 650; color: var(--ink); margin-bottom: .1rem; }
.pop-cite { display: block; font-family: var(--mono); font-size: .7rem; color: var(--ink-mute);
  margin-bottom: .5rem; }
.pop-body { display: block; }

/* A pointer, so the panel reads as belonging to its row. */
.pop::after {
  content: ""; position: absolute; left: 1.6rem; top: -12px;
  border: 6px solid transparent; border-bottom-color: var(--hot-rule);
}

.constructs figcaption .hint {
  display: block; margin-top: .4rem; font-family: var(--mono); font-size: .72rem;
}
.constructs-fig figcaption .hint {
  display: block; margin-top: .5rem; font-family: var(--mono); font-size: .72rem;
  color: var(--ink-mute);
}

/* Narrow screens differ only in width; the placement is the same everywhere now. */
@media (max-width: 70rem) {
  .pop { width: min(28rem, 86vw); }
}

/* A dash row in the manuscript is a rule across the table — the council cut. */
.md-table tr.rule-row td, .md-table tr.rule-row th {
  padding: 0; height: 0; font-size: 0; line-height: 0; color: transparent;
  border-top: .8px solid var(--ink);
}

/* The legend the paper prints under each table: what every column means. */
.tbl-note {
  font-size: .78rem; line-height: 1.5; color: var(--ink-mute);
  max-width: none; margin: .55rem 0 0;
}

/* The paper and its code, above the contents list. */
.sidebar-links { display: flex; flex-direction: column; gap: .3rem; margin: 0 0 1.3rem; }
.sidebar-links a {
  display: block; padding: .34rem .7rem;
  font-family: var(--mono); font-size: .76rem; color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--rule); border-radius: 3px;
}
.sidebar-links a:hover { border-color: var(--accent); color: var(--accent); }

/* ------------------------------------------------ Appendix D: the transcript

   Four levels, each given a different kind of weight so the nesting is visible:
   archetype (h2) > section banner > unit card > the judges inside it. */

.apx-banner {
  font-family: var(--mono); font-size: .72rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .14em; color: var(--paper);
  background: var(--ink); border-radius: 3px;
  padding: .45rem .8rem; margin: calc(var(--stack) * 2) 0 var(--stack);
  max-width: none;
}

/* One parallel context, or one rating axis: the material and every judgement of it,
   in a single card, so it is never ambiguous which comments are about which passage. */
.apx-unit {
  max-width: none;
  border: 1px solid var(--rule); border-radius: 8px;
  background: var(--panel);
  padding: 1rem 1.1rem 1.1rem;
  margin: 0 0 var(--stack);
}
.apx-pc { margin: 0 0 .9rem; }
.pc-title { display: block; font-weight: 650; font-size: 1.08rem; color: var(--ink); }
.pc-sub { display: block; font-size: .93rem; color: var(--ink-mute); margin-top: .1rem; }

/* What was submitted — on paper, so it reads as the object under discussion. */
.apx-form {
  background: var(--paper); border: 1px solid var(--rule-hair); border-radius: 5px;
  padding: .7rem .85rem; margin: 0 0 .6rem; font-size: .88rem; line-height: 1.6;
  max-width: none;
}
.apx-form-label {
  display: block; font-family: var(--mono); font-size: .66rem; text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink-mute); margin-bottom: .3rem;
}

/* Each judge: who, and what they gave. The comment follows underneath. */
.apx-eval {
  display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  margin: 1.1rem 0 .2rem; max-width: none;
  font-family: var(--mono); font-size: .8rem;
  border-top: 1px solid var(--rule-hair); padding-top: .7rem;
}
.apx-eval strong { color: var(--ink); font-weight: 650; }
.apx-rating {
  margin-left: auto; color: var(--accent); font-weight: 650;
  background: var(--accent-bg); border-radius: 2px; padding: .08em .5em;
}
.apx-eval + p { margin: 0 0 .2rem; font-size: .92rem; line-height: 1.55; color: var(--ink-soft); }

.apx-admin {
  border-top: 2px solid var(--ink); padding-top: .7rem;
  margin: 1.2rem 0 0; font-size: .92rem; color: var(--ink-soft); max-width: none;
}
.apx-admin strong {
  display: block; font-family: var(--mono); font-size: .68rem; text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink-mute); margin-bottom: .25rem;
}


/* ------------------------------------------- the paper's contents, with its gaps
 *
 * This list is the site's answer to a real problem: it reproduces the paper's words
 * and tables, so it READS like the paper while carrying about half of it. A banner
 * saying "this is not the full paper" only reaches a reader who stops for banners,
 * and reaches nobody who lands on /leaderboards from a search result.
 *
 * So the contents list carries every section of the paper, and the ones this site
 * does not have are visibly present and visibly not links. The solid rules mark what
 * is here, the faint dashed ones what is not; down 45 entries that contrast is
 * readable as a shape, before a single label has been read.
 */
.paper-toc { list-style: none; margin: 0; padding: 0; }
.paper-toc a,
.paper-toc .ol-absent span {
  display: block; text-decoration: none;
  padding: .26rem .7rem; border-left: 2px solid var(--rule-hair);
}
.paper-toc .ol-2 > a, .paper-toc .ol-2 > span { font-weight: 600; color: var(--ink-soft); }
.paper-toc .ol-3 > a, .paper-toc .ol-3 > span {
  padding-left: 1.5rem; font-size: .95em; color: var(--ink-mute);
}
.paper-toc a:hover { color: var(--ink); background: var(--paper-sunk); }
.paper-toc a { border-left-color: var(--rule); }
.paper-toc .is-here > a { color: var(--ink); border-left-color: var(--accent); }

/* Not on this site. Muted, and dashed so the difference survives being printed,
   being viewed in greyscale, or being read by someone who cannot separate the two
   greys — the message must not rest on colour alone. */
/* Absent sections read as SHADED BLOCKS, not as slightly different lines. The
   omissions are contiguous runs — 3.4-3.5, 4.1-4.5, 6 through the references,
   appendices A-B — so a tinted ground turns each run into a visible band, and the
   shape of what is missing is legible before any label is read. A border-only
   distinction was not: 3.1-3.3 and 3.4-3.5 looked the same at a glance, which is
   precisely the misreading this exists to prevent. */
.paper-toc .ol-absent span {
  color: var(--ink-mute); font-style: italic;
  background: var(--paper-sunk);
  border-left: 2px dashed var(--rule);
  cursor: default;
}
/* No opacity here, for the second time in this file: --ink-mute clears 4.5:1 on
   paper and any multiplier drops it under. What separates absent from present is
   the dashed rule and the absence of link styling, neither of which costs contrast.
   Making the unavailable half illegible would defeat the purpose — it is there to
   be read. */

.toc-legend {
  margin: .9rem .7rem 1.4rem; font-size: .72rem; line-height: 1.45;
  color: var(--ink-mute); border-top: 1px solid var(--rule-hair); padding-top: .6rem;
}

/* "(abridged)" in the h1 of a page that carries only part of its paper section.
   Set at the weight and colour of an editorial note rather than of the title, so it
   reads as a qualifier on the heading instead of as part of the section's name. */
.abridged {
  font-weight: 400; font-size: .5em; letter-spacing: 0;
  color: var(--ink-mute); white-space: nowrap;
}
h1 .abridged { vertical-align: .35em; }

/* h4 exists because the eight former pages were demoted a level when they were
   joined into one document; it is the paper's deepest heading. */
h4 {
  font-size: 1rem; font-weight: 650; color: var(--ink-soft);
  margin: calc(var(--stack) * 1.2) 0 .4rem;
}

/* Scroll-spy: the section the reader is in. Same accent rule as a chosen page had,
   because it means the same thing — you are here. */
.paper-toc li.is-here > a {
  color: var(--ink); background: var(--accent-bg);
  /* 2px, matching every other entry: a thicker rule would shift the label a pixel
     right as the highlight moves down the list, and that jitter is visible when the
     thing is following a scroll. */
  border-left-color: var(--accent); font-weight: 600;
}
/* A hue, not a grey. --paper-sunk was too close to the paper to find at a glance,
   and it is also what the absent entries sit on, so the one thing that moves while
   you read wore the same ground as the 21 things that never change. Teal is already
   the site's "you are here" — it marks the chosen column in the metanym table and
   the current page in the header nav — so this adds no new colour to the system. */

/* ------------------------------------------------------------- the apex page
 *
 * archetypes.ai itself: a masthead and a list of the work. Deliberately not the
 * paper site's chrome — no contents sidebar, no scroll-spy — because this page is
 * a door, and a door with a table of contents is a filing cabinet.
 */
.home { background: var(--paper); }

.home-head {
  max-width: 62rem; margin: 0 auto;
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: .6rem 2rem;
  padding: 1.6rem var(--gutter) 1.3rem;
  border-bottom: 1px solid var(--ink);
}
.home-id { display: flex; align-items: baseline; flex-wrap: wrap; gap: .3rem .85rem; }
.home-wordmark {
  font-family: var(--mono); font-size: 1.15rem; font-weight: 600;
  letter-spacing: .04em; color: var(--ink);
}
/* The tagline is a gloss on the name, so it is set as one: same line, lighter, and
   it drops below the name rather than truncating when the line runs out. */
.home-tagline { font-size: .95rem; color: var(--ink-mute); }
.home-contact { margin: 0; font-size: .88rem; color: var(--ink-mute); }

.home-main { max-width: 62rem; margin: 0 auto; padding: clamp(2rem, 5vw, 3.4rem) var(--gutter) 4rem; }

/* One work per row: figure beside text on a wide screen, stacked on a narrow one.
   A list, not a hero — the second entry is the whole reason the paper lives at
   /metanym-game/ instead of here, so the layout should already expect it. */
.home-work {
  display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: clamp(1.2rem, 3vw, 2.4rem); align-items: center;
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  background: var(--panel); border: 1px solid var(--rule); border-radius: 10px;
}
.home-work + .home-work { margin-top: 1.4rem; }
.home-figwrap { min-width: 0; }
.home-fig {
  display: block; background: var(--paper); border-radius: 6px; padding: .5rem;
  border: 1px solid var(--rule-hair);
}
.home-fig img { display: block; width: 100%; height: auto; }

.home-eyebrow {
  margin: 0 0 .5rem; font-family: var(--mono); font-size: .68rem;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-mute);
}
.home-work-title { font-size: clamp(1.25rem, 2.6vw, 1.6rem); margin: 0 0 .7rem; line-height: 1.25; }
.home-work-title a { color: var(--ink); text-decoration: none; }
.home-work-title a:hover { text-decoration: underline; text-underline-offset: .16em; }
.home-blurb { margin: 0 0 1.1rem; font-size: 1rem; line-height: 1.55; color: var(--ink-soft); }

.home-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .6rem 1.1rem; margin: 0; }
.home-cta {
  font-family: var(--mono); font-size: .8rem; text-decoration: none;
  background: var(--ink); color: var(--paper);
  padding: .55em .9em; border-radius: 4px;
  /* 44px, so the one thing this page exists to be tapped is tappable. */
  min-height: 44px; display: inline-flex; align-items: center;
}
.home-cta:hover { background: var(--accent); }
.home-meta-link { font-family: var(--mono); font-size: .78rem; color: var(--ink-mute); }

.home-foot {
  max-width: 62rem; margin: 0 auto;
  border-top: 1px solid var(--rule); padding: 1.2rem var(--gutter) 3rem;
  font-family: var(--mono); font-size: .72rem; color: var(--ink-mute);
}

@media (max-width: 46rem) {
  .home-work { grid-template-columns: minmax(0, 1fr); }
  /* Text first on a phone: the figure is evidence for the claim, not the claim. */
  .home-fig { order: 2; }
  .home-work-body { order: 1; }
}

/* ------------------------------------------------------- phone (last on purpose)
 *
 * These overrides must be the LAST rules in the file. A media query adds no
 * specificity, so a narrow-width block placed mid-file loses to any equally
 * specific rule below it — which is exactly what happened: .constructs padding is
 * declared at ~line 500 and silently won over an identical selector in a 26rem
 * block at ~line 444, leaving the table 314px wide in a 320px viewport.
 *
 * 26rem covers the 320px and 390px classes. Both components have a width floor set
 * by cell padding rather than by their content, so tightening padding is enough;
 * neither is made a horizontal scroller, which would hide columns rather than fit
 * them.
 */
@media (max-width: 26rem) {
  .we table { font-size: .72rem; }
  .we th, .we td { padding: .3em .3em; }
  .we-panel { padding: .5rem .4rem .55rem; }
  .we-col { padding: .35em .3em; }
  /* Five columns cannot be made legible in 280px. Below this width the grid scrolls
     inside its own panel rather than pushing the document sideways -- the reader
     swipes the table, which is the expected phone gesture, instead of the page
     drifting off-centre. Safe here (unlike .constructs) because this exhibit has no
     popovers for the new clipping context to cut off. */
  .we-panel { max-width: 100%; overflow-x: auto; }

  .constructs { font-size: .78rem; }
  .constructs th, .constructs td { padding: .4em .3em; }
  .constructs th.construct { width: auto; }
}

/* The contents, as a disclosure, on the widths where the sidebar is gone.
   Below 62rem .sidebar is display:none, which left the phone with only the eight
   top-level links in the header scroller — the site's actual contents, forty
   entries deep, were unreachable. */
.toc-phone { display: none; }
@media (max-width: 62rem) {
  .toc-phone {
    display: block; margin: 0 0 var(--stack);
    border: 1px solid var(--rule); border-radius: 6px; background: var(--paper-sunk);
  }
  .toc-phone > summary {
    font-family: var(--mono); font-size: .74rem; text-transform: uppercase;
    letter-spacing: .1em; color: var(--ink-soft);
    padding: .8rem 1rem; cursor: pointer;
    /* 44px minimum touch target (WCAG 2.5.5) — .8rem padding on a .74rem line
       clears it, but state it rather than leave it to arithmetic. */
    min-height: 44px; display: flex; align-items: center; gap: .55rem;
  }
  /* display:flex on a <summary> suppresses the UA disclosure triangle, so the
     control loses the one mark that says it opens. Supply it explicitly. */
  .toc-phone > summary::-webkit-details-marker { display: none; }
  .toc-phone > summary::marker { content: ''; }
  .toc-phone > summary::before {
    content: '\25B8'; font-size: .9em; color: var(--ink-mute);
    transition: transform .15s ease;
  }
  .toc-phone[open] > summary::before { transform: rotate(90deg); }
  .toc-phone[open] > summary { border-bottom: 1px solid var(--rule); }
  .toc-phone > nav { padding: .8rem 0 1rem; font-size: .82rem; line-height: 1.35; }
  .toc-phone .sidebar-links { margin: 0 1rem 1rem; }
  /* Every contents entry is a tap target. Padding alone left them at 29-36px
     because the padding is rem-based while the line box is em-based; a min-height
     states the floor directly instead of arriving at it by arithmetic.
     44px is WCAG 2.5.5 (AAA) and the iOS HIG figure. */
  .toc-phone .toc-page-link,
  .toc-phone .toc-subs a,
  .toc-phone .paper-toc a,
  .toc-phone .paper-toc .ol-absent span,
  .toc-phone .sidebar-links a {
    min-height: 44px; display: flex; align-items: center;
  }
  /* The absent entries get the same height as the links even though they are not
     tappable: an inconsistent rhythm would read as a rendering fault rather than as
     a deliberate distinction, and the shaded bands only work if they are the same
     shape as what surrounds them. */
  .toc-phone .paper-toc a { padding: .4rem 1rem; }
  .toc-phone .paper-toc .ol-3 > a,
  .toc-phone .paper-toc .ol-3 > span { padding-left: 1.8rem; }
  .toc-phone .toc-page-link { padding: .4rem 1rem; }
  .toc-phone .toc-subs a { padding: .4rem 1rem .4rem 1.8rem; }
  .toc-phone .sidebar-links a { padding: .4rem 1rem; }
}

@media (max-width: 30rem) {
  /* clamp(2.2rem, 6vw, 3.6rem) bottoms out at 2.2rem, so on a phone the floor —
     not the viewport term — set the size, and an eleven-word paper title filled
     the entire first screen before a word of the abstract. */
  h1 { font-size: 1.85rem; letter-spacing: -.02em; }
  .page > h1 + h3 { font-size: 1.05rem; }

  /* These tables already scroll sideways inside .scroll-x, so there is nothing to
     gain by breaking `claude-opus-4.0` across four lines — it only makes the rows
     tall enough to hide the shape of the ranking. */
  .lb .model-name, .lb .ci { white-space: nowrap; }
  .ranked-table td, .ranked-table th { white-space: nowrap; }
}

/* Wide tables scroll, but a table cropped exactly at the viewport edge looks like a
   table that ends there. A shadow at the edges says there is more.

   The textbook version of this pairs each shadow with a paper-coloured cover on
   `background-attachment: local`, so the shadow vanishes at the end of the travel.
   Not here: the cover would sit on top of the heatmap cells, washing colours the
   site copies from the paper exactly. A shadow that stays visible is the cheaper
   error than a leaderboard whose end columns are tinted paper-white.

   Scoped to the widths where these tables genuinely overflow. */
@media (max-width: 62rem) {
  /* background-IMAGE, not the background shorthand: the shorthand would reset
     background-color and take the frame's tint with it. */
  /* RIGHT edge only. A shadow on the left says "there is content back that way",
     and at rest there is not — the table starts flush. These tables are wider than
     any phone, so the right edge is the true state in all but the last swipe, while
     the left edge would have been false on the first and most common one.

     background-IMAGE, not the background shorthand: the shorthand resets
     background-color and would take the frame's tint with it. */
  .scroll-x {
    background-image:
      linear-gradient(to left, hsl(220 13% 9% / .12), hsl(220 13% 9% / 0));
    background-size: .9rem 100%;
    background-position: right center;
    background-repeat: no-repeat;
  }
}

/* The page's own name, beside the site's. The wordmark says where you are on the
   web; this says which piece of the work you are reading. */
.crumb { color: var(--rule); font-family: var(--mono); font-size: .95rem; }
.crumb-page {
  font-family: var(--mono); font-size: .82rem; letter-spacing: .02em;
  color: var(--ink-mute);
}
@media (max-width: 34rem) {
  /* On a phone the wordmark alone is the orientation; the page title is already
     the first heading under it, so this would only repeat it. */
  .crumb, .crumb-page { display: none; }
}

/* The 404 has no figure, so it must not keep the figure's column. */
.home-404 { grid-template-columns: minmax(0, 1fr); }
