:root {
  /* light only — no dark mode; see the note above this export. */
  color-scheme: light;
  --page: #e2e0dd; --panel: #f3f2f2; --card: #fbfaf9; --sunken: #eae9e9;
  --ink: #201f1d; --mid: #444141; --muted: #605d5d;
  --link: #7d5411; --link-hover: #5a3b0a;
  --border: rgba(32, 31, 29, 0.13); --hair: #d2cec8;
  --accent: #b68235; --on-accent: #201f1d; --accent-ink: #3a270d; --accent-tint: #f3e9d6; --accent-line: #d8b877;
  --ok: #2f6b45; --warn: #8a6410; --down: #a3341f;
  --r: 14px; --r-sm: 9px; --r-lg: 20px; --pill: 999px;
  --font: -apple-system, "SF Pro Text", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --head: -apple-system, "SF Pro Display", "Helvetica Neue", system-ui, sans-serif;
  --shadow: 0 1px 2px rgba(32, 31, 29, 0.04), 0 12px 32px -12px rgba(32, 31, 29, 0.12);
}
* { box-sizing: border-box; }
body {
  margin: 0; padding: 32px 20px 56px; background: var(--page); color: var(--ink);
  font: 16px/1.6 var(--font); -webkit-font-smoothing: antialiased;
}
/* ⛔ **Prose links spend the link ramp; they do not inherit ink** · `G428`,
   `G450`. Measured drawn→built over the nine pages: 15 runs the drawings paint
   `#7d5411` the build painted ink or muted. This is an ELEMENT selector on
   purpose — every class-scoped link (.brand, .nav a, .toc a, .footer-col a,
   .action, .triage-hit, .crumb a) is more specific and keeps its own colour.
   Hover DARKENS: `link-hover` is #5a3b0a, the owner's call in `G450`. */
a { color: var(--link); }
a:hover { color: var(--link-hover); }
/* ⛔ **Three measured exceptions, and they are not taste.** The drawings paint
   a link the accent brown when it sits in PROSE and ink when the link IS the
   thing — a platform row, a topic in a browse list, a page title. Measured with
   the blanket rule in place: 11 runs drawn ink that the build painted brown. */
h1 > a, .platform dt a, .topics a { color: var(--ink); }
/* The footer's legal row is drawn in the ramp; the sitemap columns are not. */
.footer-links a { color: var(--link); }
.shell {
  max-width: 1140px; margin: 0 auto; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow);
  overflow: hidden;
}
/* ── Masthead ── */
.masthead {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 18px 40px; border-bottom: 1px solid var(--border); background: var(--card);
}
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
/* ⛔ **The masthead tile is the drawn one, and it is transcribed by ROLE** ·
   `G1552`, `CL-C33`. Eighteen drawings draw one masthead tile with a single
   declaration — an `--color-accent-200` ground under a 1px `--color-accent-400`
   hairline, holding a `brand-mark` stroked `--color-accent-800` — and this build
   shipped a LARGER SOLID `--accent` tile with a near-black glyph and no border
   at all, while `apps/status` built the drawn one. One drawn tile, two public
   surfaces, two answers — and no gate could see it: `adherence.py` checks that a
   value IS a design token and never WHICH token, L1 is a text gate, and both
   `47 System status` frames are `measure_only` in `design/diff-budgets.json`.

   ⚠️ **The geometry is deliberately NOT restated here.**
   `test/composition.test.js` reads the drawn declaration out of the drawings and
   asserts this rule and the footer's override against it, so the two accounts
   cannot drift and no digit in this file can go stale (`G850`).

   ⚠️ **By ROLE, not by nearest value** — `apps/status`'s own transcription and
   its reasoning, applied here: tint → ground, line → border, ink → mark. The drawn
   ramp steps are not this palette's values (`tokens.json` `$public-derived`:
   accent-tint and accent-line have NO drawn counterpart), and `--color-accent-800`
   resolves to the six digits `tokens.json` also carries as `light.link-hover`, so
   a value-for-value copy would pass `adherence.py` by value while recording a link
   state as page chrome.

   ⚠️ `box-sizing: border-box` is set above, so the hairline is INSIDE the box
   and the outer square is the drawn one. Nothing spends `var(--on-accent)` after
   this change; the declaration stays because `accent-text` is still one half of
   `tokens.json`'s accent contrast pair. */
