/* ===========================================================================
   PRIVI — the shared company palette, light base and one dark opt-in.

   The six colours, their recorded contrast ratios and the reserved-hue rule are
   ShopifyACO/viewer/src/theme.css v4.3 (lens.thirdocular.com). The values below
   are that file's, not an interpretation of it:

     navy      #24273A   primary text, nav, the high-contrast CTA ground
     slate     #596C8E   links, evidence chrome, the PASSING state
     pale      #C7D1DA   borders, quiet containers
     band      #E9EDF1   the pale blue-gray section band
     sand      RESERVED  could not be determined — defined in result.css
     crimson   RESERVED  did not hold — defined in result.css

   ⚠️ THE LAST TWO ARE NAMED HERE AND NOT SPELLED. Their hex values appear in
   `result.css` and nowhere else, and `test/report.test.mjs` greps THIS file for
   them — so writing one into a comment here, even as documentation, fails the
   build. That is deliberate: the one way to be certain a document theme cannot
   render a result hue is for the literal never to enter the file.

   ⚠️ LIGHT IS `:root`, AND THERE IS NO prefers-color-scheme BLOCK. Copied from
   lens along with the reason it is copied: that repo carried two hand-maintained
   light blocks, a `[data-theme="light"]` and a media-query twin, and they drifted
   — the media copy lost `--border-strong`, so every system-dark visitor who had
   never touched the toggle silently lost emphasized hairlines. Light being the
   base means there is nothing to duplicate and that class of bug cannot recur.
   Dark is exactly one explicit opt-in block, and it persists.

   ⚠️ THE RESERVED HUES MEAN ONE THING EACH, ACROSS BOTH PRODUCTS. On lens they
   are proven / requires-store-access / not-proven. Here they carry PRIVI's own
   result vocabulary, mapped one-to-one so a reader moving between the two sites
   never has to relearn a colour:

     --pass             slate     PROMOTE · a check that passed
     --requires-access  sand      REVIEW  · could not be determined
     --not-proven       crimson   BLOCK   · a check that did not hold

   Crimson appears ONLY where something did not hold. Not buttons, not links,
   not headings, not hover states, not "danger" tiles. In a product whose entire
   pitch is proof, the rarest colour on the page must be the one that means the
   proof is missing. `test/palette.test.mjs` enforces this the way lens's
   test/palette.test.ts does.

   ON THE STANDARD'S OWN PAGE THE RESULT HUES MAY NOT APPEAR AT ALL. A standard
   is a document; nothing on it has failed. The automation-flag badges are
   neutral ink, NOT a red/amber/green scale — an [R] badge is not a warning, it
   says which instrument reads the check.

   ⚠️ AND NEVER COLOUR ALONE. Every result state ships a glyph beside its hue,
   because roughly one man in twelve cannot separate the crimson from the slate.
   =========================================================================== */

:root {
  color-scheme: light;

  --navy: #24273a;
  --slate: #596c8e;
  --slate-light: #8fa6c6;
  --ice: #c7d1da;

  /* ⚠️ THE PAGE GROUND IS THE PALE BLUE-GRAY, AND SINCE THE BLUE-GROUND CHANGE
     (2026-08-07) LENS SHARES IT — these four values are byte-identical to
     ShopifyACO/viewer/src/theme.css again, by the owner's decision.

     ⚠️ ALL FOUR SURFACES SIT INSIDE [#E9EDF1 … white], AND THAT IS A FLOOR, NOT
     A TASTE. The reserved result hues measure 4.51–4.54:1 on #E9EDF1 — the
     4.5 floor, exactly — so no surface that can carry text may be darker than
     the field. A first pass here ran the tiers DOWNWARD (#DFE5EB, #D7DFE7),
     and crimson on that surface-2 measured 4.21:1: the BLOCK verdict on the
     home page, under the floor, shipped. The tiers now go up. */
  --bg: #e9edf1;
  --surface: #ffffff;
  --surface-2: #eff2f5;
  --band: #f1f4f7;

  --ink: #24273a;   /* 14.72:1 on --surface, 12.51:1 on --bg */
  --ink-2: #484c6b; /* 7.08:1 on --bg */
  --ink-3: #64698a; /* 4.54:1 on --bg — the a11y floor. (Reverted: the darkened
                       #5a5f7e existed only for the abandoned darker band.) */

  --border: #c7d1da;
  --border-ui: #728ba2; /* a control edge — WCAG 1.4.11, 3:1 */
  --border-strong: rgba(89, 108, 142, 0.38);
  --accent: #24273a;
  --accent-soft: rgba(89, 108, 142, 0.09);
  --ink-hover: #3a3f5e;
  --line: var(--border);

  /* ⚠️ THE THREE RESULT HUES ARE NOT DEFINED HERE, AND THAT IS THE POINT.
     They live in `result.css`, which only the surfaces that show a RESULT link.
     A stylesheet that does not carry a hue cannot render it, whatever a future
     rule asks for — and the standard is a document, where nothing has failed.
     A first pass at the dark theme put them here and two existing tests caught
     it within the hour. */

  /* ---- everything that is NOT a result ---- */
  --attention: #24273a;
  --attention-soft: color-mix(in srgb, var(--navy) 6%, transparent);
  --advisory: #484c6b;
  --advisory-soft: color-mix(in srgb, var(--advisory) 7%, transparent);

  --radius: 14px;
  --radius-sm: 10px;

  --font-body: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --font-display: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --font-ui: system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, 'Cascadia Mono', monospace;
}