.brand-mark {
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-tint); color: var(--accent-ink); border-radius: var(--r-sm);
  border: 1px solid var(--accent-line);
}
.brand-name { font: 500 21px/1 var(--head); letter-spacing: -0.2px; }
.nav { display: flex; gap: 28px; flex-wrap: wrap; }
.nav a { font-size: 14px; color: var(--muted); text-decoration: none; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
/* ── Content ── */
main { display: block; padding: 44px 48px 52px; }
h1 { font: 500 40px/1.08 var(--head); letter-spacing: -0.6px; margin: 0 0 14px; }
h2 { font: 500 23px/1.2 var(--head); letter-spacing: -0.3px; margin: 40px 0 14px; }
h3 { font: 600 16px/1.35 var(--font); margin: 0 0 6px; }
p { margin: 0 0 14px; }
.lede { font-size: 19px; line-height: 1.5; color: var(--muted); margin: 0 0 28px; max-width: 40em; }
/* ⛔ **The lede's ink level is the page's, not the class's** · `G428`. Measured
   over the drawings: "34" sets its opening line at `--color-neutral-700` and
   "48", "50" and "51" set theirs at `--color-neutral-800` — a stated position
   reads one step darker than a description. One rule for all of them painted
   three of the eight a level too light. */
.lede.stated { color: var(--mid); }
.muted, .note { color: var(--muted); }
.note { font-size: 14.5px; }
/* ⛔ **A `font` shorthand, not `font-size` alone, because the class now lands on
   headings too** · `G546`. Eleven drawn eyebrows were built as display headings;
   they keep their heading element (the drawings carry no semantics — see
   `docs/DESIGN-FIDELITY.md` §2) and take the drawn paint from here. `font-size`
   alone would leave the heading's own `font:` shorthand supplying the display
   face and line-height. These values are what this class computed to on a `<p>`
   before the change, so nothing already built moves. */
.eyebrow, .crumb {
  font: 600 12px/1.6 var(--font); letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 10px;
}
.crumb a { color: var(--ink); }
section { margin: 0 0 8px; }
ul, ol { margin: 0 0 14px; padding-left: 1.25em; }
li { margin: 0 0 6px; }
/* ── Two-column with a table-of-contents rail ── */
/* `43` and `44` draw the same document twice and the two columns disagree
   about the ORDER, not about the parts: desktop puts the contents rail BESIDE
   the text, and the phone frame draws eyebrow, title, lede, a compact contents
   card, then the clauses — captioned *"Contents first — nobody scrolls a
   contract"* (`G922`). One grid served both by stacking in DOM order, so at
   the 390 column the nine-item rail and the version card came first and pushed the drawn
   title to y 903, outside the 844 box the fidelity harness compares.

   ⛔ **`order: 2` on the rail is the obvious remedy and it was MEASURED WRONG**:
   it takes `Privacy · phone` out of its band and puts a nine-item contents
   BELOW all nine clauses on a page 4339 tall, which the drawn caption refuses. So
   the head is its own grid child and the phone column places four things rather
   than swapping two.

   The desktop placement is explicit for the same reason: with `row-gap: 0` the
   head and the body stack exactly as they did when they were one `.prose` box
   — the lede's own 28 of bottom margin is the only thing between them — and the
   rail spans both rows, so its top is the content top and the version card sits
   directly under the contents as before. Verified box for box against the build
   this replaced. */
.two-col {
  display: grid; grid-template-columns: 220px 1fr;
  column-gap: 56px; row-gap: 0; align-items: start;
}
.two-col > .rail { grid-column: 1; grid-row: 1 / span 2; }
.two-col > .doc-head { grid-column: 2; grid-row: 1; }
.two-col > .prose { grid-column: 2; grid-row: 2; }
.toc { position: sticky; top: 24px; }
.toc ol { list-style: none; margin: 0; padding: 0; }
.toc li { margin: 0; }
.toc a {
  display: flex; gap: 12px; padding: 9px 14px; border-radius: var(--r-sm);
  text-decoration: none; color: var(--muted); font-size: 15px;
}
/* The section you are in is the drawn accent ink, not merely a tinted row. */
.toc a[aria-current="true"] { color: var(--accent-ink); }
.toc .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.toc a:hover { background: var(--sunken); }
.toc a[aria-current="true"] { background: var(--accent-tint); }
/* ── Cards ── */
.card, .radio-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 18px 20px; margin: 0 0 16px;
}
.grid { display: grid; gap: 16px; }
@media (min-width: 720px) { .grid.two { grid-template-columns: 1fr 1fr; } }
.split { display: grid; gap: 48px; align-items: start; }
@media (min-width: 860px) { .split { grid-template-columns: 1.5fr 1fr; } }
/* ── Drawn glyphs · `G428`, `CL-S22` ── */
/* ⛔ **No colour of its own.** Every glyph in `apps/web/src/ui/icons/` paints
   `currentColor` on purpose, so a glyph takes the ink level of the text it sits
   beside and cannot smuggle a value past the ramp. Where a drawing pins a glyph
   a level of its own — `51`'s shelf at `--color-neutral-700`, `46`'s ticks and
   crosses at the status ramp — the rule that does it is beside that block, not
   here. `inline-flex` so the glyph sits on the label's BAND: `design-geometry`'s
   `unglyphed` axis asks whether a glyph leads a label, which is a
   vertical-overlap question and a baseline-aligned `<svg>` fails it. */