/* ============ dark — an explicit opt-in, never the default ============
   The same six colours inverted: navy becomes the surface family and ice becomes
   the ink. slate-light carries the passing state here, because base slate is
   ~2.5:1 on navy and unreadable at text size. Crimson and sand are lifted in
   lightness at the same hue for the same reason.

   ⚠️ THIS BLOCK MUST DECLARE THE SAME TOKEN NAMES AS `:root` ABOVE. The bug the
   equivalent lens test exists for was a MISSING token, not a wrong value — a
   dark visitor silently losing one variable and inheriting a light value for it.
   `test/palette.test.mjs` asserts the two name sets agree exactly. */
:root[data-theme='dark'] {
  color-scheme: dark;

  --navy: #1b2131;
  --slate: #4f6890;
  --slate-light: #7b9bc7;
  --ice: #cbd8e4;

  --bg: #171c29;
  --surface: #1b2131;
  --surface-2: #232b3d;
  --band: #1f2637;

  --ink: #cbd8e4;   /* ice — 11.1:1 on --surface */
  --ink-2: #9baec6; /* secondary — 6.2:1 on --surface-2 */
  --ink-3: #8598b2; /* tertiary — 4.8:1 on --surface-2, the a11y floor */

  --border: #2e3850;
  --border-ui: #55648a;
  --border-strong: rgba(123, 155, 199, 0.34);
  --accent: #e3ebf4;
  --accent-soft: rgba(123, 155, 199, 0.10);
  --ink-hover: #f2f6fa;
  --line: var(--border);

  /* The result hues' dark lifts live beside their light values, in result.css. */

  --attention: #cbd8e4;
  --attention-soft: color-mix(in srgb, var(--ice) 7%, transparent);
  --advisory: #9baec6;
  --advisory-soft: color-mix(in srgb, var(--advisory) 10%, transparent);

  --radius: 14px;
  --radius-sm: 10px;

  --font-body: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --font-display: 'Source Serif 4', 'Iowan Old Style', Georgia, serif;
  --font-ui: system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, 'Cascadia Mono', monospace;
}

/* The toggle itself. A quiet control in the nav, not a floating widget. */
.theme-toggle {
  margin-left: auto;
  border: 1px solid var(--border-ui);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  padding: 3px 11px;
  cursor: pointer;
  line-height: 1.5;
}
.theme-toggle:hover { color: var(--ink); border-color: var(--ink-3); }

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--slate); text-underline-offset: 2px; }
a:hover { color: var(--ink); }
:focus-visible { outline: 2px solid var(--border-ui); outline-offset: 3px; }

/* ============ page shell ============ */

.std-page { max-width: 780px; margin: 0 auto; padding: 40px 22px 96px; }

.std-crumb {
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-3);
  margin-bottom: 18px;
}
.std-crumb a { color: var(--ink-3); }

/* Type ramp 26/18/15/13. The h1 is the SHORT name and the full descriptive
   title is a subtitle below it: a 26px h1 against an 18px h2 is a 1.44x step,
   where the 30px original was 1.76x and made the top of the page a wall. */
.std-doc h1 {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 6px;
}
.std-doc h2 {
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 44px 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.std-doc h3 {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  margin: 22px 0 6px;
}
.std-doc h4 {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 600;
  margin: 16px 0 6px;
}

.std-subtitle { font-size: 15px; color: var(--ink-3); margin: 0 0 20px; line-height: 1.5; }
.std-page p { margin: 0 0 12px; }
.std-page ul, .std-page ol { padding-left: 20px; margin: 0 0 12px; }
.std-page li { margin-bottom: 8px; }
.std-page code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--surface-2);
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--ink);
}

/* ============ the artifact header ============ */

.std-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0 0 20px;
  font-family: var(--font-ui);
  font-size: 12.5px;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.badge-version { border-color: var(--border-ui); color: var(--ink); }
.badge-status { text-transform: uppercase; font-size: 11px; letter-spacing: 0.08em; }

.std-hash {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 11px;
  margin: 0 0 22px;
  overflow-wrap: anywhere;
}
.std-hash b { color: var(--ink-2); font-weight: 600; }

/* The posture statement. This is the load-bearing honesty block; it is set as a
   quiet card rather than a warning, because it is a statement of standing and
   not an alert. */
.std-posture {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-ui);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  margin: 0 0 26px;
  font-size: 15px;
}
.std-posture h4 { margin-top: 0; }
.std-posture p:last-child { margin-bottom: 0; }

/* ============ counts strip ============ */

.std-counts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin: 0 0 26px;
}
.std-count { background: var(--surface); padding: 12px 14px; }
.std-count-v {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.1;
  color: var(--ink);
}
.std-count-k {
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--ink-3);
  line-height: 1.35;
  margin-top: 3px;
}
@media (max-width: 560px) {
  .std-counts { grid-template-columns: repeat(2, 1fr); }
}

/* ============ tier navigation ============ */

.std-nav {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  margin: 0 0 30px;
  font-family: var(--font-ui);
  font-size: 13.5px;
}
.std-nav ol { list-style: none; padding: 0; margin: 0; }
.std-nav li { margin: 0 0 5px; display: flex; gap: 10px; align-items: baseline; }
.std-nav li:last-child { margin-bottom: 0; }
.std-nav-n { color: var(--ink-3); font-variant-numeric: tabular-nums; min-width: 1.6em; }
.std-nav-range { color: var(--ink-3); font-size: 12px; margin-left: auto; white-space: nowrap; }

/* ============ a tier ============ */

.std-tier { margin-top: 44px; }
.std-tier-weight {
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-3);
  margin: -4px 0 16px;
}

/* ============ a check ============ */

.std-entry {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  margin: 0 0 14px;
  /* An anchored check must not land under a sticky header or flush against the
     viewport edge, or /ars#ARS-24 arrives with its heading off-screen. */
  scroll-margin-top: 18px;
}
.std-entry-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.std-entry-id {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.std-entry-id a { color: inherit; text-decoration: none; }
.std-entry-id a:hover { text-decoration: underline; }
.std-entry-title {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin: 0;
  flex: 1 1 260px;
}

/* Automation-flag badge. Neutral by rule: see the header note. The three flags
   differ by BORDER WEIGHT and label, never by hue. */
.flag {
  font-family: var(--font-ui);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink-3);
  white-space: nowrap;
}
.flag-S { border-color: var(--border-ui); color: var(--ink-2); }

.std-field { margin: 10px 0 0; }
.std-field-k {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-3);
  margin-bottom: 2px;
}
.std-field-v { margin: 0; }
.std-field-fail { color: var(--ink-2); }

/* A qualifying line inside a table cell — "attestation alone cannot settle it".
   Smaller and quieter than the claim it qualifies, and it survives print,
   because a qualifier that disappears on paper turns a hedged sentence into a
   flat one. */
.std-note {
  display: block;
  font-family: var(--font-ui);
  font-size: 11.5px;
  color: var(--ink-3);
}
/* ⚠️ INSIDE A TABLE CELL, THE NOTE SETS A FLOOR. Auto table layout squeezed the
   methodology table's rules column to 72px, and a seven-word note rendered one
   word per line — found by the skinny-box sweep that now runs after the .steps
   grid bug shipped the same shape. The wrapper scrolls horizontally, so forcing
   the column wider costs a scroll on narrow screens, not an overflow. */
/* td AND th: the runtime table annotates its ROW HEADERS with the same notes,
   and a td-only selector left exactly those crushed at 380px. */
.std-page td .std-note,
.std-page th .std-note { min-width: 13em; }