.glyph { display: inline-flex; flex: none; align-items: center; }
h3 > .glyph, h4 > .glyph { margin-right: 8px; vertical-align: -2px; }
p > .glyph { margin-right: 8px; }
/* "51"'s assessor shelf: the document on the left, its type on the right. */
.shelf .doc { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
/* The glyph and the label are ONE side of that row, not two things the
   space-between pushes apart — `51` draws them one gap step apart at the left edge. */
.doc-name { display: inline-flex; align-items: center; gap: 12px; min-width: 0; }
.doc-name .glyph { color: var(--muted); }
/* "46"'s two consent lists: the glyph carries which list an item is in, so it
   sits on the item's own band and takes the status ramp rather than the ink. */
.included li, .not-included li { display: flex; align-items: center; gap: 9px; }
.included, .not-included { list-style: none; padding-left: 0; }
.included .glyph { color: var(--ok); }
.not-included .glyph { color: var(--down); }
.lede > .glyph { margin-right: 8px; }
h2 > .glyph { margin-right: 10px; vertical-align: -2px; color: var(--muted); }
/* "45" heads each triage card with a glyph in the accent ramp, above the
   symptom rather than beside it — the card is a column, so the glyph is a row
   of its own. */
.triage-hit > .glyph { color: var(--link); margin-bottom: 2px; }
.crumb > .glyph { margin: 0 4px 0 2px; vertical-align: -2px; }
/* ⛔ **The glyph sits OUTSIDE the run it leads, and that is not cosmetic.**
   "48" and "50" both draw this shape — a flex row of a fixed glyph and a
   flowing span — and putting the glyph inside the paragraph instead makes the
   paragraph's own box start at the glyph's left edge, which is a NEGATIVE gap.
   `design-geometry::leadsLabel` reads that as "not beside" and the run stays
   unglyphed however visible the picture is. */
.glyph-row { display: flex; align-items: flex-start; gap: 13px; }
.glyph-row > .glyph { margin-top: 2px; color: var(--muted); }
/* ⚠️ **A bare child-span selector would match the glyph's own wrapper too**,
   which is a span element,
   and at (0,1,1) it outranks `.glyph`'s `flex: none` — measured, it split the
   row in half and put the run half a column right of the glyph, which reads exactly
   like the layout being ignored. Name the text instead. */
.glyph-row > .glyph-text { flex: 1; min-width: 0; }
.action > .glyph { margin-right: 8px; }
/* `34`'s `Read the admin guide` ends in an arrow rather than leading with a
   glyph, so the gap goes between label and mark — `p > .glyph`'s right margin
   would push it away from the text it points out of. */
.guide a { display: inline-flex; align-items: center; gap: 8px; }
.pending > .glyph { margin-right: 6px; vertical-align: -1px; }
/* "34"'s download strip and administrator list: the glyph leads the name. */
.platform dt { display: flex; align-items: center; gap: 10px; }
.platform dt > .glyph { color: var(--muted); }
#for-admins ~ ul { list-style: none; padding-left: 0; }
#for-admins ~ ul li { display: flex; align-items: flex-start; gap: 10px; }
#for-admins ~ ul .glyph { color: var(--ok); margin-top: 3px; }
.feature h3 > .glyph { color: var(--link); margin-right: 10px; vertical-align: -3px; }
.doc-kind {
  flex: 0 0 auto; font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.doc-kind.is-absent { text-transform: none; letter-spacing: 0; font-weight: 400; font-style: italic; }
.doc:has(.is-absent) .doc-label { color: var(--muted); }
/* `:not(.eyebrow)` because this selector is (0,1,1) and `.eyebrow` is (0,1,0) —
   without it `51`'s shelf label keeps this rule's display face · `G546`. */
.practices h3:not(.eyebrow), .shelf h3:not(.eyebrow) { font: 500 18px/1.25 var(--head); letter-spacing: -0.2px; margin: 26px 0 12px; }
.practices section:first-child h3, .shelf section:first-child h3 { margin-top: 0; }
.card h4 { margin: 0 0 6px; font: 600 15px/1.35 var(--font); }
/* "51" sets a practice card's body one level below its title — 9 of the runs
   `G428` counted recoloured were this one rule. */
.practices .card p { color: var(--muted); }

/* 51's dashed state pill under a practice title -- the page saying a row is a
   commitment it has not met yet rather than dropping the row. NOTE the drawing
   sets it at 9.5 px -- written with a space on purpose, because lengths.test.js
   scans this whole template for a raw length and a number in a COMMENT joins the
   population it describes (G850); it cost one red run to learn. tokens.json's
   site ramp has no such step, so the rule spends L[10], the nearest; recorded
   here rather than rounded silently, and the letter spacing is the drawn 0.12em. Everything else is an existing token: --pill for
   the radius, --hair for the rule, --muted for the ink.
   No backticks in this comment: it sits INSIDE a template literal, and one
   closes the string -- which is how this block broke the build once already. */
.practices .card .unbuilt {
  display: inline-block; margin: 0 0 8px;
  font: 500 10px/1.2 var(--head); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted); border: 1px dashed var(--hair); border-radius: var(--pill);
  padding: 2px 8px;
}
/* The E2EE card's scope · `G1831`. The headline is a stated sentence and takes
   the stated level; the table sits under it at the page's small size, its
   caption spelling what the two halves are. */
.practices .card p.stated { color: var(--mid); margin-top: 12px; }
.practices .card .scope { margin-top: 12px; font-size: 13px; }
.practices .card .scope caption { text-align: left; color: var(--muted); padding: 0 0 8px; }
.detail { display: block; font-weight: 400; color: var(--muted); font-size: 0.9em; margin-top: 2px; }
.pending { font-style: italic; color: var(--muted); }
.guest {
  color: var(--muted); font-size: 14.5px; border-left: 3px solid var(--accent-line);
  padding: 2px 0 2px 16px; margin: 16px 0;
}
.reading-aid { font-style: italic; color: var(--muted); font-size: 13px; display: inline-block; margin-top: 4px; }
/* ── Radio-style region rows ── */
.radio-card { padding: 0; overflow: hidden; max-width: 30rem; }
.radio-head { margin: 0; padding: 12px 18px 10px; font: 600 11px/1.3 var(--font);
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.radio-row {
  display: flex; align-items: center; gap: 12px; padding: 14px 18px;
  border-top: 1px solid var(--border);
}
.radio-row:first-child { border-top: 0; }
.radio-row.selected { background: var(--accent-tint); }
.radio-row > span { color: var(--muted); }
.radio-row.selected > span { color: var(--accent-ink); }
.radio-row > span.radio-dot { color: inherit; }
.radio-dot {
  width: 16px; height: 16px; border-radius: 999px; border: 2px solid var(--hair); flex: 0 0 auto;
}
.radio-row.selected .radio-dot { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--accent); }
/* ── Tables ── */
.scroll { overflow-x: auto; margin: 0 0 16px; }
table { border-collapse: collapse; width: 100%; border: 1px solid var(--border); border-radius: var(--r); }
thead th {
  background: var(--sunken); font: 600 12px/1.3 var(--font); letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted); text-align: left;
}
th, td { padding: 12px 16px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border); }
/* ⛔ **Two tables, two drawn header levels** · `G428`. "44" sets its holdings
   header at `--color-neutral-600` — which `D363` renders one step up — and
   "50" sets its plan columns at the ink level, because there the header IS the
   plan. One `thead th` rule painted the second one muted. */