.std-static {
  margin-top: 12px;
  border-top: 1px dashed var(--border);
  padding-top: 10px;
}
.std-static summary {
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-3);
  list-style: none;
}
.std-static summary::-webkit-details-marker { display: none; }
.std-static summary::after {
  content: ' +';
  font-family: var(--font-mono);
}
.std-static[open] summary::after { content: ' \2212'; }
.std-static summary:hover { color: var(--ink-2); }
.std-ceiling {
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  margin: 10px 0;
}
.std-ceiling b { color: var(--ink); }
.std-signals { font-size: 14.5px; }

/* ============ tables (scoring model) ============ */

.std-table-wrap { overflow-x: auto; margin: 0 0 14px; }
.std-page table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-ui);
  font-size: 13.5px;
}
/* ⚠️ A CELL MAY SCROLL; IT MAY NOT BE CRUSHED. With width:100%, auto layout
   compresses columns to fit a 380px screen before it lets the wrapper scroll,
   and a prose cell ends up one word per line — the same shape as the .steps
   grid bug, found by the same sweep. A floor on the cell flips the choice:
   the table exceeds the viewport and the wrap scrolls, which is its job.
   ⚠️ THE FLOOR SITS ABOVE THE SWEEP'S BAR ON PURPOSE. The skinny-box sweep
   flags any prose element under 120px; a first pass set this floor to 6.5em
   (≈88px), which is BELOW that bar — a fix and a detector disagreeing about
   what "too narrow" means, so the sweep kept firing on cells the fix had
   already touched. 9em ≈ 121px at the table's 13.5px type: the two agree,
   and at desktop widths the widest squeezed column measured 119px, so the
   change there is invisible. The source-listing table opts out: its number
   gutter is meant to be narrow. */
.std-page .std-table-wrap td:not(.src-n):not(.src-t),
.std-page .std-table-wrap th[scope='row'] { min-width: 9em; }
.std-page th, .std-page td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.std-page th { color: var(--ink); font-weight: 600; border-bottom-color: var(--border-ui); }
.std-page tbody tr:last-child td { border-bottom: none; }

/* ============ footer ============ */

.std-foot {
  margin-top: 56px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-3);
}
.std-foot p { margin: 0 0 6px; }

/* ===========================================================================
   PRINT.

   ⚠️ A COLLAPSED <details> PRINTS NOTHING OF ITS BODY, AND ON THIS PAGE THAT IS
   WHERE THE STATIC CEILINGS AND SIGNALS LIVE. Measured in the lens repo, not
   argued: /standards/coffee/1.3 printed 20 pages as served and 27 with its
   sections expanded — 7 pages, 18,100 of 60,542 visible characters, 29.9% of
   the document, gone.

   THE MECHANISM IS THE PSEUDO-ELEMENT. Chromium hides the body via a UA rule on
   `details::details-content`, not on the author-visible children, so every
   folklore fix was measured INERT there:
     details { display: block }
     details > *:not(summary) { display: revert !important }
     details > * { display: block !important }
     details { content-visibility: visible !important }
     * { content-visibility: visible !important }   <- the universal selector
                                                       does not match pseudo-elements
   Only the rule below restores it, and it is deliberately NOT scoped to a page
   class. No second "fallback" rule is shipped beside it: the obvious pairing
   measured inert and a guard whose removal changes nothing is decorative.
   =========================================================================== */