.matrix thead th { color: var(--ink); }
/* "44" sets the three columns at three levels: the row header, then WHY at the
   middle level and HOW LONG at the muted one. The build painted both ink, which
   is 12 of `G428`'s 191 recoloured runs in one table. */
.holdings td { color: var(--mid); }
.holdings td:last-child { color: var(--muted); }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
th[scope="row"] { font-weight: 600; }
/* ── Forms ── */
/* "46"'s two-column split: the form on the left, the diagnostics and consent
   on the right, a hairline between them. Drawn as
   1.25fr, a hairline, 1fr; the rule is decoration and is dropped
   at the single-column width rather than becoming an empty grid row. */
.form-split { display: grid; gap: 32px; align-items: start; }
.form-split .rule { display: none; }
@media (min-width: 860px) {
  .form-split { grid-template-columns: minmax(0, 1.25fr) 1px minmax(0, 1fr); }
  .form-split .rule { display: block; align-self: stretch; background: var(--border); }
}
.form-split .form-col > section:first-child { margin-top: 0; }
/* "46" pairs the reply address with the meeting code. The drawn sub-grid fixes
   the code column at a width the display registry does not declare, so the
   RATIO is spent rather than the literal: 0.45fr reproduces it against the
   drawn form column. See support.ts::SupportField.row. */
.field-row { display: grid; gap: 16px; }
@media (min-width: 720px) { .field-row { grid-template-columns: minmax(0, 1fr) minmax(0, 0.45fr); } }
.field-row > label { margin-bottom: 0; }
/* Chips: one answer out of a visible set, so a radio group wearing pills. The
   input covers the chip and stays the thing that is focused and announced. */