@media print {
  body { background: #fff; font-size: 11pt; }
  .no-print { display: none !important; }
  .std-page { max-width: 100%; padding: 0; }

  .std-entry,
  .std-posture,
  .std-hash,
  .std-nav { break-inside: avoid; box-shadow: none; border-color: #ddd; }
  .std-doc h2 { break-after: avoid; }
  .std-tier { break-before: auto; }

  details::details-content { content-visibility: visible !important; }
  details { break-inside: avoid; }

  /* The disclosure marker is driven by [open], so an expanded-in-print section
     would still print "+" — an affordance that is both untrue and unusable on
     paper. */
  summary::after { content: '' !important; }

  /* A printed page cannot be clicked, so a bare "#ARS-24" href is noise, but
     the full canonical URL of the artifact is not. */
  .std-entry-id a::after { content: ''; }
  .std-foot a::after { content: ' (' attr(href) ')'; font-family: var(--font-mono); font-size: 9pt; }
}


/* ===========================================================================
   /findings — the corpus scan.
   
   The one rule that matters here: the not-observable bucket renders at the SAME
   SIZE as the other two. A figure whose unreadable share is set in small grey
   type is a figure that hides it, and hiding it is what makes a percentage a
   statement about the instrument rather than about the subject.
   =========================================================================== */

.finding-figure { margin: 0.6rem 0 0.9rem; font-size: 1.05rem; }
.finding-figure b { font-size: 2.1rem; font-family: var(--font-mono, monospace); letter-spacing: -0.02em; }
.finding-frac { margin-left: 0.6rem; opacity: 0.75; }

.finding-headline { border-left-width: 4px; }
.finding-headline .finding-figure b { font-size: 2.8rem; }

/* Same type scale as observed-present and observed-absent. Deliberate. */
.finding-buckets .std-count-v { font-variant-numeric: tabular-nums; }
.finding-noobs .std-count-v { text-decoration: underline; text-underline-offset: 3px; }

.finding-caveat { font-style: normal; }

.finding-examples, .finding-limits { margin: 0.5rem 0 0; padding-left: 1.1rem; }
.finding-examples li, .finding-limits li { margin: 0.45rem 0; line-height: 1.55; }
.finding-examples .flag { margin-right: 0.4rem; }

@media (max-width: 480px) {
  .finding-headline .finding-figure b { font-size: 2.1rem; }
  .finding-figure b { font-size: 1.7rem; }
  .finding-frac { display: block; margin-left: 0; }
}

/* The outreach one-pager. Narrower measure, bigger lede, prints to one page. */
.brief-page { max-width: 46rem; }
.brief-lede { font-size: 1.15rem; line-height: 1.6; }
.brief-lede b { font-family: var(--font-mono, monospace); }
.brief-stats { list-style: none; padding: 0; margin: 0.9rem 0 0; }
.brief-stats li { margin: 0.7rem 0; line-height: 1.5; }
.brief-stats b { font-family: var(--font-mono, monospace); font-size: 1.3rem; }
/* Same size as the surrounding text. Not small, not grey. */
.brief-noobs { font-size: inherit; }

/* ⚠️ A STATISTIC ID IS AN UNBROKEN 40-CHARACTER STRING and it pushed the page
   into horizontal scroll at 375px. Caught by measuring rather than by looking:
   scrollWidth 502 against a 375 viewport. The provenance line is the one place
   on this page that prints an identifier, so it wraps. */
.finding .std-field-v { overflow-wrap: anywhere; word-break: break-word; min-width: 0; }
.finding .std-field-v code { overflow-wrap: anywhere; word-break: break-word; }
.finding .std-field { flex-wrap: wrap; min-width: 0; }

/* ⚠️ A 64-HEX CONTENT HASH IS ONE UNBREAKABLE TOKEN, and it pushed /consulting
   and /ars into horizontal scroll at 380px — measured at 442 against a 380
   viewport. Pre-existing, found while checking the new pages, and fixed here
   because the footer hash appears on every page this site publishes. It wraps
   rather than shrinking: a truncated content hash is worse than a wrapped one,
   since the whole point of printing it is that somebody can compare it. */
.std-hash { overflow-wrap: anywhere; word-break: break-all; }

/* And the same token appears in footers that never got the .std-hash class.
   Keying on the class alone left /consulting and /ars still overflowing at
   380px, which is how a fix that measured clean in one place ships broken in
   another. Any monospace-length token in a footer wraps. */
.std-foot p, .std-foot code { overflow-wrap: anywhere; word-break: break-word; }


/* ===========================================================================
   The home page, and the navigation every page carries.

   Same light editorial theme as the rest: no gradient, no icon grid, no
   full-bleed hero. The page earns attention with a number and an artifact, and
   the type gets out of the way. Generous whitespace is doing the work that a
   heavier design would try to do with colour.
   =========================================================================== */

/* ---- the persistent nav -------------------------------------------------- */
/* It exists so nothing is orphaned, so it is on every page at every depth. The
   current page is text, not a link — a link to where you already are is a dead
   control and a screen reader announces it as a destination. */
.sitenav {
  font-family: var(--font-ui);
  font-size: 13px;
  letter-spacing: 0.01em;
  padding-bottom: 14px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 2px;
}
.sitenav a { color: var(--ink-3); text-decoration: none; padding: 2px 0; }
.sitenav a:hover { color: var(--ink); text-decoration: underline; }
.sitenav-here { color: var(--ink); font-weight: 600; padding: 2px 0; }
.sitenav-sep { color: var(--slate-light); padding: 0 9px; }

/* ---- 1. the first screen: who, what, and five claims ---------------------- */
/* Everything above the artifact is skimmable in ten seconds. That is the whole
   design constraint — a reader who does not yet know what you sell cannot
   evaluate your evidence, so the evidence waits. */

.eyebrow {
  font-family: var(--font-ui);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 16px;
}

.lede { margin: 4px 0 46px; }
.lede h1 {
  font-size: clamp(1.85rem, 5vw, 2.6rem);
  line-height: 1.16;
  letter-spacing: -0.015em;
  margin: 0 0 18px;
  color: var(--ink);
  text-wrap: balance;
  max-width: 19em;
}
.lede-p { font-size: 1.13rem; line-height: 1.55; color: var(--ink-2); margin: 0 0 12px; max-width: 34em; }
.lede-sub { font-size: 1rem; }

/* Five one-line claims. No icons, no cards — a hairline and a hanging rule.
   A feature grid says "we have features"; a list of one-line claims can be
   read, and each line is a thing somebody could contradict. */
.claims {
  list-style: none;
  padding: 0;
  margin: 24px 0 26px;
  border-top: 1px solid var(--border);
  max-width: 40em;
}
.claims li {
  margin: 0;
  padding: 9px 0 9px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 15px;
  color: var(--ink-2);
  position: relative;
}
.claims li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.05em;
  width: 9px;
  height: 1px;
  background: var(--slate);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 22px;
  margin: 0;
  font-family: var(--font-ui);
  font-size: 14px;
}
/* ⚠️ THE PRIMARY ACTION IS NAVY, NOT A RESULT HUE. Crimson and sand mean
   not-proven and could-not-be-determined; a button wearing one of them would
   spend the two colours this site reserves for the truth. */
.cta-primary {
  background: var(--accent);
  color: var(--bg);
  text-decoration: none;
  padding: 9px 18px;
  border-radius: 999px;
  font-weight: 500;
}
.cta-primary:hover { background: var(--ink-hover); color: var(--bg); }

/* ---- shared section furniture -------------------------------------------- */

.home h2 {
  font-size: clamp(1.3rem, 3.2vw, 1.65rem);
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 10px;
  text-wrap: balance;
}
.section-sub { color: var(--ink-3); margin: 0 0 22px; max-width: 40em; }

/* The one band, used to alternate section density without adding a card grid. */
.band-section {
  background: var(--band);
  border-radius: var(--radius);
  padding: 30px 26px 28px;
  margin: 0 0 46px;
}
.home section { margin: 0 0 52px; }

/* ---- 2. deliverables ------------------------------------------------------ */
.deliverables { list-style: none; padding: 0; margin: 0; }
.deliverables li {
  margin: 0 0 14px;
  padding-left: 22px;
  position: relative;
  line-height: 1.6;
}
.deliverables li::before {
  content: "\2014";
  position: absolute;
  left: 0;
  color: var(--slate);
}
.deliverables li:last-child { margin-bottom: 0; }

/* ---- 3. the named process ------------------------------------------------- */
.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; }
.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2.1rem 1fr;
  gap: 0 14px;
  padding: 14px 0;
  border-top: 1px solid var(--border);
  margin: 0;
}
.steps li:last-child { border-bottom: 1px solid var(--border); }
.steps li::before {
  content: counter(step);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--slate-light);
  padding-top: 4px;
  font-variant-numeric: tabular-nums;
}
.steps b { display: block; color: var(--ink); font-weight: 600; }
/* ⚠️ grid-column: 2 IS THE FIX FOR A SHIPPED BUG. The <li> is a two-column grid
   with THREE children — ::before, <b>, <span> — and auto-placement dropped the
   span into column 1, which is 2.1rem wide. The result was one word per line,
   live, on the home page. It shipped because verification measured scrollWidth
   (this bug stretches vertically, not horizontally) and every screenshot call
   failed without the page ever being LOOKED at. A measurement is not a look. */