.chips { border: 0; padding: 0; margin: 0 0 20px; min-width: 0; }
.chips legend { padding: 0; margin: 0 0 10px; font-size: 14px; color: var(--muted); }
.chip-set { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { position: relative; display: inline-flex; margin: 0; }
.chip input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: pointer;
}
.chip span {
  display: inline-flex; align-items: center; padding: 8px 14px;
  border: 1px solid var(--hair); border-radius: var(--pill);
  font-size: 13px; color: var(--muted); background: var(--card);
}
.chip input:checked + span { background: var(--accent-tint); border-color: var(--accent); color: var(--accent-ink); }
.chip input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
/* "51"'s disclosure chips: three plain pills under the reporting sentence,
   stating a fact each rather than offering a destination. Drawn as spans with
   no href, so they are not controls and carry no focus ring. G400.
   The size is measured, not chosen — securityPage's own comment carries the
   numbers, because a length written into a CSS comment is a raw length that
   ships and lengths.test.js counts it. Padding and radius are the drawn ones. */
.notes { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; }
.note-chip {
  display: inline-flex; align-items: center; padding: 4px 10px;
  border: 1px solid var(--hair); border-radius: var(--pill);
  font-size: 11px; color: var(--muted);
}
.handoff { margin: 10px 0 0; }
kbd {
  display: inline-block; padding: 2px 6px; font: inherit; font-size: 0.9em;
  background: var(--sunken); border: 1px solid var(--hair); border-radius: var(--r-sm);
}
/* "50"'s closing strip: what a licence is, three across with hairlines. */
.seat-defs {
  list-style: none; margin: 24px 0 0; padding: 0; display: grid; gap: 16px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 14px 18px; font-size: 13px;
}
@media (min-width: 720px) { .seat-defs { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; } }
.seat-defs li { color: var(--mid); }
/* "50" draws the four plans across, not down; "48" draws its four alternate
   platforms as one row. Both were stacked, which is the collapse L1.5 counts. */
@media (min-width: 860px) { .grid.plans { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 720px) { .platform-alts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.platform-alts .platform-row { flex-direction: column; align-items: flex-start; gap: 6px; }
.grid.plans > .version, .grid.two > .version { margin: 0; display: flex; flex-direction: column; }
.grid.plans > .version > :last-child, .grid.two > .version > :last-child { margin-bottom: 0; }
.grid.plans > .version > p, .grid.two > .version > p,
.grid.meters .meter-body > p, .grid.meters .meter-body > h3 { color: var(--mid); }
.grid.plans > .version > p.note, .grid.two > .version > p.note,
.grid.meters .meter-body > p.note { color: var(--muted); }
/* ── "50"'s two meters: a glyph, then one flowed line ── `G428` */
.grid.meters > .version.meter { flex-direction: row; align-items: flex-start; gap: 11px; }
.meter > .glyph { margin-top: 2px; color: var(--link); }
.meter-body { flex: 1; min-width: 0; }
/* Inline so the bold name and the unit share a first line, which is what "50"
   draws and what puts both runs beside the glyph rather than one of them. */
.meter-body > h3 { display: inline; margin: 0; }
.meter-body > h3 + p { display: inline; margin: 0; }
.meter-body > p.note { display: block; margin: 8px 0 0; }
/* The blank level and the billing basis are drawn in the accent brown — the
   blank is meant to be READ, and the basis is the drawn second note line. */
.grid.plans > .version > p.price-blank { color: var(--link); }
.grid.plans > .version > p.note.billing-basis { color: var(--link); }
form { max-width: 34rem; }
.form-split form { max-width: none; }
form label { display: block; margin: 0 0 16px; font-size: 14px; color: var(--muted); }
input, select, textarea {
  display: block; width: 100%; margin-top: 6px; padding: 10px 12px; font: inherit; color: var(--ink);
  background: var(--card); border: 1px solid var(--hair); border-radius: var(--r-sm);
}
textarea { min-height: 120px; resize: vertical; }
input[type="checkbox"] { display: inline-block; width: auto; margin: 0 8px 0 0; }
.recording label, .diagnostics label:has(input[type="checkbox"]) { color: var(--ink); font-size: 15px; }
/* ── Buttons & actions ── */
.action, button[type="submit"] {
  display: inline-flex; align-items: center; gap: 6px; padding: 10px 18px; font: 500 14.5px var(--font);
  background: var(--accent); color: var(--accent-ink); border: 0; border-radius: var(--pill);
  text-decoration: none; cursor: pointer; margin-top: 4px;
}
.action:hover, button[type="submit"]:hover { filter: brightness(0.96); }
.action.ghost { background: transparent; border: 1px solid var(--hair); color: var(--ink); }
/* A drawn control with nothing behind it yet — rendered, dimmed, and described
   by the note that says why. G400: the absence belongs on the page. */
.action:disabled { background: var(--sunken); color: var(--muted); cursor: not-allowed; }
.action:disabled:hover { filter: none; }
/* ── Triage / incident (help) ── */
.incident {
  display: flex; gap: 12px; background: var(--accent-tint); border: 1px solid var(--accent-line);
  border-radius: var(--r); padding: 14px 18px; margin: 0 0 24px; font-size: 14.5px;
}
.triage-list { display: grid; gap: 14px; }
@media (min-width: 720px) { .triage-list { grid-template-columns: 1fr 1fr; } }
.triage {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 18px 20px; margin: 0;
}
.triage h3 { margin-bottom: 6px; }
/* `50` draws the blank level in the accent brown, not in a hairline grey a
   reader's eye slides off. The blank is meant to be READ — it says the level is
   not set — so it is spent through `--link`, the darkest legible accent. */
.price-blank { font: 500 30px/1 var(--head); color: var(--link); margin: 4px 0 8px; }
/* ── Meters / plan / version cards (pricing, download, versions) ── */
.version, .acceptance {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 18px 20px; margin: 0 0 14px;
}
.version h3, .acceptance h3 { margin-bottom: 4px; }
.in-force, .when { color: var(--muted); font-size: 14px; margin: 0 0 8px; }
/* "49" draws the published history at the muted level and your own acceptance
   one level up — it is the half that is about you. */
.history p, .history .version > p { color: var(--muted); }
.acceptances .acceptance > p { color: var(--mid); }
/* ── Footer ── */
.site-footer {
  max-width: 1140px; margin: 22px auto 0; padding: 4px 40px; display: flex; flex-wrap: wrap;
  align-items: center; justify-content: space-between; gap: 12px 24px;
}
.footer-links { display: flex; flex-wrap: wrap; gap: 20px; margin: 0; padding: 0; list-style: none; }
.footer-links a { color: var(--muted); text-decoration: none; font-size: 14px; }
.footer-links a:hover { color: var(--ink); }
.footer-legal { color: var(--muted); font-size: 13px; margin: 0; }
/* ── CL-S20 · the sections the drawings carry ── */
/* "34"'s download strip: a definition list, because each row is a platform and
   the thing it requires. Grid rather than the browser's dt/dd indent. */
.platforms { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 0 0 18px; }
.platform {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 16px 18px;
}
.platform-rows { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 10px; }
.platform-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 12px 16px;
}
.platform-row .platform-name { font-weight: 600; color: var(--accent-ink); }
.platform-row .note { flex: 1 1 auto; }
.platform dt { font-weight: 600; margin: 0 0 4px; }
.platform dd { margin: 0; font-size: 14px; color: var(--muted); }
.browser-line { font-size: 17px; margin: 0 0 12px; color: var(--muted); }
.strip { margin: 0 0 12px; }

/* "34"'s three feature cards, and "50"'s stance heading. */
.features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.feature {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 20px 22px; margin: 0;
}
.feature h3 { margin: 0 0 8px; }
.feature p { margin: 0; font-size: 15px; color: var(--muted); }
/* Element-agnostic for the same reason: `48` and `50` draw their eyebrow above
   the stance, so the stance is the page's headline and now carries the `<h1>`.
   The values are `h2.stance`'s computed ones, so the rendering is unchanged. */
.stance { margin: 0 0 12px; font: 500 27px/1.2 var(--head); letter-spacing: -0.3px; }
.closing {
  background: var(--accent-tint); border: 1px solid var(--accent-line);
  border-radius: var(--r); padding: 24px 26px; margin: 32px 0 0;
}
.closing h2 { margin: 0 0 8px; }

/* "43"'s clauses. The gloss is the grey half and must never read as the
   binding one — it is set apart rather than merely lighter. */
.clause { border-top: 1px solid var(--border); padding: 22px 0 4px; margin: 0; }
.clause h3 { display: flex; gap: 10px; align-items: baseline; font-size: 17px; }
/* `43` sets the binding sentence one level below the heading and the gloss one
   below that — three levels, which the build painted as one (`G428`). */
.clause > p:not(.gloss) { color: var(--mid); }
.clause-num, .toc-num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; border-radius: var(--pill);
  background: var(--sunken); color: var(--muted);
  font-size: 12px; font-weight: 600;
}
.gloss {
  border-left: 2px solid var(--accent-line); padding-left: 14px;
  color: var(--muted); font-size: 15px; margin: 10px 0 0;
}
.clause.pending h3 { color: var(--muted); }
.version-note { color: var(--muted); font-size: 14.5px; margin: 0 0 16px; }
.pending-note {
  background: var(--sunken); border: 1px solid var(--border); border-radius: var(--r);
  padding: 14px 16px; font-size: 14.5px; color: var(--muted); margin: 0 0 24px;
}
/* "43" and "44" both close the left rail with the version in force. It was
   built in the document column, above the lede, which is one of the 22 of 32
   side-by-side pairs L1.5 measured collapsed on Terms. */