.steps span { display: block; grid-column: 2; color: var(--ink-2); font-size: 15px; line-height: 1.55; }

/* ---- 4. the artifact ------------------------------------------------------ */
.artifact { margin: 0 0 52px; }
.panel {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 18px 18px 16px;
  margin: 0 0 14px;
  min-width: 0;
}
.panel-k {
  font-family: var(--font-ui);
  font-size: 11.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 8px;
}
.panel-note { font-size: 14.5px; color: var(--ink-2); margin: 0 0 12px; }
.panel-quote {
  margin: 0 0 14px;
  padding: 0 0 0 14px;
  border-left: 3px solid var(--border-ui);
  color: var(--ink);
  font-size: 1.02rem;
  line-height: 1.55;
}
.panel-after { margin: 12px 0 0; font-size: 15px; }
.panel-verdict { border-color: var(--border-ui); background: var(--surface-2); }

.verdict { margin: 0 0 10px; display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 12px; }
.verdict-rule { color: var(--ink-2); font-size: 15px; min-width: 0; }


/* ---- source, with real line numbers -------------------------------------- */
/* The line numbers are the point: the artifact cites a file and a line, and the
   page shows that line. A snippet with the numbers stripped is a quotation
   nobody can go and check. */
.src { margin: 0; min-width: 0; }
.src-file { font-family: var(--font-ui); font-size: 12.5px; color: var(--ink-3); margin: 0 0 8px; overflow-wrap: anywhere; }
.src-cite { color: var(--ink-2); }
.src .std-table-wrap { margin: 0; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); }
.std-page table.src-table { margin: 0; font-family: var(--font-mono); font-size: 13px; border-collapse: collapse; width: 100%; }
.std-page .src-table td { border: none; padding: 1px 0; vertical-align: top; white-space: pre; }
.src-n {
  width: 3.4em;
  padding-right: 14px !important;
  padding-left: 12px !important;
  text-align: right;
  color: var(--slate-light);
  user-select: none;
  font-variant-numeric: tabular-nums;
}
.src-t { padding-right: 12px !important; color: var(--ink); }
/* Marked with a rule and a weight, never with colour alone. */
.src-hit td { background: var(--band); font-weight: 600; }
.src-hit .src-n { box-shadow: inset 3px 0 0 var(--ink); color: var(--ink-2); }
.src-table tr:first-child td { padding-top: 10px; }
.src-table tr:last-child td { padding-bottom: 10px; }