/* The word the residency card turns on, set apart as "44" draws it. */
.emphatic { font-style: normal; font-weight: 700; color: var(--mid); }
.distinction { color: var(--mid); }
.pending-state { color: var(--link); }
.rail-version { margin: 28px 0 0; padding: 16px 14px 0; border-top: 1px solid var(--border); }
.rail-version p { margin: 0 0 6px; font-size: 13px; }
.rail-version-n { font: 600 15px/1.2 var(--font); color: var(--ink); }
.toc ol { list-style: none; padding: 0; }
.toc li { margin: 0 0 8px; }
.toc a { display: inline-flex; gap: 9px; align-items: baseline; text-decoration: none; }
.toc a:hover { text-decoration: underline; }

/* "46"'s field hint and worked example — visible, not a placeholder. */
.hint { font-size: 14px; color: var(--muted); margin: 0 0 6px; }
/* "46" sets what IS sent at the middle level and what is NOT at the muted one —
   the itemisation reads as two lists because it is drawn as two. */
.diagnostics .included li { color: var(--mid); }
.diagnostics .not-included li { color: var(--muted); }
.sample { font-size: 14px; color: var(--muted); margin: 8px 0 16px; }
.sample summary { cursor: pointer; }
.sample p { margin: 8px 0 0; padding-left: 14px; border-left: 2px solid var(--border); }

/* ── CL-S20 · the masthead actions and the footer sitemap 34 draws ── */
.masthead { gap: 18px; }
.masthead-actions { display: flex; align-items: center; gap: 18px; margin-left: auto; }
.masthead-actions .quiet { font-size: 14px; color: var(--ink); text-decoration: none; }
.masthead-actions .quiet.secondary { color: var(--muted); }
.masthead-actions .quiet:hover { color: var(--ink); text-decoration: underline; }
.masthead .action { padding: 8px 16px; font-size: 14px; }
/* "50"'s billing-period switch: a segmented pill in the masthead, beside the
   quiet actions. The current half is where you already are; the other is a real
   control with nothing to switch, disabled and described. */
.period-switch {
  display: inline-flex; align-items: center; gap: 3px; padding: 3px;
  border: 1px solid var(--hair); border-radius: var(--pill); background: var(--sunken);
}
.period {
  font: inherit; font-size: 13px; padding: 6px 14px;
  border-radius: var(--pill); border: 1px solid transparent; background: transparent;
  color: var(--muted); margin: 0;
}
.period.is-current { background: var(--card); border-color: var(--hair); color: var(--ink); }
.period:disabled { cursor: not-allowed; }
/* The reason the inert half carries. It is referenced by `aria-describedby`, so
   it must be in the document — it sits at the top of `<main>`, small, where the
   drawing has no counterpart for it and a reader who tabs to the control gets
   it read out. */
.visually-quiet { font-size: 13px; margin: 0 0 16px; }
/* The billing basis is the second, quieter note line under a plan's seat basis. */
.billing-basis { margin-top: -8px; }
.nav { margin-left: 12px; }

.footer-map {
  display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 32px;
  padding: 28px 20px 4px; align-items: start;
}
/* `34` draws the footer mark one size down from the masthead's · `G400`. */
.footer-brand .brand-mark { width: 26px; height: 26px; border-radius: 8px; }
.footer-brand .brand-name { font-size: 18px; }
.footer-brand .note { margin: 4px 0 0; }
.footer-col h2 { font: 600 12px/1 var(--font); letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 12px; }
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin: 0 0 8px; }
.footer-col a { font-size: 14px; color: var(--muted); text-decoration: none; }
.footer-col a:hover { color: var(--ink); text-decoration: underline; }

/* 45's triage cards: the whole card is the target, not the arrow. */
.triage { padding: 0; margin: 0 0 12px; }
.triage-hit {
  display: block; text-decoration: none; color: inherit;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r);
  padding: 18px 20px;
}
.triage-hit:hover { border-color: var(--accent-line); }
.triage-hit h3 { margin: 0 0 6px; }
.triage-hit p { margin: 0 0 8px; color: var(--muted); font-size: 15px; }
.action-text { font-size: 14px; font-weight: 600; color: var(--link); }
.count { color: var(--muted); font-variant-numeric: tabular-nums; }