.examples { padding-left: 20px; margin: 20px 0 0; }
.examples li { margin-bottom: 10px; line-height: 1.55; }

/* ---- 5. the measurement --------------------------------------------------- */
.figures { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin: 0; }
@media (max-width: 640px) { .figures { grid-template-columns: 1fr; gap: 26px; } }

.figure { border-top: 2px solid var(--ink); padding-top: 14px; min-width: 0; }
.figure-v { margin: 0 0 8px; display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 10px; }
.figure-v b {
  font-family: var(--font-mono);
  font-size: clamp(2rem, 5.5vw, 2.7rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink);
}
/* ⚠️ THE DENOMINATOR IS NOT SMALL PRINT. Same line, same ink family. A share
   whose denominator is set in grey six-point type is a share that is hiding
   what it was counted out of. */
.figure-sub { font-family: var(--font-mono); font-size: 0.95rem; color: var(--ink-2); }
.figure-body { margin: 0 0 10px; line-height: 1.6; font-size: 15px; }
.figure-src { margin: 0; font-family: var(--font-ui); font-size: 12.5px; }

/* ---- 6. the limits -------------------------------------------------------- */
.limits { list-style: none; padding: 0; margin: 0 0 24px; }
.limits li {
  margin: 0 0 12px;
  padding-left: 22px;
  position: relative;
  line-height: 1.6;
  color: var(--ink-2);
}
.limits li::before { content: "\00b7"; position: absolute; left: 6px; color: var(--ink-3); font-weight: 700; }
.limits b { color: var(--ink); }
.closing-line { font-size: 1.08rem; color: var(--ink); margin: 0 0 16px; max-width: 34em; }
.soft { color: var(--ink-2); font-size: 15px; }

@media print {
  .figures { grid-template-columns: 1fr 1fr; gap: 18px; }
  .figure, .panel, .artifact, .steps li { break-inside: avoid; }
  .panel, .band-section { border-color: #ddd; background: #fff; }
  .panel-verdict { background: #fff; }
  .src .std-table-wrap { border-color: #ddd; background: #fff; }
  .src-hit td { background: #f0f0f0; }
  .cta-primary { background: none; color: inherit; border: 1px solid #999; }
  /* A printed page cannot scroll, so a long source line must wrap rather than
     be cut off at the paper edge. */
  .std-page .src-table td { white-space: pre-wrap; overflow-wrap: anywhere; }
}