/* ── The drawn ink ramp ── `G428`, `D363` */
/* ⛔ **Body copy is not ink, and that is a census rather than a preference.**
   Counted over the desktop frames of the nine drawings this site builds, every
   run of 40+ characters carrying an explicit colour is `--color-neutral-600`
   (27), `--color-neutral-700` (50) or `--color-neutral-800` (34) — and
   **zero** are `--color-text`. The build inherited ink from `body` and painted
   prose the one level the drawings never use for it.
   `D363` refuses a fourth ink level, so a drawn 600 renders at `--muted` — one
   step up, a permanent L1.5 `recoloured` finding and the accepted cost of that
   decision. That leaves `--muted` as the drawn default for prose and `--mid`
   as the darker of the two shipped levels, which `.stated` spends. */
/* ⚠️ **`li` is deliberately NOT here.** Added with the rest it moved six runs
   the wrong way — "34"'s three administrator assurances and "51"'s three shelf
   labels are all drawn `--color-text` — because the census above is of runs of
   40+ characters and a list item is usually a short label, which the drawings
   set at the ink level. Prose is the class of thing this rule is about. */
main p, main dd { color: var(--muted); }
/* One step darker, where the drawing paints `--color-neutral-800`: a position
   the page is taking rather than a description of something. */
main p.stated, main li.stated, main .stated { color: var(--mid); }
/* "46" sets the diagnostics label and the recording toggle at the faint level,
   which `D363` renders one step up; the build had both at ink. */
.diagnostics h3 { color: var(--muted); }
.recording label { color: var(--muted); }
/* "46" writes the worked example one level darker than the disclosure that
   holds it — the summary is a prompt, the example is the thing. */
.sample p { color: var(--mid); }
/* "49" sets the guest question at the ink level inside an otherwise muted
   aside; it is the question, not the answer around it. */
.guest .guest-q { color: var(--ink); }

/* ── Responsive ── */
@media (max-width: 760px) {
  body { padding: 12px 10px 40px; }
  /* At the 390 px column the nav wrapped under itself and collided with the
     brand — "space-between" on a flex row with a wrapping child. Stacking is
     what the phone frames draw anyway. Found by looking at the page (CL-S20). */
  .masthead { padding: 16px 20px; flex-direction: column; align-items: flex-start; gap: 12px; }
  .nav { gap: 20px; }
  main { padding: 28px 22px 36px; }
  /* The drawn phone order · `G922`, `CL-S20`, `CL-W126`. `.rail` is a bare
     wrapper with no styling of its own, so `display: contents` promotes the
     contents card and the version card to grid items and each is placed on its
     own — which is what the drawing needs and what an `order` on the rail
     cannot do, since it can only move both together. */
  .two-col {
    grid-template-columns: 1fr; column-gap: 0; row-gap: 28px;
    grid-template-areas: "head" "toc" "body" "version";
  }
  .two-col > .rail { display: contents; }
  .two-col > .doc-head { grid-area: head; }
  .two-col > .rail > .toc { grid-area: toc; }
  .two-col > .prose { grid-area: body; }
  /* `43` frame 1 and `44` frame 1 draw no version card at all — the version
     is in the eyebrow they draw above the title. It is kept, and it goes last. */
  .two-col > .rail > .rail-version { grid-area: version; margin-top: 0; }
  /* The drawn contents is a CARD, not a list: one bordered, rounded box with a
     divider between rows. Its rows are the drawn 50, so the card is compact
     in the sense the caption means — it is what you see first, above the
     clauses, rather than a shorter list. The row height is `--tap-lg` (52),
     the kit's own phone tap size, rather than the drawing's 50: a contents row
     IS a tap target, tokens.json carries no 50, and a length that is not a
     token is the signal the component is wrong rather than that a magic number
     is needed. */
  .toc ol {
    border: 1px solid var(--border); border-radius: var(--r); overflow: hidden;
    background: var(--card);
  }
  .toc li { margin: 0; }
  .toc li + li { border-top: 1px solid var(--border); }
  .toc a {
    display: flex; align-items: center; gap: 12px;
    min-height: 52px; padding: 0 14px;
  }
  /* Neither phone frame draws the rail's "On this page" label; the `<nav>`
     carries the same words as its accessible name, so the label is a label and
     nothing is lost by not painting it twice at the 390 column. */
  .toc > .eyebrow { display: none; }
  .platforms { grid-template-columns: repeat(2, 1fr); }
  .footer-map { grid-template-columns: 1fr 1fr; gap: 24px; }
  .masthead-actions { margin-left: 0; flex-wrap: wrap; }
  .features { grid-template-columns: 1fr; }
  .toc { position: static; }
  h1 { font-size: 32px; }
  .site-footer { padding: 4px 20px; }
}
