/* Thirtyish — one stylesheet for the whole site.
 *
 * ⚠️ 09 §6's blanket exclusion of palette and typography work was LIFTED on
 * 10 August 2026 (decision 51) and the direction settled on 11 August
 * (decision 52, written up in 09a-Design-Direction-and-Tokens.md). The rest
 * of §6 stands and is load-bearing: no logo, no favicon beyond a default,
 * no brand book, no personas, no social, no named author, no second brand,
 * no blog. 📌 The wordmark is styled text and must STAY styled text — a
 * plum band is exactly where a logo normally arrives next, and it must not.
 *
 * The whole palette change is six variables and four rules (09a §5). It is
 * not a redesign, and the reason is a measured one: on a content page the
 * masthead is ~40px of a very long screen and everything below it was
 * near-identical across the hues tested. The band does nearly all the work.
 *
 * TYPOGRAPHY IS DELIBERATELY UNCHANGED. The system stack stays; no web
 * font, no @font-face, no dependency. The tempting option leaned on Avenir
 * Next, which exists on macOS and iOS and not on Windows or Android — it
 * would have looked right to the one person reviewing it and wrong to most
 * readers. 📌 A type decision made on a Mac is a decision about the
 * reviewer's device. Weight, size and letter-spacing carry the load.
 *
 * Mobile-first throughout: every rule is the phone rule, and the two media
 * queries at the bottom add width rather than take it away.
 */

:root {
  --ink: #181528;
  --ink-soft: #5B5270;
  --ink-faint: #6b6b6b;
  --rule: #E6E2EE;
  --rule-soft: #ececec;
  --paper: #ffffff;
  --paper-tint: #f6f6f4;
  /* ── The palette. 09a §4. ──────────────────────────────────────────────
     ⚠️ Contrast ratios below were COMPUTED with a WCAG relative-luminance
     script and re-derived independently in this build — not estimated, not
     recalled. Every number produced by eye in this project so far has been
     wrong, and decision 38 does not stop at the engine boundary. The §8 bar
     is 4.5:1; the narrowest pairing in the set is 4.85:1 (ink-soft on the
     Build 009 tint, down from 6.52:1 — see below), so there is margin — but
     the margin is a fact, not a licence. If you change any colour here,
     RECOMPUTE. Do not assert. */
  --accent: #2E1A5B;      /* 14.84:1 on white (the navy it replaces was 9.17) */
  --accent-on: #ffffff;   /* 14.84:1 on the band */
  /* Build 009 Part B: raised from #F4F1FA (1.12:1 against white) to
     #D5D1DE (1.50:1), computed with the same WCAG relative-luminance script
     as the rest of this block — p=0.20 blend of --accent into white, chosen
     as visibly above the old value while staying well under the 3:1 WCAG
     non-text-contrast threshold for a UI-component BOUNDARY, because this is
     a SURFACE (§ below) and is not meant to read as a coloured box. */
  --accent-tint: #D5D1DE; /* ink 11.90:1 · accent 9.90:1 · ink-soft 4.85:1 */
  --warn-tint: #fdf6e7;
  --warn-rule: #e0c98a;

  --panel-radius: 12px;

  --measure: 34rem;
  --gap: 1rem;

  /* ⚠️ THE SIDE GUTTER. ONE PLACE. DO NOT HARD-CODE THIS VALUE ANYWHERE.
     Build 009 fixed the margin defect by making every panel break out to
     .wrap's edge, which aligned panel text with body text — but it did it
     at .wrap's then-current 1.1rem (17.6px), and pulled panel text INWARD
     from 2.1rem to 1.1rem in the process. So both halves of the change
     moved toward the screen edge, and the second half of David's original
     feedback — "too close to the edge" — was never addressed. Raised here
     to 1.5rem (24px) mobile / 2rem (32px) from 48rem up.

     It is a variable because the old value appeared in SIX places that had
     to move together — .wrap, four breakout rules, a blockquote calc() —
     and Build 009's own note warned the fix "silently reverts" if they
     drift apart. Decision 57: a mechanism beats an instruction on anything
     that has already failed once. To retune the whole page, change these
     two numbers and nothing else. */
  --gutter: 1.5rem;
}

/* Was "known and accepted, do NOT try to solve it" at 1.12:1 against white —
   Build 009 Part B raised it to 1.50:1 (§ above), because the margin
   defect fix (below) means every panel's inset now only reads as
   deliberate if the panel is visible, and 1.12:1 often wasn't on a phone in
   daylight. Still fine for a SURFACE and not for a BOUNDARY — every panel
   below keeps radius and padding rather than relying on the fill alone to
   be seen. Whether 1.50:1 survives a phone in daylight is untested; if a
   future pass finds it still isn't enough, recompute — don't nudge by eye. */

* { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  /* 16px, decision 176 (10 Sept 2026), David's own call taken element by
     element off a rendered handset screen. 16px is a FLOOR, not a preference:
     below it Safari zooms the page when a reader taps a field.
     CORRECTED 14 Sept 2026 — this comment used to argue FOR 1.0625rem
     ("the default 16px is a shade tight for 750 words of argument"), which
     is the case AGAINST the value declared beneath it. Decision 219's shape:
     a right instruction with a wrong reason underneath it.
     The ≥48rem step to 1.0625rem is still live, further down this file. */
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
}

/* ── Skip link ─────────────────────────────────────────────────────────── */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--accent-on);
  padding: 0.6rem 1rem;
  z-index: 20;
}
.skip-link:focus { left: 0; }

/* ── Focus. Visible everywhere, never removed. ─────────────────────────── */

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

/* ── Layout ────────────────────────────────────────────────────────────── */

.wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

main { display: block; }

/* ── Masthead and the topic nav (the cold-arrival entry point) ─────────── */

/* ⚠️ THE ONLY PLACE THE BRAND RAISES ITS VOICE. A full-bleed saturated
   band, and 09a §2's measured finding is that it does nearly all the work
   of the whole direction — on a content page it is ~40px of a very long
   screen and everything below it was near-identical across the three hues
   tested. It is also decision 44's "framing up at the entry point" made
   physical.

   Plum was chosen on CONNOTATION, not taste: red beside a five-figure
   number reads as a loss or a warning, on pages whose entire job is to make
   the reader less frightened; green reads as growth, one step towards the
   investment register decision 31 keeps this site out of. Plum carries no
   financial connotation at all and no UK bank or lender is using it. 📌 The
   absence of meaning is the feature. ⚠️ That is reasoning from connotation
   with no evidence behind it — reversible in one variable. */
.masthead {
  background: var(--accent);
  padding: 0.75rem 0;
}

.masthead-inner {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* Styled text, and it must stay styled text — 09a §6. */
.wordmark {
  font-weight: 700;
  font-size: 1.25rem;          /* ~20px, per 09a §4 */
  letter-spacing: -0.03em;
  color: var(--accent-on);     /* 14.84:1 on the band */
  text-decoration: none;
}
.wordmark:hover { text-decoration: underline; }

/* Softened so it does not compete with the wordmark. COMPUTED: white at 80%
   flattens to #d5d1de over the band, which is 9.9:1 — well clear of 4.5. */
.masthead .strap {
  margin: 0;
  font-size: 0.8125rem;
  color: rgba(255, 255, 255, 0.8);
}

/* ── The "All Topics" control (decision 212, Build 032) ───────────────────
   🔴 BASE-LEVEL, because build-pages.js now emits this <details> on every
   page unconditionally — decision 172's lesson, applied before the fact
   rather than found again after it. A reverted DIRECTION 3c must not leave
   an unstyled disclosure sitting in the masthead.
   ⚠️ COLOURED IN INK, NOT --accent-on, AND THIS WAS A REAL BUG CAUGHT BY
   RENDERING THE REVERTED STATE, not assumed from reading the rule below it.
   The raw base masthead is a dark band, but DIRECTION 1b — which is
   PERMANENT and is NOT what a 3c revert deletes — already repaints the
   masthead to a light, near-white ground (its own comment: "Cream ground").
   So the state a 3c revert actually produces is 1b's light masthead, not
   the raw dark one, and white-on-white (--accent-on on a --paper band) was
   invisible: caught by looking at the rendered reverted page, not by
   reading this rule in isolation. --ink is dark in every layer this site
   has (base, 1b, 3c alike), which is exactly why the rail's arrow below
   uses it too — one legible default, no per-direction override needed.
   ⚠️ A <summary>, so decision 176's 44px control floor applies to it in
   full — this is a control you tap to open something, not a link you tap
   to go somewhere. */
.all-topics {
  position: relative;
  margin-left: auto;
}
.all-topics summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 1rem;
  cursor: pointer;
  list-style: none;
  border: 2px solid var(--ink);
  border-radius: var(--panel-radius);
  color: var(--ink);
  font-weight: 700;
  font-size: 0.875rem;
  background: transparent;
}
.all-topics summary::-webkit-details-marker { display: none; }
/* Overlays rather than pushing the page down — the measurement (Options-005
   §7.2) that keeps the masthead's height identical at two products and at
   eight: the sheet simply grows downward from here. */
.all-topics-sheet {
  position: absolute;
  z-index: 20;
  top: calc(100% + 8px);
  right: 0;
  width: min(300px, calc(100vw - 2 * var(--gutter, 1.5rem)));
  /* 🔴 FIX 4, Build 032.1 (Review 024 F3). `100%` here is `.all-topics`'s OWN
     box — the 44px control — because that is the containing block a
     percentage `max-height` resolves against; `top`'s `calc(100% + 8px)`
     above is correctly relative to that same box (the sheet grows down from
     the control's own bottom edge, wherever that is), but `max-height` needs
     the sheet's distance from the top of the VIEWPORT instead, which is a
     different quantity `100%` cannot express. The old formula therefore let
     a sheet run ~50px taller than the screen could show, and decision 212's
     own "the eight-item sheet ends 462px down at 320px" ruling — made before
     216 added money worries as a third live row — had quietly drifted to
     551.5px with nothing catching it. 94px below is MEASURED, not
     estimated: getBoundingClientRect().top on .all-topics-sheet itself,
     both webfonts loaded, 93.7890625px identical at 320 and 390 width and on
     a product page and a site-level one, because the masthead's box model
     doesn't change between them. A CSS-only literal rather than a live
     read, because no JavaScript may touch the masthead — decision 212's
     <details>-only choice was protecting exactly that. Re-measure this
     constant if the masthead's own height, padding or border ever changes. */
  max-height: calc(100svh - 94px - 16px);
  overflow-y: auto;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--panel-radius);
  padding: 0.6rem;
}
.all-topics-sheet ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.all-topics-sheet li > * {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
}
.all-topics-sheet a { color: inherit; text-decoration: none; font-weight: 600; }
.all-topics-sheet a:hover { text-decoration: underline; }
.all-topics-sheet li.coming { color: var(--ink-faint); }
.all-topics-sheet li.coming .mark-product svg { fill: var(--ink-faint); }
.all-topics-sheet .row-tag {
  margin-left: auto;
  flex: none;
  /* Matches .topic-nav.home-topics .row-tag's own ruled size (decision
     216) — same tag, same word ("Coming Soon"), same sheet's worth of rows,
     so it reads at the same weight in both places. */
  font-size: 0.5625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.all-topics-sheet li.hairline-above {
  border-top: 1px solid var(--rule);
  padding-top: 10px;
  margin-top: 4px;
}

/* The topic nav. This is the entry-point answer to decision 41: a reader
   landing cold on one page can see the whole topic and get to the tool
   without any page having to restate the flagship. Labels only — no prose,
   because prose here would be new copy and this build does not write copy.

   ⚠️ RESTYLED IN CSS ONLY, Build-006, and that is deliberate. Q8: "the
   section with the links looks Bank-1 out of 10. We need this but we need
   to make it look sexier." Q11, arriving cold on write-off as a first ever
   page: "diving straight to the Heading 'Student Loans' followed by a list
   of links is too brutal."

   📌 The diagnosis is that seven underlined links in a row in a grey box IS
   a list of links — it looks like a directory index, which is the one thing
   a worried stranger does not want to read. The markup is unchanged and
   still labels-only; what changes is that the links become the same PILL
   component the path switch already uses, the grey becomes the palette's
   own tint so the strip reads as a continuation of the plum band rather
   than as an unrelated grey box beneath it, and the calculator stops being
   the first item in a list and starts being the one filled thing on the
   screen. Build-005 §6 chose a nav over a standfirst, breadcrumbs and a
   banner because "the nav is labels, not sentences"; that argument is
   unchanged and this extends it — the problem was never the words. */
/* Build 009 Part C (Q8: "looks right, but too tall" — ~162px of a 390px
   screen). Padding, gap and line-height are all reduced; the pill
   treatment and all seven items are unchanged — see §4a.is-hub etc. below,
   untouched. Measured before/after in the Build 009 note. */
.topic-nav {
  background: var(--accent-tint);
  padding: 0.55rem 0 0.6rem;   /* was 0.85rem 0 0.95rem */
  font-size: 0.875rem;
  line-height: 1.25;           /* was the inherited body value, 1.6 */
}

.topic-nav h2 {
  margin: 0 0 0.35rem;         /* was 0.5rem */
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--accent);
}

.topic-nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;                 /* was 0.4rem */
}

/* Pills, matching .path-switch. White on the tint per the inversion rule,
   and the underline goes: underlining seven adjacent links is most of what
   made this read as a directory index. Accent on white is 14.84:1. */
.topic-nav li > * {
  display: block;
  padding: 0.22rem 0.6rem;     /* was 0.32rem 0.7rem */
  border-radius: 999px;
  background: var(--paper);
  color: var(--accent);
  text-decoration: none;
}

.topic-nav a:hover { text-decoration: underline; }

/* The calculator is the destination every content page points at, so it is
   the one filled thing here rather than merely the first item. */
.topic-nav .is-hub > * {
  background: var(--accent);
  color: var(--accent-on);
  font-weight: 700;
}

/* The page you are on. It does not need to shout — its own h1 is directly
   below — so it is weight and a flatter fill rather than another accent.
   ⚠️ MUST STAY AFTER the .is-hub rule above. On the tool page the hub IS
   the current page, both selectors have the same specificity, and source
   order is what makes the filled pill correctly drop away once you have
   arrived. Reordering these two silently paints "you are here" as "go
   here". */
.topic-nav [aria-current="page"] {
  background: transparent;
  color: var(--ink-soft);
  font-weight: 700;
}

/* ── The rail (decision 213, Build 032) ───────────────────────────────────
   🔴 BASE-LEVEL, for the same reason the "All Topics" control above is:
   build-pages.js now emits the .rail wrapper and the two arrow buttons
   unconditionally, on every product page, so deleting DIRECTION 3c below
   must not leave two unstyled buttons beside a nav that no longer scrolls
   (decision 172's lesson, applied ahead of time). Scoped to `.rail ul`/
   `.rail li`, never the bare `.topic-nav ul` above — that rule still governs
   .home-topics, an unrelated column-of-cards component this build must not
   touch, and `.rail`'s higher specificity wins here without needing to
   touch that rule at all.
   ⚠️ The two arrow slots are RESERVED, not an overlay: proved geometrically
   in the specimen (Options-005 §7.4) that the scrolling box and each arrow's
   slot never intersect at any scroll position, so a pill can never pass
   under an arrow. */
.topic-nav .rail {
  display: flex;
  align-items: center;
  gap: 2px;
}
.topic-nav .rail ul {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  /* `overflow-x: auto` makes the other axis compute to `auto` too (CSS
     Overflow 3), so this box clips vertically as well as horizontally —
     and the box is exactly as tall as a pill, so the whole top and bottom
     of the 3px focus ring was clipped (Review 025 §3). 6px of padding
     gives the ring room; the matching negative margin cancels it back out
     so the rail's own height — and decision 213's 151px argument — does
     not move. */
  padding: 6px 0;
  margin: -6px 0;
}
.topic-nav .rail ul::-webkit-scrollbar { display: none; }
.topic-nav .rail li { flex: none; }
/* 🚫 NOT `pointer-events: none` + opacity alone (§3.5) — that leaves an
   invisible control in the keyboard tab order, confirmed by tabbing a built
   page (see the build note). `visibility: hidden` holds the reserved slot's
   layout exactly as opacity would, AND removes the button from the tab
   order and from pointer/click targeting, so no second property is needed
   to finish the job. */
.rail-arrow {
  flex: none;
  width: 20px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  visibility: hidden;
  opacity: 0;
}
.rail-arrow svg { width: 15px; height: 15px; display: block; }
.rail-arrow.on { visibility: visible; opacity: 1; }
.rail-arrow-l { order: -1; }
/* 🔴 FIX 6, Build 032.1 (Review 024 F8). The approved specimen
   (Options-005-Navigation-Specimens.html) has `.arrow:active svg
   {transform:scale(.88)}` — decision 212 records that the within-product
   half of this control could not be settled from static pictures because it
   "turns on what a tap FEELS like rather than on what a layout costs", and
   this is the one piece of tap feel in the artefact David approved. It did
   not ship with the rest of the specimen; this restores it. */
.rail-arrow:active svg { transform: scale(0.88); }

/* The home page (Build 009 Part A). Same .topic-nav markup and CSS, reused
   inline in the page body rather than as its own chrome band below the
   masthead: the container is a plain .home-topics div, not the .topic-nav
   nav landmark, and it is never inserted via the @chrome marker — so the
   home page gains no band of its own. One modifier turns the row of pills
   into a stack; nothing about .topic-nav's own behaviour changes. */
.topic-nav.home-topics ul {
  flex-direction: column;
  align-items: flex-start;
}

/* ── The next-step block (09a §2, §5.5) ────────────────────────────────── */
/* The second use of the tint, and the reason it is here rather than being
   nice-to-have: without it a content page reverts to the undesigned version
   below the fold, which is where a reader spends nearly all of their time.
   Radius and padding carry the panel, not the fill — the tint is 1.50:1
   against white as of Build 009 Part B (was 1.12:1). */
.next-step {
  background: var(--accent-tint);
  border-radius: var(--panel-radius);
  padding: 1rem 1rem 1.1rem;
  margin: 2.4rem 0 0.5rem;
}

.next-step h2 {
  margin: 0 0 0.7rem;
  font-size: 0.9375rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--accent);
}

/* The calculator, as a filled block rather than a pill — it is the one
   thing a reader who has just finished a page should do next, and every
   content page already links to it as the destination.
   🔴 BUILD 040, decision 255: David's first pass over take-home pay found
   this pill "way too loud" at full width. RULED: it shrinks to fit its own
   label and sits hard left, label still centred inside — shrink-to-fit,
   not a fixed narrower width, so it matches every other pill on the site
   and there is no width number to maintain. `width: fit-content` on a
   block, not `display: inline-block`, so the paragraph's line box adds no
   strut gap beneath it. The two later rules for this element (1b's square
   corners, 3c's marigold-and-keyline) restyle paint only and never set a
   width, so this one declaration serves all of them. */
.next-step-hub { margin: 0 0 0.7rem; }

.next-step-hub a {
  display: block;
  width: fit-content;
  background: var(--accent);
  color: var(--accent-on);
  font-weight: 700;
  text-decoration: none;
  text-align: center;
  padding: 0.7rem 1rem;
  border-radius: 999px;
}

.next-step-hub a:hover { text-decoration: underline; }

.next-step ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  font-size: 0.875rem;
}

.next-step li a {
  display: block;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  background: var(--paper);
  color: var(--accent);
  text-decoration: none;
}

.next-step li a:hover { text-decoration: underline; }

/* ── Typography ────────────────────────────────────────────────────────── */

/* ⚠️ PADDING-TOP ONLY, AND THE SHORTHAND IS THE BUG THIS REPLACES.
   This was `padding: 1.25rem 0 0`. `.page` only ever appears as
   `<main class="wrap page">`, so the shorthand's two zeroes overwrote
   .wrap's `padding: 0 var(--gutter)` — equal specificity (0,1,0), later in
   the file, so it won on source order. THE SIDE GUTTER HAS THEREFORE BEEN
   ZERO ON EVERY MAIN CONTENT AREA ON THE SITE, and the panels' breakout
   (`margin-left: calc(-1 * var(--gutter))`, added Build 009) had nothing to
   break out INTO — they hung 24px past the viewport on each side, giving
   24px of horizontal page overflow and putting body text hard against the
   screen edge at x=0.

   📌 Measured in the live DOM at 320px before this fix: main padding-left
   0px, h1 left 0, document scrollWidth 344 against clientWidth 320. That is
   Build 009's "too close to the edge" in its most extreme possible form,
   and it is what David saw as the preview "truncating text".

   ⚠️ Build 012 checked the standing hypothesis and it was WRONG:
   `.headline .figure { white-space: nowrap }` overflows nothing. Measured
   at 320px across four profiles including the widest reachable figures,
   .headline scrollWidth == clientWidth == 316 every time; the widest
   unbreakable token is "December 2045" at 156px in a 316px box. The nowrap
   is not the defect and has been left alone.

   `article` keeps the horizontal zero it always had — it is a plain block
   inside main and has no padding of its own to restore. */
article, .page { padding-top: 1.25rem; }

h1 {
  font-size: 1.5rem;
  line-height: 1.22;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
}

/* Claim headings (decision 30). These carry the argument on their own, so
   they get real weight and real space above them. */
h2 {
  font-size: 1.1875rem;
  line-height: 1.3;
  margin: 2rem 0 0.4rem;
  letter-spacing: -0.01em;
}

h3 {
  font-size: 1.0625rem;
  margin: 1.5rem 0 0.4rem;
}

p { margin: 0 0 0.9rem; }

/* ── Lists in prose ─────────────────────────────────────────────────────
   Added 8 Sept 2026, alongside list support in build-pages.js. Until that
   day a bullet in a deck rendered as a LITERAL HYPHEN inside a paragraph,
   so no <ul> could ever reach an <article> and no rule was needed — which
   is why every other ul/li rule in this file is scoped to a named
   component (.topic-nav, .next-step, .card-facts, .path-list,
   footer.site). None of those sit inside <article>, and the direct-child
   selector below keeps the separation true in both directions.

   ⚠️ DELIBERATELY NOT A DESIGN STATEMENT. The list borrows the
   paragraph's own bottom margin and the body's line-height so that it
   sits inside the prose rather than announcing itself. No new colour, no
   new type size, no new token. If a list should ever look like anything
   more than this, that is a design decision and belongs in 09a, not
   here. */

article > ul,
article > ol {
  margin: 0 0 0.9rem;
  padding-left: 1.35rem;
}

article > ul > li,
article > ol > li {
  margin: 0 0 0.35rem;
}

article > ul > li:last-child,
article > ol > li:last-child { margin-bottom: 0; }

a { color: var(--accent); }

/* The bolded one-line answer under each claim heading (decision 30), and
   the standfirst under the h1 (the decision-36 extension of the pattern).
   Same treatment because they do the same job. */
.answer-line,
.standfirst {
  font-weight: 700;
  margin: 0 0 0.9rem;
}

.standfirst {
  font-size: 1.125rem;
  border-left: 3px solid var(--accent);
  padding-left: 0.8rem;
}

/* The page-opening device — "You're thirtyish and…" (09 §5a). */
.opener {
  color: var(--ink-soft);
  font-size: 1rem;
  margin: 0 0 1.5rem;
}

blockquote {
  margin: 0 0 0.9rem;
  padding: 0.1rem 0 0.1rem 0.9rem;
  border-left: 3px solid var(--rule);
  color: var(--ink-soft);
}

blockquote p:last-child { margin-bottom: 0; }

/* ── Tables ────────────────────────────────────────────────────────────── */

.table-scroll {
  overflow-x: auto;
  margin: 0 0 1.1rem;
  -webkit-overflow-scrolling: touch;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9375rem;
  /* Tables are the cheapest evidence on these pages per unit of argument
     (decision 39), so they must stay readable on a 360px screen rather
     than wrapping into mush. */
  min-width: 19rem;
}

th, td {
  text-align: left;
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: top;
}

thead th {
  border-bottom: 2px solid var(--rule);
  font-size: 0.9375rem;
}

/* 🔴 CE12, Build 038, David's ruling: left, against the convention that a
   money column is right-aligned for digit comparison — "it didn't pass the
   eyeball test." tabular-nums stays: it fixes digit width, not alignment. */
td.num, th.num { text-align: left; font-variant-numeric: tabular-nums; }

/* ── Collapsed working (decision 30) ───────────────────────────────────── */

details {
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 0.6rem 0.85rem;
  margin: 0 0 1.1rem;
  background: var(--paper-tint);
}

summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--accent);
  /* The default marker is small and easy to miss on a phone, and this is
     voice rule 4's "within one click" made physical. */
  padding: 0.15rem 0;
}

details > *:last-child { margin-bottom: 0; }
details[open] > summary { margin-bottom: 0.7rem; }

details blockquote {
  border-left-color: var(--rule);
  font-variant-numeric: tabular-nums;
}

/* ── The sources rule ──────────────────────────────────────────────────── */

/* 🔴 `.signoff` IS RETIRED, Thread 087, decision 174. The standing long-form
   sign-off came off every product page on David's instruction; the paragraph
   classifier that applied this class was retired with it, and no element on
   the site now carries it. 📌 Recorded here rather than silently deleted:
   the class is named in Thread 086's build notes and in `18-01`, and a
   reader finding it there needs to know where it went. */

.page-sources {
  margin: 1.5rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--ink-faint);
}

/* ── The money-worries line (decision 182, Build 030) ──────────────────────
   🔴 THE SPACE IS THE WHOLE RULE, and it is David's call — option (b) of
   four put to him at the wrap of Thread 095, after the line was rendered at
   375px and seen to arrive flush under .page-sources above it.

   ⚠️ WHY IT MATTERED ENOUGH TO RULE ON. This line asks a reader who has just
   been shown a number they may not like to admit that they are worried. It
   was doing that immediately after a grey footnote about where the tax
   thresholds came from, with no space of its own, so the two read as one
   block. The line is not a continuation of the citation and must not look
   like one.

   🚫 NOT a rule and NOT a tint — option (c) was a hairline and option (d)
   was moving it above the sources. Space only, so the component stays
   unstyled furniture that any page can carry.

   📌 It shipped with NO CSS rule at all until now, which is why it inherited
   paragraph spacing: the component was added in the same build that added
   the page, and nothing renders a class into existence. Found by an
   independent review, not by a check — no check here looks at appearance. */
.money-worries {
  margin-top: 2.25rem;
}

/* ── The visuals (Part C). Inline HTML/CSS, never images. ──────────────── */

/* Tint, no border, larger radius (09a §5.3). The hairline-box grid these
   four selectors used to draw was most of what read as "bank". */
.visual {
  margin: 1.4rem 0;
  padding: 1rem;
  background: var(--accent-tint);
  border-radius: var(--panel-radius);
}

.visual-caption {
  font-size: 0.8125rem;
  color: var(--ink-faint);
  margin: 0.8rem 0 0;
}

/* Two-card device: two balances, one identical payment (flagship), and the
   same £5,000 twice (overpaying). Stacked on a phone, side by side above. */
.two-cards {
  display: grid;
  gap: 0.8rem;
  grid-template-columns: 1fr;
}

/* ⚠️ INVERTED, and 09a could not have decided this. §5.3 lists both .visual
   and .borrower-card as taking the tint — but .borrower-card NESTS INSIDE
   .visual, and tint on tint is 1.0:1, so the inner cards would have
   disappeared entirely. 09a §7 says only the answer card and the top of
   write-off.md were ever rendered, and the two-card device appears on
   neither, so the nesting was never seen.
   The visual takes the tint and the cards sit on it in white — raised
   rather than recessed. White on tint is 1.50:1 as of Build 009 Part B
   (was 1.12:1), so the boundary is still carried by RADIUS AND PADDING
   rather than by fill, which is what §4's own "fine for a surface, not for
   a boundary" note requires. */
.borrower-card {
  border-radius: var(--panel-radius);
  padding: 0.85rem;
  background: var(--paper);
}

.borrower-card h4 {
  margin: 0 0 0.5rem;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}

.card-facts {
  margin: 0 0 0.7rem;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}

.card-facts li { margin: 0 0 0.15rem; }

.card-facts .differs { font-weight: 700; }

/* The figure that is the point of the card. Large, and — where the point
   is that two of them are identical — visibly identical. */
.card-punch {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  display: block;
}

.card-punch-label {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-faint);
  margin-top: 0.15rem;
}

.same .card-punch { color: var(--accent); }

/* The one-bar visual on the-big-scary-number. Two bars on a shared £ axis
   that deliberately DO NOT sum — see the VISUAL 1 comment in that page's
   markdown, rewritten 10 August. */
.bar-figure { margin: 0.4rem 0 0; }

.bar-row { margin: 0 0 0.9rem; }

.bar-label {
  display: block;
  font-size: 0.875rem;
  margin: 0 0 0.3rem;
}

.bar-track {
  background: var(--rule-soft);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
}

.bar-fill {
  display: block;
  height: 2.1rem;
  background: var(--accent);
}

.bar-fill.secondary {
  background: var(--ink-faint);
}

.bar-value {
  display: block;
  font-weight: 700;
  font-size: 1.0625rem;
  margin-top: 0.3rem;
  font-variant-numeric: tabular-nums;
}

.bar-axis {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--ink-faint);
  border-top: 1px solid var(--rule);
  padding-top: 0.2rem;
}

/* ── The tool ──────────────────────────────────────────────────────────── */

.card {
  background: var(--accent-tint);
  border-radius: var(--panel-radius);
  padding: 1rem;
  margin: 0 0 1.1rem;
}

.card > h2:first-child { margin-top: 0; }

/* ⚠️ ONE DELIBERATE EXCEPTION to "drop the border", stated so it can be
   struck in one line if David disagrees. Once every card takes the tint,
   the answer card — which already had the tint — stops being distinguished
   from the three form cards above it, and spec §7 puts the headline "above
   everything else". 09a §5.3's stated reason for dropping borders is that
   "the hairline-box grid was most of the bank reading"; a single 2px accent
   border on the one card that carries the answer is emphasis, not grid. */
.card.answer {
  border: 2px solid var(--accent);
}

.fields { display: grid; gap: 1rem; }

.field { margin: 0; display: block; }

.field label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.hint {
  display: block;
  font-size: 0.875rem;
  color: var(--ink-soft);
  margin-top: 0.3rem;
}

input[type="number"],
input[type="text"],
select {
  font: inherit;
  /* 16px minimum on iOS or Safari zooms the page on focus. */
  font-size: 1rem;
  width: 100%;
  padding: 0.6rem 0.65rem;
  border: 1px solid #8a8a8a;
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}

.prefix-wrap, .suffix-wrap {
  display: flex;
  align-items: stretch;
}

.prefix, .suffix {
  display: flex;
  align-items: center;
  padding: 0 0.6rem;
  border: 1px solid #8a8a8a;
  background: var(--paper-tint);
  color: var(--ink-soft);
}

.prefix { border-right: 0; border-radius: 6px 0 0 6px; }
.prefix + input { border-radius: 0 6px 6px 0; }
.suffix { border-left: 0; border-radius: 0 6px 6px 0; }
.suffix-wrap input { border-radius: 6px 0 0 6px; }

/* ── "Take me to the answer" (Build-012 Part E) ─────────────────────────
   Full width on a phone, because it sits at the end of a column of
   full-width fields and a button narrower than the field above it reads as
   secondary. 14.84:1 on the accent, the same pairing as the masthead. */
/* 🔴 CE10, Build 038: 10px below, so the button and the answer card (0
   top margin on .card) don't sit flush against each other. Found in two
   places — both calculators' to-answer-row + answer-card pairing — and
   fixed once, here, since both share this class. */
.to-answer-row { margin: 1.25rem 0 10px; }

.to-answer {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 0.75rem 1.25rem;
  font: inherit;
  font-weight: 600;
  color: var(--accent-on);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 8px;
  cursor: pointer;
}

.to-answer:hover { opacity: 0.92; }

@media (min-width: 34rem) {
  .to-answer { width: auto; min-width: 16rem; margin: 0 auto; }
}

.hidden { display: none !important; }

/* ── The HTML `hidden` ATTRIBUTE, made to mean what it says ──────────────
   🔴 THIS RULE EXISTS BECAUSE THE ATTRIBUTE DID NOT WORK ON THIS SITE, and
   the way it failed is the kind that leaves no trace. `hidden` hides
   through the USER-AGENT stylesheet's own `[hidden] { display: none }` —
   and ANY author rule beats a UA rule, whatever the specificity. So
   `.field { display: block }` forty lines above quietly switched `hidden`
   off for every element carrying `class="field"`, and Build 028's pension
   fields — whose JavaScript was correct — were all on screen at once, with
   whichever one did not apply silently ignored. A reader could type into a
   box that did nothing and was never told. Found by David in a browser in
   about a minute, after four automated suites reported the build clean
   (Review 014's addendum, decision 159).

   ⚠️ THE FIX IS THE MECHANISM, NOT THE THREE INSTANCES. Converting those
   fields to `class="field hidden"` would have fixed the symptom and left
   the trap armed for the next session — and every future session will
   assume the attribute means what it says. It does now. `!important`
   because that is what it takes to beat an author `display` rule, and
   `.hidden` above needs it for the same reason. */
[hidden] { display: none !important; }

/* The pension percentage/fixed-amount swap link (Build 028.1, decision
   159). It is a grid item inside `.fields`, like every `.field` around it,
   so it needs the same margin reset — and it is deliberately SMALL: the
   percentage is the answer nearly every reader gives, and a link offering
   the minority path should not compete with the question above it. */
.pension-type-swap { margin: 0; font-size: 0.9375rem; }

/* ── The payslip reconciliation panel (Build 026, decision 189) ──────────
   Answers one payslip, beneath the monthly deduction figure. Lives outside
   #result in the markup (see the template's own comment for why) but reads
   as part of the same answer visually, so it carries no card-level margin
   of its own beyond what .card already gives every section on this page. */
.yesno {
  display: flex;
  gap: 0.75rem;
  margin: 0.75rem 0;
}

/* 🔴 Decision 176's tap-target split: a control tapped to ANSWER a
   question keeps the 44px floor — every calculator input, every <summary>,
   and now these. Not a link, so it does not take the 30px pill treatment
   decision 176 gave the topic nav. */
.yesno-btn {
  flex: 1;
  min-height: 44px;
  padding: 0.5rem 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid #8a8a8a;
  border-radius: 6px;
  cursor: pointer;
}

.yesno-btn[aria-pressed="true"] {
  color: var(--accent-on);
  background: var(--accent);
  border-color: var(--accent);
}

.payslip-check .fields { margin-top: 0.75rem; }

#payslipCheck-recalc-row { margin: 0.9rem 0 0; }

#payslipCheck-recalculate {
  min-height: 44px;
  padding: 0.5rem 1.25rem;
  font: inherit;
  font-weight: 600;
  color: var(--accent-on);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 8px;
  cursor: pointer;
}

#payslipCheck-result:empty { margin: 0; }
#payslipCheck-result .caption { margin: 0.9rem 0 0; color: var(--ink-soft); font-size: 0.9375rem; }
#payslipCheck-result .amount { font-size: 1.5rem; font-weight: 700; margin: 0.3rem 0; }
#payslipCheck-result .note { margin: 0.3rem 0 0; }

.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}

.verdict {
  display: none;
  margin-top: 0.9rem;
  padding: 0.75rem 0.85rem;
  background: var(--accent-tint);
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
  font-size: 0.9375rem;
}
.verdict.shown { display: block; }
.verdict span { display: block; }
.verdict .caveat {
  margin-top: 0.5rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.waiting { color: var(--ink-soft); margin: 0; }

/* The headline. One sentence, above everything else (§7). */
.headline {
  font-size: 1.3125rem;
  line-height: 1.32;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 0.6rem;
}

.headline .figure { white-space: nowrap; }

/* The two answer figures (09a §4): the lifetime total here, and the monthly
   deduction below. Accent on tint is 9.90:1 as of Build 009 Part B
   (was 13.29:1) — computed. ⚠️ 09a calls this one "the accent pill", which
   is ambiguous between "set in the accent" and "set in a tinted pill". The
   smaller reading is taken; making it a real pill is a background, a
   radius and some padding on this selector. */
.headline .figure.total { color: var(--accent); }

.headline-basis {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin: 0 0 0.9rem;
}

/* The short "not financial advice" variant, directly beneath the result.
   not-financial-advice.md: same type size as surrounding body text, not
   greyed out, not 10px, never inside a <details>. */
.advice-line {
  margin: 0 0 1.1rem;
  font-size: 1rem;
  color: var(--ink);
}

.cash-terms {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  margin: 0 0 1rem;
}

.deduction {
  border-top: 1px solid var(--rule);
  padding-top: 0.9rem;
  margin-top: 0.9rem;
}

.deduction .amount {
  display: block;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--accent);   /* 9.90:1 on the tint — computed */
}

/* Sits ABOVE the figure, not below it — see the comment in tool.js. The
   figure is the largest number on the page and must not be met bare. */
.deduction .caption {
  display: block;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  margin-bottom: 0.1rem;
}

.note { font-size: 0.9375rem; color: var(--ink-soft); }

.note-box {
  background: var(--accent-tint);
  border-radius: var(--panel-radius);
  padding: 0.75rem 0.85rem;
  margin: 0 0 1rem;
  font-size: 0.9375rem;
}

/* ⚠️ THE INVERSION RULE, and it is the thing 09a could not have foreseen.
   A pale tint is a surface, not a boundary (§4), so a tinted thing on a
   tinted parent is not merely low-contrast — it is 1.0:1, i.e. gone. Three
   selectors nest inside a tinted parent: .note-box and .path-switch button
   inside .card.answer, and .borrower-card inside .visual. Each is tinted on
   white and white on tint, with radius and padding carrying the boundary
   both ways. 📌 None of this was visible in the mockups, which rendered the
   answer card and the top of write-off.md and nothing that nests. */
.card .note-box,
.card .path-switch button {
  background: var(--paper);
}
.card .path-switch button[aria-pressed="true"] {
  background: var(--accent);
}

/* The threshold-freeze box keeps the warn palette and its border. That
   colour pair is semantic rather than decorative — it marks announced
   policy that is not yet enacted law — and the six tokens in 09a §4 do not
   include the warn pair, so the direction does not reach it. */
.note-box.policy {
  background: var(--warn-tint);
  border: 1px solid var(--warn-rule);
}

.note-box h3 { margin-top: 0; }

/* The sensitivity band — shown only after the answer (decision D). */
.sensitivity { margin: 1.2rem 0 0; }

.sensitivity h3 { margin-top: 0; }

.path-list { margin: 0 0 0.7rem; padding: 0; list-style: none; }

.path-list li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  align-items: baseline;
}

.path-list li:last-child { border-bottom: 0; }

.path-list .path-figure {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.path-list .is-current .path-name { font-weight: 700; }

.path-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
}

/* Filled/tinted rather than outlined (09a §5.4). Fully rounded, tint when
   unpressed, accent when pressed. Accent on tint is 9.90:1 as of Build 009
   Part B (was 13.29:1) and accent-on on accent is 14.84:1 — both computed. */
.path-switch button {
  font: inherit;
  font-size: 0.875rem;
  padding: 0.4rem 0.8rem;
  border: 0;
  border-radius: 999px;
  background: var(--accent-tint);
  color: var(--accent);
  cursor: pointer;
}

.path-switch button[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-on);
  font-weight: 700;
}

/* ── The chart ─────────────────────────────────────────────────────────── */

.chart-wrap { margin: 1.3rem 0 0; }

.chart-caption {
  font-size: 0.8125rem;
  color: var(--ink-faint);
  margin: 0 0 0.8rem;
}

.chart { width: 100%; height: auto; display: block; }

.chart-line { fill: none; stroke: var(--accent); stroke-width: 2.5; }
.chart-area { fill: var(--accent); opacity: 0.09; }
.chart-grid { stroke: var(--rule); stroke-width: 1; }
.chart-axis { stroke: var(--ink-faint); stroke-width: 1; }
.chart-writeoff {
  stroke: var(--ink);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
}
.chart-dot { fill: var(--accent); }
.chart-label { font-size: 10px; fill: var(--ink-soft); }
.chart-label.strong { fill: var(--ink); font-weight: 700; }

/* ── Footer ────────────────────────────────────────────────────────────── */

footer.site {
  margin-top: 2.5rem;
  border-top: 1px solid var(--rule);
  background: var(--paper-tint);
  padding: 1.25rem 0 2rem;
  font-size: 0.875rem;
  color: var(--ink-soft);
}

footer.site ul {
  list-style: none;
  margin: 0 0 0.75rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
}

footer.site .advice-line {
  font-size: 0.875rem;
  margin-bottom: 0.6rem;
}

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

/* ── Panels break out to the container edge (Build 009 Part B, Q6b) ──────
   .wrap gives everything 1.1rem of side padding. Panels then added their
   own INSIDE that — .card and .visual another 1rem, .note-box and details
   0.85rem, blockquote 0.9rem on the left only — so body text, panel text
   and quoted text each started at a different distance from the edge of
   the same page. Fix: panels carry .wrap's own side padding instead of
   their own, and a matching negative margin pulls their background out to
   .wrap's edge — only the background steps outward, text lines up with
   body text everywhere. Placed after every panel's own rule above, so
   nothing there needs touching and specificity stays equal throughout.
   ⚠️ AMENDED 16 August 2026. These were four rules — this pair plus a
   duplicated 48rem counterpart — because .wrap's padding changed at the
   breakpoint and the breakout had to be restated to track it. They now
   read --gutter, which the breakpoint redefines, so the 48rem duplicates
   are DELETED and the tracking cannot drift. */
.card, .visual, .note-box, details {
  margin-left: calc(-1 * var(--gutter));
  margin-right: calc(-1 * var(--gutter));
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

/* blockquote has no background, so there is nothing to "step outward" —
   only its left rule and its text need to line up with everything else.
   The rule sits at the .wrap edge and the padding is short by its 3px
   width, so the TEXT still starts exactly where body text does. */
blockquote {
  margin-left: calc(-1 * var(--gutter));
  padding-left: calc(var(--gutter) - 3px);
}

/* ⚠️ Nesting exceptions. Three panels above are also used NESTED inside
   another panel — .note-box and details both sit inside .card.answer
   (render.js), and blockquote sits inside details on the written pages
   (the "details blockquote" rule further up). A nested panel is already
   inside a parent that has just broken out; breaking out a second time
   would push it past its own parent's edge. So these three restore the
   ORIGINAL contained padding and cancel the negative margin. Specificity
   (two classes, or a class and a type, or two types) beats the plain
   .note-box / details / blockquote above regardless of source order or
   which side of the 48rem breakpoint it is compared against, so this one
   block covers both. */
.card .note-box,
.card details {
  margin-left: 0;
  margin-right: 0;
  padding-left: 0.85rem;
  padding-right: 0.85rem;
}
details blockquote {
  margin-left: 0;
  padding-left: 0.9rem;
}

/* ── Wider screens. Additive only. ─────────────────────────────────────── */

@media (min-width: 34rem) {
  .two-cards { grid-template-columns: 1fr 1fr; }
  h1 { font-size: 1.875rem; }
  .headline { font-size: 1.5rem; }
}

@media (min-width: 48rem) {
  body { font-size: 1.0625rem; }

  /* ONE line does what six used to. --gutter is redefined on :root so that
     .wrap AND every breakout rule above pick it up together; restating the
     breakout here is exactly the duplication that let the two drift. */
  :root { --gutter: 2rem; }
}

/* Respect a reader who has asked for less motion. Nothing here animates
   today; this is a standing guard for anything added later. */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

@media print {
  .topic-nav, .next-step, .path-switch, footer.site ul { display: none; }
  details[open], details { border: 0; padding: 0; background: none; }
}

/* ── The split: chips and the proportion bar — BASE BEHAVIOUR ───────────── */
/* 🔴 THIS EXISTS BECAUSE STAGE 3 BROKE THE REVERT BOUNDARY, and the break was
   found by rendering the reverted state rather than by assuming it.
   Every block above this point could be undone by deleting CSS, because
   nothing above it added MARKUP. The chips and the proportion bar do:
   render.js now always emits them, whichever direction is painted on top.
   ⚠️ With the Sunny Ledger block deleted and no rule here, the answer card
   showed a bare bullet list — "Income tax£360", no space, no styling — and
   an invisible zero-height bar. That is not "reverts to its 1b appearance";
   it is a visibly broken page, and it would have shipped that way to anyone
   who reverted the direction and deployed.
   📌 THE GENERAL POINT, worth more than the fix: a revert boundary drawn
   around a stylesheet stops being a boundary the moment the change also
   emits markup. Stages 1 and 2 could be undone in one step. From Stage 3 the
   revert is TWO steps — delete the block, AND remove renderSplitHtml and its
   one call site — and the build note says so in the same words.
   So the base takes responsibility for what the base emits: a plain,
   unopinionated pair-list that belongs to no direction. The bar is a
   component of the new direction alone and is HIDDEN here — it carries no
   information the chips beside it do not, which is also why it is
   aria-hidden. */
.chips {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 8px;
}
.chips .chip {
  border: 1px solid var(--rule-soft);
  border-radius: var(--panel-radius);
  padding: 10px 12px;
}
.chip-label { display: block; font-size: 0.8125rem; color: var(--ink-soft); }
.chip-value { display: block; margin-top: 4px; font-weight: 700; font-variant-numeric: tabular-nums; }
.proportion-bar { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   DIRECTION 1b — "LEDGER". Adopted 17 August 2026, decision 78.
   ══════════════════════════════════════════════════════════════════════════

   David scored the three Claude Design directions on the DJ Bank Scale
   (bank = 1, whacky youth brand = 10) on 17 August: 1a 3.5, 1b 5–6, 1c 8.
   Thread 019 set the target at 5–6. 📌 1b lands on it exactly, and 1c was
   rejected as overshooting a reader who is one cold, worried stranger
   arriving from a search rather than somebody choosing a brand to admire.

   WHY THIS IS ONE APPENDED BLOCK AND NOT THIRTY EDITS ABOVE
   --------------------------------------------------------
   Every rule here overrides an existing rule rather than replacing it, and
   the whole direction can be reverted by deleting from the banner above to
   the banner below. ⚠️ That matters because ONE THING IN HERE IS UNTESTED
   AND MIGHT FAIL (see THE RISK below), and this venture's own history is
   that a change spread across thirty places is a change nobody dares undo.
   📌 THE PHONE CHECK PASSED — 18 August 2026, Thread 035, read outdoors on
   a real handset. So the sentence that stood here — "fold this into the body
   of the file and delete the block; either way this is a staging state, not a
   resting place" — IS WITHDRAWN, deliberately, on 20 August 2026.

   ⚠️ DO NOT FOLD THIS BLOCK INTO THE FILE ABOVE. It was priced before it was
   declined: 435 lines of overrides merged one at a time into the rules they
   override, roughly half a day, carrying a real chance of visual regression,
   in exchange for NOTHING THAT ANY READER SEES. That is precisely the shape
   of work 00-Brief.md's materiality gate exists to stop, and the gate's own
   calibration table is full of jobs like it. This block is the resting place.

   ⚠️ The standing cost of that choice, written down so nobody meets it by
   surprise: the last third of this stylesheet overrides the first two thirds.
   Anyone editing a rule above line 1062 must check down here for an override,
   or the edit will appear to do nothing. That price is known and accepted,
   and it is smaller than the fold-in.

   WHAT THIS IS NOT
   ----------------
   🚫 No markup. No copy. No `render.js`, no `build-pages.js`, no engine.
   The Design exports are non-canonical (decision 74) — every money figure
   in them is invented and several clauses were cut, including one that is
   decision 70's entire remedy. NOTHING from an export reaches a deck or a
   template. This file is the only thing that moves.

   🚫 Not 1b's answer card. That region of the mockup is CD's invention over
   the *unrun* calculator, which it never captured. Its proposals there —
   deleting the balance chart, replacing the breakdown bar — are Tier 2,
   they are product decisions taken silently inside a design, and they are
   not adopted. See §7 below for the one place that bites.

   THE RISK — RAISED, TESTED, AND CLOSED ON 18 AUGUST 2026
   -------------------------------------------------------
   ✅ CLOSED. Leave --rule-1b alone unless a NEW observation reopens it.

   The risk as it stood before the test: 1b deletes the tinted panels and
   carries the entire structure of the page on hairline rules in --rule.
   COMPUTED: #E6E2EE on #F7F3EF is **1.15:1** — fainter than the 1.12:1 tint
   that Build 009 had to raise because it was vanishing on a phone in
   daylight, and fainter than the 1.50:1 it was raised to. Decorative rules
   carry no WCAG requirement, which is exactly why this would have gone
   unnoticed. Had the rules failed to read on a phone, a 750-word page would
   have become the undifferentiated wall of text that "my daughters wouldn't
   make it half way through" was about — the change would have made worse the
   very thing it exists to fix.

   ✅ THE TEST WAS RUN AND THE RULES PASSED. David read them on a handset,
   outdoors, 18 August 2026 (Thread 035). So the 1.15:1 value stands ON
   EVIDENCE rather than on argument, which is the only thing entitling it to
   sit this far below the tint that failed.

   ⚠️ Therefore: do NOT darken --rule-1b as a precaution, and do NOT re-derive
   this from the contrast figure alone — the figure predicted failure and the
   handset disagreed with it. If some future observation genuinely reopens the
   question, darken --rule-1b below and RECOMPUTE. Never nudge by eye.

   CONTRAST, COMPUTED WITH THE WCAG RELATIVE-LUMINANCE METHOD, NOT ASSERTED
   -----------------------------------------------------------------------
     ink       #171320 on paper #F7F3EF   16.53:1
     ink-soft  #5B5270 on paper           6.59:1
     accent    #2E1A5B on paper          13.44:1
     ink-faint #6b6b6b on paper           4.83:1   ⚠️ narrowest, was 5.29
     white on accent (the one filled CTA) 14.84:1
     ink on the warn tint (policy box)   16.96:1

   ✅ The site's floor RISES. Today's narrowest text pairing is ink-soft on
   the tinted panel at 4.85:1; this deletes that panel, so the pairing
   ceases to exist. ⚠️ The new narrowest is --ink-faint at 4.83:1, which is
   above the 4.5 bar but only just, and it is used only for the sources
   rule at the foot of a page.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Two variables carry the palette. Three of 1b's five colours — ink-soft,
     accent and rule — are already ours, unchanged, to the hex digit.
     📌 So this is NOT a reversal of decision 52: the plum survives. It
     moves off the masthead and into rules, swatches and figures. */
  --paper: #F7F3EF;
  --ink: #171320;

  /* Square corners are 1b's actual move — "the absence of radii", warm
     paper, hairline rules, typographic authority rather than boxes. */
  --panel-radius: 0;

  /* The hairline that replaces every panel. Separate from --rule so that
     the phone check has ONE value to change and so that darkening it
     cannot silently alter table borders and the sources rule as well. */
  --rule-1b: #E6E2EE;      /* 1.15:1 on paper. ✅ Tested outdoors on a handset
                              and PASSED, 18 Aug 2026. Read THE RISK above
                              before changing this. */
  --rule-strong: #171320;  /* the 2–3px ink rules under headings and fields */
}

/* ── Masthead. The band goes. ──────────────────────────────────────────────
   ⚠️ THIS CONTRADICTS DECISION 52, and the contradiction is deliberate and
   evidenced rather than accidental. 52's central finding was that on a
   content page the plum band "does nearly all the work". 1b removes the
   band entirely and still scores 5–6 — so either that finding was wrong,
   or it was a finding about HUE and not about THE BAND. 📌 David scored the
   direction as rendered, with no band in it. An inference from four
   treatments loses to a score taken on the thing itself.
   The wordmark stays styled text and must stay styled text — 09 §6. */
.masthead {
  background: var(--paper);
  border-bottom: 3px solid var(--rule-strong);
  padding: 1.25rem 0 1rem;
}

.wordmark {
  color: var(--ink);
  font-weight: 800;
  font-size: 1.625rem;
}

/* The plum, redeployed: a swatch under the wordmark rather than a field
   behind it. ::after rather than an element, so no markup changes. */
.wordmark::after {
  content: "";
  display: block;
  width: 44px;
  height: 4px;
  background: var(--accent);
  margin-top: 6px;
}

.masthead .strap { color: var(--ink-soft); }

/* ── Topic nav. Pills become a row of text. ───────────────────────────────
   Build 006 made these pills because seven underlined links in a grey box
   read as a directory index. 1b's answer to the same problem is different
   and also not a list of links: no box at all, a plain row, and the current
   page marked by a heavy plum underline. */
.topic-nav {
  background: none;
  border-bottom: 1px solid var(--rule-1b);
  padding: 0.8rem 0;
}

/* ⚠️ The nav's h2 is hidden VISUALLY ONLY. 1b shows no heading here, but
   this is a real <h2> labelling a landmark: `display: none` would take it
   out of the accessibility tree as well, which is a regression a sighted
   review cannot see. Same technique as .visually-hidden. */
.topic-nav h2 {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.topic-nav ul { gap: 0.75rem 1rem; }

.topic-nav li > * {
  padding: 0 0 4px;
  border-radius: 0;
  background: none;
  color: var(--ink-soft);
  border-bottom: 4px solid var(--ink-faint);
}

/* The calculator stops being a filled pill and becomes the weighted item. */
.topic-nav .is-hub > * {
  background: none;
  color: var(--ink);
  font-weight: 800;
}

/* ⚠️ MUST STAY AFTER .is-hub, for the reason the original rule gives: on
   the tool page the hub IS the current page, the selectors have equal
   specificity, and source order is what makes "you are here" stop
   shouting "go here". */
.topic-nav [aria-current="page"] {
  color: var(--ink);
  font-weight: 800;
  border-bottom-color: var(--accent);
}

/* ── Panels become rules. The largest single move in the direction. ────────
   Seven rules in this stylesheet fill a surface with --accent-tint. 1b
   fills none of them. What replaces the fill is a hairline above the block
   and the space around it.
   ⚠️ The breakout is CANCELLED here (margin/padding back to zero). Build
   009 gave panels a negative margin so their BACKGROUND could step out to
   the container edge while their text stayed aligned. With no background
   there is nothing to step out, and 1b's rules span the text column rather
   than the screen — so cancelling it is what makes the rules line up with
   the words above them. */
.card, .visual, .note-box, details, .verdict {
  background: none;
  border-radius: 0;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}

.card {
  border-top: 1px solid var(--rule-1b);
  padding-top: 1.1rem;
  padding-bottom: 0;
  margin-bottom: 1.5rem;
}

/* ⚠️ Equal specificity to the Build 009 nesting exception above, and later,
   so nested panels lose their 0.85rem inset too and align with everything
   else. Without this a .note-box inside the answer card would be the only
   indented thing on the page. */
.card .note-box,
.card details {
  padding-left: 0;
  padding-right: 0;
}

/* Build 006's inversion rule existed because a tint on a tint is 1.0:1 —
   gone. With no tints anywhere, the inversion has nothing to invert. */
.card .note-box { background: none; }

.note-box {
  border-top: 1px solid var(--rule-1b);
  padding-top: 0.8rem;
  padding-bottom: 0;
}

/* ⚠️ The threshold-freeze box KEEPS its own palette and its border, for the
   reason the original rule gives: warn is semantic rather than decorative —
   it marks announced policy that is not yet law — and 1b's five colours do
   not include a warn pair, so the direction does not reach it. Ink on the
   warn tint computes 16.96:1. */
.note-box.policy {
  background: var(--warn-tint);
  border: 1px solid var(--warn-rule);
  padding: 0.75rem 0.85rem;
}

details {
  border: 0;
  border-top: 1px solid var(--rule-1b);
  padding-top: 0.6rem;
  padding-bottom: 0;
}

blockquote {
  margin-left: 0;
  padding-left: 0.9rem;
  border-left-color: var(--rule-1b);
}

.verdict {
  border-left: 0;
  border-top: 2px solid var(--accent);
  padding: 0.75rem 0 0;
}

/* ── The answer card. Emphasis without a box. ──────────────────────────────
   Build 006 gave this card a 2px accent border as "ONE DELIBERATE
   EXCEPTION to drop the border", because once every card took the tint the
   answer card stopped being distinguished from the three form cards above
   it, and spec §7 puts the headline above everything else. That argument
   survives the direction change; only the device changes. A plum swatch
   above the card does the job a border did, in 1b's own vocabulary. */
.card.answer {
  border: 0;
  border-top: 3px solid var(--rule-strong);
  padding-top: 1.2rem;
}

.card.answer::before {
  content: "";
  display: block;
  width: 40px;
  height: 4px;
  background: var(--accent);
  margin: 0 0 0.9rem;
}

/* 🚫 NOT ADOPTED, and this is the one place 1b is refused on its own terms.
   The mockup sets the monthly deduction at 56px against a 26px headline.
   Spec §7 says explicitly not to lead with the monthly figure, and TWO
   consecutive builds independently named the existing 2rem-against-
   1.3125rem as the weakest thing on the most important page. 1b makes that
   worse, not better. 📌 The sizes stay as they are; only the box goes. */

/* ── Typography ───────────────────────────────────────────────────────────
   1b's authority comes from weight and rules, not from size. */
h1 { font-weight: 800; letter-spacing: -0.02em; }

h2 {
  font-weight: 800;
  margin: 2.2rem 0 0.6rem;
}

/* The plum swatch under each claim heading — decision 30's headings given
   1b's mark. ::after, so no markup moves. */
.page h2::after,
article h2::after {
  content: "";
  display: block;
  width: 40px;
  height: 4px;
  background: var(--accent);
  margin: 0.55rem 0 0.75rem;
}

/* The swatch is for claim headings on written pages only — not for the
   calculator's section labels, the nav, the next-step block or a panel
   heading, none of which are claims. */
.topic-nav h2::after,
.next-step h2::after,
.card h2::after,
.note-box h2::after { content: none; }

/* Calculator section labels in small caps — 1b's treatment of "First —
   which plan are you on?" and "Now your numbers". These are labels, not
   claims, and 1b marks the difference. */
.card > h2:first-child {
  font-size: 0.9375rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
}

/* The standfirst loses its left rule and becomes an italic line — the
   rule was doing the job the hairlines now do everywhere else. */
.standfirst {
  border-left: 0;
  padding-left: 0;
  font-style: italic;
  font-weight: 400;
  font-size: 1.125rem;
  color: var(--ink-soft);
}

/* The bolded answer line under each claim heading carries more weight in
   1b, because with the panels gone it is the page's second-loudest thing. */
.answer-line {
  font-size: 1.125rem;
  font-weight: 800;
  line-height: 1.3;
}

/* ── The form ─────────────────────────────────────────────────────────────
   Boxes become underlines. The 44px touch targets are untouched — this is
   paint. ⚠️ Build 012's paired slider/typed-box behaviour this comment used
   to name is gone as of Build 038, CE9 — the sliders were removed. */
.field label { color: var(--ink-soft); }

.field input,
.field select {
  border: 0;
  border-bottom: 2px solid var(--rule-strong);
  border-radius: 0;
  background: transparent;
  font-weight: 700;
}

.prefix, .suffix {
  border: 0;
  border-bottom: 2px solid var(--rule-strong);
  border-radius: 0;
  background: transparent;
  color: var(--accent);
  font-weight: 800;
}
.prefix, .prefix + input, .suffix, .suffix-wrap input { border-radius: 0; }

/* "Take me to the answer" becomes a text link with a heavy plum underline.
   ⚠️ Build 012 made this full-width on purpose — a button narrower than
   the fields above it reads as secondary. 1b's version is left-aligned and
   full-width, so that reasoning is preserved. */
.to-answer {
  background: none;
  border: 0;
  border-bottom: 3px solid var(--accent);
  border-radius: 0;
  color: var(--accent);
  font-weight: 800;
  font-size: 1.25rem;
  text-align: left;
  padding: 0.75rem 0;
  min-height: 0;
}
.to-answer:hover { opacity: 1; text-decoration: none; }

@media (min-width: 34rem) {
  .to-answer { width: 100%; min-width: 0; margin: 0; }
}

.path-switch button {
  background: none;
  border-radius: 0;
  border: 0;
  border-bottom: 2px solid transparent;
}
.card .path-switch button { background: none; }
.path-switch button[aria-pressed="true"],
.card .path-switch button[aria-pressed="true"] {
  background: none;
  color: var(--accent);
  font-weight: 800;
  border-bottom-color: var(--accent);
}

/* ── Tables. A heavier head rule, hairlines between rows. ───────────────── */
th { border-bottom: 2px solid var(--rule-strong); }
td, tbody th { border-bottom: 1px solid var(--rule-1b); }

/* ── The next-step block and the footer ───────────────────────────────────
   ⚠️ Neither region was in the capture, so 1b has no opinion on them. These
   are the minimum needed to stop them being the only boxes left on an
   otherwise unboxed page — a judgement, not evidence.
   📌 The hub link KEEPS its fill. It is the one call to action on a content
   page, white on accent is 14.84:1, and 1b's own submit button shows the
   direction is willing to shout once per screen. Square, not round. */
.next-step {
  background: none;
  border-top: 1px solid var(--rule-1b);
  border-radius: 0;
  padding: 1.1rem 0 0;
}
.next-step-hub a { border-radius: 0; }
.next-step li a {
  background: none;
  border-radius: 0;
  padding: 0 0 3px;
  border-bottom: 2px solid var(--rule-1b);
}

footer.site { border-top: 1px solid var(--rule-1b); }

/* ── Anything still round ─────────────────────────────────────────────────
   Swept last, so nothing above has to remember to be square. */
.skip-link, .bar-track, .bar-fill, .borrower-card, .two-cards > * {
  border-radius: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   END DIRECTION 1b — and this block is PERMANENT, not staging (20 Aug 2026).
   ✅ The revert route below is still real and still cheap, and keeping it is
   the whole reason this stays an appended block rather than being folded in:
   delete from the opening banner to here and the site returns to exactly its
   pre-17-August appearance.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   DIRECTION 3c — "SUNNY LEDGER, PUSHED". Staged 9 September 2026, Thread 086.
   ══════════════════════════════════════════════════════════════════════════

   🔴 ADOPTED. This banner said "STAGING STATE, NOT YET ADOPTED" until 10
   September 2026 and it was four statements out of date by then: Stage 3 has
   been built on this block, markup and decks and build-pages.js have all been
   touched, and it is deployed. ⚠️ THAT MATTERED because this banner is the
   revert boundary — a wrong instruction living inside the thing it instructs.
   ⏳ ONE THING IS STILL TRUE AND STILL OPEN: the DJ Bank Scale score has never
   been taken. Decision 76 set the target at 5–6 and rejected a direction that
   came in at 8. The outdoor read was done and was fine; the number was not
   taken, and it is on the open register. That is now the only claim here.

   Source: 19-Visual-Style-Guide.html (decision 175 — THE MASTER). The Claude
   Design canvas file and 18-02-Style-Guide-Additions.md are superseded and
   are not built from. A change to how the site looks starts in 19, not here.

   WHY THIS IS AN APPENDED BLOCK, AGAIN
   ------------------------------------
   Same shape and same reasoning as DIRECTION 1b above, which is now three
   weeks old and has been proved by use: every rule here overrides rather
   than replaces, and the whole direction reverts by deleting from this
   banner to the one at the bottom. 📌 That matters more here than it did
   for 1b, because 1b was scored before it was written and this one is
   written in order TO be scored.

   ⚠️ THE STANDING COST, RESTATED because this block makes it worse. The
   stylesheet now has THREE layers: the base, 1b's overrides, and these.
   Anyone editing a rule must check BOTH blocks below it. That price was
   known and accepted for one block; a second is the point at which the
   fold-in argument should be re-priced — but not now, and not while the
   direction might yet be reverted wholesale.

   WHAT THIS IS NOT
   ----------------
   ⚠️ THIS PARAGRAPH IS HISTORY, KEPT BECAUSE IT RECORDS THE ORIGINAL SCOPE.
   It said "no markup, no copy, no render.js, no build-pages.js, no deck —
   two font files are the only new files." That held for one afternoon.
   Decisions 172, 174 and 176 have since touched render.js, build-pages.js,
   the templates and the decks. 📌 Decision 74 still stands on its own terms:
   nothing from a design export reaches a deck or a template UNREAD — the copy
   that has changed was written for the site, not lifted from a drawing.
   🚫 Not the chips row, the proportion bar, the company mark, or the
   answer block's full-bleed band. All four need markup and all four are
   Stage 3, deliberately after the scoring.
   🚫 Not the "Being built next" strip, not the new home-page copy, and not
   the answer block's figure-leads-the-sentence change. Those are content
   and product decisions, and they are David's, separately.

   TYPOGRAPHY — THE RULE THAT WAS NEVER A DECISION
   -----------------------------------------------
   09a said "No web font, no dependency, no decision-log entry needed", and
   its reason was that Direction D's Avenir Next exists on macOS and not on
   Windows or Android — 📌 "a type decision made on a Mac is a decision about
   the reviewer's device."
   ⚠️ READ CAREFULLY, THAT ARGUMENT POINTS THE OTHER WAY. A self-hosted
   woff2 renders identically on every device. The SYSTEM STACK is the option
   that renders as San Francisco on iOS, Roboto on Android and Segoe on
   Windows. The rule's own test fails the rule. Ruled by David, 9 September.

   Two files, both SIL OFL 1.1, self-hosted, no third party, no npm
   dependency, no build step:
     assets/fonts/bricolage-grotesque-latin-wght-normal.woff2   41,344 bytes
     assets/fonts/instrument-sans-latin-wght-normal.woff2       30,092 bytes
   71,436 bytes total, latin subset, variable weight axis so ONE file covers
   every weight the guide uses (Bricolage 200–800, Instrument 400–700).

   🚫 The Google Fonts <link> in the design exports is NOT used. A
   fonts.googleapis.com stylesheet is a third-party request on every page
   load of a site that runs a consent banner. Self-hosting avoids it.

   ⚠️ TWO THINGS DELIBERATELY NOT SHIPPED, both priced against the
   materiality gate rather than dropped by accident:
   1. Bricolage's OPTICAL SIZE AXIS. The opsz build is 77KB against 41KB and
      the wght build has no opsz. The guide sets its own letter-spacing
      (−0.05em on display) which does much of the same work. If display type
      reads loose on the handset, this is the lever — it is not a mystery.
   2. THE ITALIC FACE. Instrument Sans italic is another 31KB, doubling the
      text payload for the single "Estimates, not advice" sign-off line —
      and the italic/plain sign-off fork is an OPEN ITEM anyway, product one
      italicising and product two not. Synthetic oblique is used instead.
      Known and accepted; look at it on the handset.

   CONTRAST, COMPUTED WITH THE WCAG RELATIVE-LUMINANCE METHOD
   -----------------------------------------------------------
   ⚠️ The ground moves from white/#F7F3EF to CREAM #FFF3E0, so every
   inherited token was RE-DERIVED rather than carried. Not asserted, not
   read off the style guide — the guide's own eleven ratios were checked
   independently first and all eleven were correct, which is why its palette
   is trusted this far and no further.

     ink       #22201C on cream          14.83:1
     body      #3E382F on cream          10.57:1
     muted     #6B5D4B on cream           5.82:1
     teal link #0E4F4A on cream           8.56:1
     visited   #B14A34 on cream           4.91:1
     ink on the pill bed #FDE9CC         13.71:1
     muted on the pill bed                5.38:1
     ink on the warn tint (kept)         15.11:1
     cream on teal                        8.56:1
     ink on marigold (the one filled CTA) 8.14:1
     marigold figure on teal              4.70:1  ⚠️ see below
     visited on the pill bed              4.54:1  ⚠️ NARROWEST

   ⚠️ THE FLOOR DROPS, and it drops onto two places worth naming. Today's
   narrowest text pairing is --ink-faint at 4.83:1. Here it is a footer
   VISITED LINK on the pill bed at 4.54:1, and the second narrowest is the
   MARIGOLD ANSWER FIGURE ON TEAL at 4.70:1 — the single most important
   number on the site. Both clear the 4.5 bar; neither has margin. 📌 If any
   colour here changes, RECOMPUTE. Do not assert, and do not nudge by eye.

   ⚠️ THE HAIRLINE IS A NEW VALUE AND ITS EVIDENCE IS INHERITED, NOT OWN.
   #EDD9BC on cream computes 1.26:1. 1b's --rule-1b was 1.15:1 and PASSED a
   real outdoor handset test on 18 August. This is fainter than nothing and
   stronger than the value that passed, so the evidence transfers in the
   favourable direction — but it transfers, it was not taken. Read the
   hairlines specifically during the handset check.
   ══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: "Bricolage Grotesque Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(/assets/fonts/bricolage-grotesque-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: "Instrument Sans Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 400 700;
  src: url(/assets/fonts/instrument-sans-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root {
  /* ── The five colours, and no sixth (guide §01) ───────────────────────── */
  --paper: #FFF3E0;        /* Cream. The ground. Every page starts here */
  --ink: #22201C;          /* Type and every keyline. Never pure black */
  --ink-soft: #3E382F;     /* Body ink */
  --ink-faint: #6B5D4B;    /* Muted — captions, helper text, the sources rule */

  /* ⚠️ --accent BECOMES TEAL, NOT MARIGOLD, and this is the load-bearing
     mapping in the whole block. Seven rules in this stylesheet put
     --accent-on (white) on top of --accent. White on marigold is 1.8:1 and
     would have been an instant, silent, site-wide accessibility failure in
     exactly the places that matter most — the one filled call to action
     among them. 📌 The guide's own rule is that MARIGOLD NEVER CARRIES TEXT
     AGAINST CREAM and that clay and marigold take ink labels only. Teal is
     the colour the guide gives to links and to the answer field, and it is
     the one that keeps every inherited pairing valid. */
  --accent: #0E4F4A;
  --accent-on: #FFF3E0;    /* cream on teal, 8.56:1 */
  --accent-tint: #FDE9CC;  /* the pill bed */

  /* ── Marigold, applied ONLY where the guide says ──────────────────────── */
  /* 📌 "Marigold means action and nothing else — it is the button, the
     current pill, the highlight and the answer figure." It is deliberately
     NOT wired into --accent, so it cannot spread by inheritance. Every use
     below is written out by hand, and that is the mechanism. */
  --action: #F2A93B;
  --action-ink: #22201C;   /* 8.14:1 — the ONLY text colour allowed on it */
  --action-hover: #E89A26;
  --action-active: #DC8F1C;

  --clay: #E2725B;         /* the deduction that costs most. Ink labels only */
  /* 🔴 DECISION 214, Build 032. Not a sixth colour — a SHADE of clay, same
     move as --action-hover/--action-active being shades of marigold. Same
     hue and saturation as --clay (10.2°, 70%), lightness 62% → 44%.
     Needed because the rail's bare chevron (decision 213 dropped its
     circular button) sits straight on the nav band and has to carry its own
     contrast rather than borrowing a fill's: --clay bare on the band is
     2.61:1, below the 3:1 a control must reach. #DE5F45 (8% darker, 3.04:1)
     was rejected on MARGIN, not appearance — it clears the threshold by
     0.04, and this project's own history is that a value that "just passes"
     goes stale unwatched.
     COMPUTED: 4.53:1 on the nav band (--accent-tint), 4.90:1 on cream paper
     (--paper), 5.38:1 on the white pill bed (--mark-bed) — all three grounds
     it can land on, and clear of 4.5:1 too, so it survives being drawn
     smaller or reused on a label. */
  --clay-deep: #BF3D22;
  --mark-bed: #FFFFFF;     /* pill and mark containers */
  --recessed: #F6E7CF;
  --teal-caption: #A9D3CC; /* 5.76:1 on teal */

  /* 🔴 BUILD 039, items 4/5/11, decision 246. The wordmark's colour was an
     ACCIDENT — there is no clay in the logo. It read rust on David's phone
     only because the wordmark links to "/", every returning reader has
     visited it, and the unscoped `a:visited` rule below recolours it. He
     chose the accidental version on its own merits, so it is now pinned
     here on purpose, in both visited and unvisited states, and given to
     the live product glyphs too so the two can never drift apart again.
     4.91:1 on cream, measured, clearing 4.5:1 for the first time (clay
     itself is 2.82:1). Sits between --clay and --clay-deep and is neither
     of them — do not "tidy" it into one of those. */
  --rust: #B14A34;

  --rule: #EDD9BC;
  --rule-soft: #EDD9BC;
  --rule-1b: #EDD9BC;      /* the 1b block's hairline, re-pointed at cream */
  --rule-strong: #22201C;
  --paper-tint: #FDE9CC;

  /* ⚠️ THE WARN PAIR IS DELIBERATELY UNCHANGED, for the same reason 1b gave:
     warn is SEMANTIC, not decorative — it marks announced policy that is not
     yet law — and 3c's five colours contain no warn pair, so the direction
     does not reach it. Ink on the warn tint computes 15.11:1 on the new
     ground. Using clay here would have made a policy note look like a
     deduction, which is a different statement. */
  --warn-tint: #fdf6e7;
  --warn-rule: #e0c98a;

  /* ── Radii (guide §03). 1b set this to 0; the direction is round again ── */
  /* 7 highlight · 16 chip and card · 22 answer · 26 shell · full for taps */
  --panel-radius: 16px;
  --radius-highlight: 7px;
  --radius-answer: 22px;
  --radius-tap: 999px;

  /* ── Type ─────────────────────────────────────────────────────────────── */
  /* Bricolage never sets a paragraph. Instrument Sans never sets a figure. */
  --font-text: "Instrument Sans Variable", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Bricolage Grotesque Variable", -apple-system,
    BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* ── Type, applied ───────────────────────────────────────────────────────── */

body { font-family: var(--font-text); }

h1, h2, h3, h4,
.headline .figure, .deduction .amount, .bar-figure, .bar-value,
.path-list .path-figure, .card-punch, .to-answer, .wordmark {
  font-family: var(--font-display);
}

/* ⚠️ Display letter-spacing does the work the optical-size axis would have
   done, and it is why opsz is not shipped. Tighter as the size grows. */
.wordmark { letter-spacing: -0.05em; font-weight: 800; }
h1 { font-weight: 800; letter-spacing: -0.045em; }
h2 { font-weight: 800; letter-spacing: -0.04em; }
h3, h4 { font-weight: 800; letter-spacing: -0.03em; }
.headline .figure, .deduction .amount { letter-spacing: -0.05em; }

/* The guide's own floor: never below 16px on an input, or iOS zooms the page
   and the reader loses their place. The base sets 1.0625rem/17px already. */
.field input, .field select { font-size: 1rem; }

/* ── Links (guide §05) ───────────────────────────────────────────────────── */

a { text-underline-offset: 2px; }
a:visited { color: var(--rust); }

/* ── Masthead. Cream ground, 3px ink, no swatch ──────────────────────────── */
/* 1b put a plum swatch under the wordmark. 3c's masthead is a plain cream
   band closed by a single 3px ink rule, so the swatch goes. 📌 The wordmark
   stays styled text — 09 §6, and the company mark is Stage 3 and only if
   David rules the logo exclusion off. */
.masthead {
  background: var(--paper);
  border-bottom: 3px solid var(--rule-strong);
}
.wordmark::after { content: none; }

/* ── The "All Topics" control's 3c vocabulary (decision 212, Build 032) ───
   Base already draws this ink-on-cream — see its own comment for why a
   single set of colours now covers every direction. The one thing left to
   add here is the filled white bed 3c gives every other pill-shaped
   control (.path-switch button, the topic-nav pills below), which base
   deliberately leaves transparent. */
.all-topics summary {
  background: var(--mark-bed);
}

/* 🔴 CE1, Build 038: the arrow, sized to sit on the same line as the text
   without touching the control's own height (44px min-height, unchanged —
   measured before and after). Down when closed, up when open — one path,
   flipped, so there is only ever one glyph to keep in sync with the other. */
.all-topics-arrow {
  width: 14px;
  height: 14px;
  margin-left: 0.4rem;
  flex: none;
  transition: transform 0.16s ease;
}
.all-topics[open] .all-topics-arrow { transform: rotate(180deg); }

/* ── The rail's chevron — clay, in a deeper shade (decision 214) ──────────
   Bare, with the circular button gone (decision 213), the chevron carries
   its own contrast rather than borrowing a fill's — see --clay-deep's own
   comment in the palette above for the full reasoning and the four
   candidates it was measured against. */
.rail-arrow {
  color: var(--clay-deep);
  transition: opacity 0.16s ease;
}

/* ── Topic nav. Pills come back, and the current one is marigold ─────────── */
/* 📌 Partly a REVERT rather than a build: the base stylesheet had pills here
   before 1b turned them into a plain underlined row. This restores the pill
   and gives it 3c's vocabulary — white bed, 2px ink keyline, fully rounded,
   current in marigold at weight 700. The guide: "Current is marigold and
   700. The rest are white and 500." */
.topic-nav {
  background: var(--accent-tint);
  border-bottom: 1px solid var(--rule);
  font-size: 0.8125rem;
}

/* 🔴 HEIGHT. The pill row measured 295px at 390px against 1b's 127px on the
   student-loans topic pages — about a third of a handset screen spent on the
   menu before the headline. David asked for the vertical gaps INSIDE the pills
   to be tightened. ⚠️ MEASURED, AND THE PADDING LEVER IS INERT ON ITS OWN: the
   pill's vertical padding was overridden by min-height: 44px, so 11px → 4px
   moved the nav 295px → 295px. 🔴 THE min-height IS NOW GONE — decision 176,
   David's instruction, 10 September 2026, after the measurement above was put
   to him. The 44px tap-target floor NO LONGER APPLIES TO LINK PILLS: the topic
   nav, the More-from hub link and the answer button are sized by their own
   padding. ⚠️ IT STILL APPLIES, UNCHANGED, TO EVERY CONTROL THAT SETS A VALUE —
   .field input/select (line ~740), .path-switch button, and summary (decision
   173). That split is the whole of the ruling: a link you tap to go somewhere
   is not a control you tap to answer a question, and David accepted the cost
   of the first while declining to touch the second.
   📌 The guide was changed in the same pass. A rule that lives only here is a
   rule the next session cannot find — §05 of 19-Visual-Style-Guide.html now
   states the split, so this comment and the guide agree.
   📌 What actually sets the height is the NUMBER OF ROWS. Tightening the gaps
   BETWEEN pills and their side padding fits seven links into four rows instead
   of five: 295px → 220px, headline up 74px, every link still visible, every
   target still 44px. Four rows is the floor at 390px — 6px gaps and 9px sides
   buy only a further 9px and make the row look cramped, so this stops here.
   ⚠️ SCOPED AWAY FROM .home-topics, whose ul is a COLUMN of cards (base
   stylesheet, Build 009 Part A) — an 8px gap there tightens the card stack,
   which is a different component with a different job. Both rendered. */
.topic-nav:not(.home-topics) {
  padding-top: 0.6rem;
  padding-bottom: 0.6rem;
}
.topic-nav:not(.home-topics) ul { gap: 8px; }

.topic-nav li > * {
  padding: 5px 12px;
  border-radius: var(--radius-tap);
  border: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  background: var(--mark-bed);
  color: var(--ink);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
}
/* 🔴 THE HUB IS NOT MARIGOLD, AND THIS WAS A REAL BUG CAUGHT BY RENDERING.
   The first version of this block gave .is-hub and [aria-current] the same
   marigold fill. They are DIFFERENT ELEMENTS in the markup — .is-hub sits on
   the <li>, aria-current on the <span> inside another one — so both matched
   and TWO pills read as "you are here" on every topic page. 📌 It is also
   exactly what the guide forbids: "Current is marigold and 700. The rest are
   white and 500." The hub is distinguished by WEIGHT, not by colour, which
   keeps marigold meaning one thing. */
.topic-nav .is-hub > * {
  background: var(--mark-bed);
  color: var(--ink);
  font-weight: 700;
}
/* ⚠️ MUST STAY AFTER .is-hub, for the reason the base and 1b both give: on
   the tool page the hub IS the current page, the selectors have equal
   specificity, and source order is what makes "you are here" stop shouting
   "go here". Kept in the same order here so the behaviour survives. */
.topic-nav [aria-current="page"] {
  background: var(--action);
  border-color: var(--ink);
  color: var(--action-ink);
  font-weight: 700;
}

/* ── The home page's product list ─────────────────────────────────────────
   🔴 CE4, Build 038 RETIRES THE CARD SHAPE THIS SECTION USED TO DESCRIBE.
   Stage 3 (decision 176) drew these as cards — 3px ink keyline, --mark-bed
   fill, flush left — and that stood until this build. It is now glyph
   outside, pill around the name only, no keyline anywhere in the row: see
   the rules below, and the shared bare-glyph rule after this block. */
.topic-nav.home-topics {
  background: none;
  border-bottom: 0;
}
.topic-nav.home-topics ul { width: 100%; gap: 8px; }
.topic-nav.home-topics li { width: 100%; }
/* 🔴 CE4, Build 038, replacing the card shape above (David's ruling, the
   Home List Marks mock, 13 September): the glyph comes OUT of its bed and
   sits OUTSIDE a pill that now wraps the NAME ONLY, not the whole row. No
   more 3px keyline, no more --mark-bed card — the row itself carries no
   border or fill of its own. */
.topic-nav.home-topics li > * {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 4px 0;
  /* ⚠️ Reset against the WITHIN-product pill rule above (`.topic-nav li > *`,
     unscoped): border, background and radius on the row itself, which
     .home-topics shares the .topic-nav class with. Explicit here, not
     assumed, because a card look with no visible declaration to blame is
     exactly the bug this specificity gap produces. */
  border: 0;
  border-radius: 0;
  background: none;
  font-weight: 700;
  line-height: 1.35;
  text-align: left;
  min-height: 0;
}
.topic-nav.home-topics .mark-product { flex: none; }
/* ⚠️ NOT flex:1 any more — a flex child that fills the row is the row being
   the pill's box, and the mock is explicit that the pill wraps the name,
   not the row. It sizes to its own text now. */
.topic-nav.home-topics a .row-label {
  background: var(--accent);
  color: var(--accent-on);
  border-radius: 999px;
  padding: 6px 13px;
  font-weight: 700;
}
.topic-nav.home-topics a:hover .row-label { text-decoration: underline; }

/* 🔴 THE RESERVED ROWS. Not links, not tappable, and they must not read as
   either. */
.topic-nav.home-topics li.coming > * {
  color: var(--ink-faint);
  font-weight: 600;
  cursor: default;
}
/* 🔴 BUILD 039, item 9 (decision 246) REVERSES CE4's own reasoning above:
   CE4 stripped the pill from reserved rows precisely so the pill's fill
   could carry live-versus-not on its own. Item 8 (above) splits the list
   in two, so POSITION now carries that signal — stronger than a colour —
   which is why the pill comes BACK here, outlined rather than solid, with
   the tag folded into it: "Pensions - Coming soon", sentence case, one
   pill. Heights match the live pill exactly (29.55px, measured) — 2px
   less padding on each side than the live pill's 6px 13px, because the
   2px keyline is absorbed inside that difference rather than added on
   top of it. `cursor: default` above already applies to this span; kept
   plain (not a link) is why the row can carry a pill and still not read
   as tappable — it looks like a tag, not a button. */
.topic-nav.home-topics li.coming .row-label {
  display: inline-block;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--accent);
  border-radius: 999px;
  padding: 4px 11px;
  font-weight: 700;
}

/* 🔴 BUILD 039, item 10 (decision 246): consistent spacing around both
   lists. `.home-opener` and `.home-why` are index.template.html's OWN
   markers (added alongside `.opener`/the bare "why" paragraph, both of
   which are shared with other pages' openers and cannot be touched
   globally) — scoping this fix to the home page ALONE rather than to
   every page that happens to open with a paragraph. Zeroing both
   paragraphs' own margin-bottom, and the first reserved row's
   hairline-above padding/margin (which used to add 16px on top of the
   list's own spacing, for no reason the other boundary shared), leaves
   THREE VISUAL GAPS 1px apart — the last pixel is the hairline's own
   border-top, which is the point of it. MEASURED on a rendered page:
   16.8 / 16.8 / 17.8px. The air that remains, on all three, is the
   pill's own line-height and padding — no margin is added anywhere. */
.home-opener,
.home-why {
  margin-bottom: 0;
}
/* The hairline-above's own padding/margin is zeroed too — see that rule's
   own comment, far below, for why. */

/* 🔴 CE4/CE6, Build 038 — the shared bare-glyph rule. Both the home list's
   own glyphs and (CE6) every product masthead's glyph lose the 24px bed
   (border, background, radius) that .mark-product gave them since decision
   169: clay, no keyline, sized up. .mark-company (the site wordmark's own
   drawing) is a different class and is not touched here.
   🔴 CORRECTED, BUILD 039, ITEM 12 (decision 249). This comment used to
   claim the "All Topics" sheet's own rows were "NOT this job's and keep
   the old bedded 15px treatment untouched" — FALSE, and it was false the
   day it was written: the sheet sits INSIDE header.masthead, so
   `.masthead .mark-product` below reaches it too, which is how the sheet
   got this treatment by accident in Build 038. Decision 249 ADOPTS that
   accident deliberately (28px, bare, on every page) rather than reverting
   it — the two lists reading the same way is the better outcome. Build
   038's own note verified what its selector SAID it reached, not what it
   actually reached — decision 245's keeper, stated here again because
   this is the comment that needed it. */
.masthead .mark-product,
.topic-nav.home-topics .mark-product {
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  background: none;
}
.masthead .mark-product svg,
.topic-nav.home-topics .mark-product svg {
  width: 28px;
  height: 28px;
  fill: var(--clay);
}
/* 🔴 BUILD 039, item 9: `.topic-nav.home-topics .row-tag` (decision 216's
   own 9px uppercase tag rule) is DELETED, not merely overridden — the
   separate `.row-tag` element it styled no longer exists in this list's
   markup at all (sites/thirtyish/index.template.html), because the tag
   now folds into `.row-label` itself, above. A rule with no element left
   to reach is the orphan decision 166 exists to catch on a deck; the same
   logic applies to a selector. `.all-topics-sheet .row-tag` (far above)
   is untouched — the sheet's own rows keep their separate tag element,
   item 9 being the home page list's alone. */

/* 🔴 THE HAIRLINE ABOVE THE FIRST RESERVED ROW — decision 192(d), moved by
   decision 216 (13 September 2026, Build 032.1 fixes a comment this build
   left stale — Review 024 F6). Originally sat above money-worries as the
   LAST row, with David's reason for putting it last being that it
   underpins everything above: a statement about DIFFERENCE. 216 reordered
   money worries to THIRD, live, and moved the hairline with it — it now
   separates the THREE live rows (student loans, take-home pay, money
   worries) above from the five reserved "Coming Soon" rows below, not one
   row from five. The reasoning survives the move unchanged: bare, the list
   would read as an unbroken column of "Coming" rows with a live link lost
   among them; the rule is what still says "the rows above this line are
   real". Sits ABOVE the row's own border — 3px on a live row, 1px on a
   reserved one, the class is applied to either — inside the ul's own 8px
   gap rather than adding a second one.
   🔴 BUILD 039, item 10 (decision 246): padding-top 12px and margin-top
   4px are GONE — they used to add 16px on top of the list's own spacing,
   for a boundary the other side of the split (opener → live list) does
   not share, which is exactly the unevenness item 10 exists to remove.
   The border-top alone is enough to say "this one is not like those";
   MEASURED on a rendered page, the three visual gaps around both lists
   are now 16.8 / 16.8 / 17.8px — the last pixel is this border. */
.topic-nav.home-topics li.hairline-above {
  border-top: 1px solid var(--rule);
}

/* ── Panels and prose. Round again, but NO 3px keylines inside an article ── */
/* 🔴 THE GUIDE'S OWN RULE, and it is the one that decides whether this
   direction survives 750 words: "Inside a long read there are no 3px
   borders: rules are 1px #EDD9BC, the table has no box, and the only brand
   event above the fold is the heading. Keylines belong to tools and cards,
   not to prose." So the hairlines 1b introduced STAY hairlines. What 3c
   changes in an article is the ground, the type and the heading mark —
   deliberately little else. */
.card {
  border-top: 1px solid var(--rule);
  border-radius: 0;
}
.note-box, details { border-top-color: var(--rule); }
blockquote { border-left-color: var(--rule); }
.verdict { border-top: 3px solid var(--ink); }

.note-box.policy {
  background: var(--warn-tint);
  border: 1px solid var(--warn-rule);
  border-radius: var(--panel-radius);
}

/* ── Claim headings (decision 30) ────────────────────────────────────────── */
/* 1b marked these with a plum swatch. 3c has no swatch device — its own
   emphasis is a marigold highlight BEHIND A WORD, which needs markup and is
   therefore Stage 3. ⚠️ So this is a JUDGEMENT, not evidence, and it is
   recorded as one: the mark becomes a short 3px INK rule, which is the
   guide's own vocabulary and is not marigold, because a decorative mark is
   not a thing you tap and "marigold means action and nothing else". */
.page h2::after,
article h2::after {
  background: var(--ink);
  height: 3px;
}

.card > h2:first-child { color: var(--accent); }
.standfirst { color: var(--ink-soft); }

/* ── Tables (guide: 1px hairlines, no box) ───────────────────────────────── */
th { border-bottom: 2px solid var(--rule-strong); }
td, tbody th { border-bottom: 1px solid var(--rule); }

/* ── The form (guide §05). Boxes become rounded, keylined fields ─────────── */
/* 1b stripped these to a 2px underline. 3c puts the field back as a fully
   rounded 3px-ink pill on a white bed — the guide's own drawing. Helper text
   stays UNDER the field, never inside it: "a placeholder that disappears is
   not help." That is already how the base behaves; nothing to change. */
.field input,
.field select {
  border: 3px solid var(--ink);
  border-radius: var(--radius-tap);
  background: var(--mark-bed);
  padding: 11px 18px;
  font-weight: 800;
  font-family: var(--font-display);
  letter-spacing: -0.03em;
}
.prefix, .suffix {
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-family: var(--font-text);
  font-weight: 600;
}
.prefix + input, .suffix-wrap input { border-radius: var(--radius-tap); }
.field label { color: var(--ink); font-weight: 700; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
/* The primary call to action is the one marigold thing on the screen. Ink on
   marigold, 8.14:1. Labels CENTRED — the guide's one exception to the
   system's flush-left habit, because "a pill with a flush-left label reads
   as unfinished". Build 012's full-width rule is preserved: a button
   narrower than the fields above it reads as secondary. */
.to-answer {
  background: var(--action);
  border: 3px solid var(--ink);
  border-radius: var(--radius-tap);
  color: var(--action-ink);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-align: center;
  padding: 8px 22px;
  min-height: 0;
}
.to-answer:hover { background: var(--action-hover); text-decoration: none; }
.to-answer:active { background: var(--action-active); transform: translateY(1px); }

.path-switch button {
  border: 2px solid var(--ink);
  border-radius: var(--radius-tap);
  background: var(--mark-bed);
  color: var(--ink);
  padding: 11px 15px;
  min-height: 44px;
}
.card .path-switch button { background: var(--mark-bed); }
.path-switch button[aria-pressed="true"],
.card .path-switch button[aria-pressed="true"] {
  background: var(--action);
  border-color: var(--ink);
  color: var(--action-ink);
  font-weight: 700;
}

/* ── Focus. 3px teal, 3px offset (guide §05) ─────────────────────────────── */
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ── The answer block (guide §06) ────────────────────────────────────────── */
/* 🔴 THE ONE PLACE THE DIRECTION SPENDS EVERYTHING IT HAS: teal field,
   marigold figure, ink keyline. One per page.
   ⚠️ THIS IS THE RISKIEST RULE IN THE BLOCK AND IT IS WRITTEN BLIND. The
   card is being inverted without a rendered view of what is inside it, so
   every descendant that could carry dark type is set explicitly below, at
   :where() specificity so any real rule still wins. 📌 LOOK AT THIS REGION
   FIRST on the handset — if anything in it is dark-on-teal, it is here.
   🚫 NOT the full-bleed band above 48rem, and NOT the figure-leads-the-
   sentence change. Both need markup, both are product decisions as much as
   visual ones, and decision 78 already refused this design tool's proposals
   for this exact region once. Stage 3, after the scoring. */
.card.answer {
  background: var(--accent);
  border: 3px solid var(--ink);
  border-top: 3px solid var(--ink);
  border-radius: var(--radius-answer);
  padding: 1.4rem 1.25rem;
  color: var(--accent-on);
}
.card.answer::before { content: none; }
.card.answer :where(p, li, div, span, h2, h3, h4, strong, em, .answer-line, .headline, .note, .advice-line, .cash-terms, .headline-basis, .deduction, .deduction .caption) {
  color: var(--accent-on);
}
.card.answer :where(.note, .headline-basis, .deduction .caption, .cash-terms) {
  color: var(--teal-caption);
}
.card.answer > h2:first-child { color: var(--teal-caption); }
/* ⚠️ DELIBERATELY NOT SCOPED TO .headline, and that is a fix rather than a
   preference. The first version required a .headline ancestor; a rendering
   check with the figure inside .answer-line instead left it CREAM. 📌 The
   base rule it overrides is `.headline .figure.total { color: var(--accent) }`
   — teal — which on a teal field would have been INVISIBLE rather than
   merely wrong. A rule that depends on markup this block is not allowed to
   change is a rule waiting to be silently defeated. */
.card.answer .figure,
.card.answer .figure.total,
.card.answer .amount {
  color: var(--action);
}
/* ⚠️ The policy box keeps its own palette even inside the answer field —
   otherwise cream type would land on the warn tint at 1.1:1. */
.card.answer .note-box.policy,
.card.answer .note-box.policy :where(p, li, div, span, h2, h3, strong) {
  color: var(--ink);
}
.card.answer .note-box { border-top-color: rgba(255,243,224,0.35); }
.card.answer details { border-top-color: rgba(255,243,224,0.35); }
.card.answer a { color: var(--teal-caption); }

/* ── The next-step block ─────────────────────────────────────────────────── */
/* 📌 The hub link KEEPS its fill and becomes the second marigold thing on a
   content page — which is correct under the guide's rule, because it is the
   one thing on that page you are meant to tap. Ink on marigold, 8.14:1.
   ⚠️ Was white on plum at 14.84:1; white on marigold would have been 1.8:1,
   which is the failure the --accent mapping above exists to prevent. */
.next-step { border-top: 1px solid var(--rule); }
.next-step-hub a {
  background: var(--action);
  border: 3px solid var(--ink);
  border-radius: var(--radius-tap);
  color: var(--action-ink);
  font-weight: 800;
  padding: 0.35rem 1rem;
  min-height: 0;
}
.next-step-hub a:hover { background: var(--action-hover); color: var(--action-ink); }
.next-step li a {
  border-bottom: 2px solid var(--rule);
  color: var(--accent);
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
/* ⚠️ The pill bed carries the NARROWEST TEXT PAIRING in the direction — a
   visited link here computes 4.54:1. Above the bar, with no margin. */
footer.site {
  background: var(--accent-tint);
  border-top: 3px solid var(--ink);
}

/* 🔴 CE2, Build 038. Measured, not assumed: on a fresh render every one of
   the five footer links already computes the same colour — there was never
   a second rule for Money Worries or Home. What David saw is the global
   `a:visited` rule (above) bleeding into persistent chrome: whichever of
   these five HE happened to have clicked (in HIS browser) recolours,
   because footer nav was never scoped out of it. ONE rule, collapsing all
   five (and the footer's mailto link) onto the same colour regardless of
   visited state — a reader's own browsing history should not make the same
   footer look different from one page to the next. */
footer.site a,
footer.site a:visited {
  color: var(--accent);
}

/* ── Radii swept back on, last, so nothing above has to remember ─────────── */
/* The mirror image of 1b's closing sweep, which squared these five. */
.skip-link, .borrower-card, .two-cards > * { border-radius: var(--panel-radius); }
.bar-track, .bar-fill { border-radius: var(--radius-tap); }
.visual { border-radius: var(--panel-radius); }

/* ⚠️ The proportion bar's segment dividers. The guide asks for a 3px ink
   divider between segments "so the pale ones stay countable". Done with an
   inset shadow rather than a border so no box model changes and no markup
   moves. */
.bar-fill.secondary { box-shadow: inset 3px 0 0 var(--ink); }

/* ── The split: chips and the proportion bar (Visual Style Guide §06) ───── */
/* 🔴 STAGE 3, Thread 087. The first component in this block that needed
   MARKUP as well as paint — sites/thirtyish/assets/take-home-pay/render.js.
   ⚠️ It is INSERTED under the two answer sentences. Nothing was reordered:
   David's ruling this thread, and the reason the guide's own figure-leads-
   the-sentence change is still NOT built.
   📌 Every figure in it is a row the table below already prints. No new
   number, no arithmetic here — see render.js's own header for why the bar
   uses flex weights rather than the export's percentages. */

/* 🔴 A GRID, NOT A WRAPPING FLEX ROW, AND THAT IS A FIX FOUND BY RENDERING.
   The design export uses `flex:1;min-width:88px` because it was drawn with
   THREE chips, which fill one row exactly. This product has FOUR — income
   tax, NI, student loan, pension — so the fourth wrapped alone and grew to
   the full width of the card: one giant lozenge under three small ones.
   📌 THE SAME FAILURE AS THE HOME PAGE'S PRODUCT LIST IN THREAD 086, in a
   different component, from the same cause — a spec drawn against a fixed
   number of items meeting a variable one. Two columns makes four chips a
   tidy 2×2 and three chips a 2+1, and nothing is ever alone and stretched
   across the card. */
.card.answer .chips {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 8px;
}
.card.answer .chips .chip {
  box-sizing: border-box;
  border-radius: var(--panel-radius);
  border: 3px solid var(--ink);
  padding: 12px;
}
/* ⚠️ THE INK OVERRIDE HAS TO BE EXPLICIT AND IT HAS TO WIN. The block above
   paints every descendant of .card.answer cream, for the teal field. These
   four chips are the exception: they are pale fills sitting ON that field,
   and cream-on-white would be invisible — the same failure mode as the
   answer figure caught in Thread 086, arriving in a new component. Ink on
   all four is verified: clay 5.26:1, marigold 8.14:1, white 14.83:1, pill
   bed 13.71:1 (all recomputed in 18-01 §4, none of them new pairings). */
.card.answer .chips .chip,
.card.answer :where(.chip-label, .chip-value) { color: var(--ink); }
.card.answer .chip-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.25;
}
.card.answer .chip-value {
  display: block;
  margin-top: 6px;
  font-family: var(--font-display, inherit);
  font-weight: 800;
  font-size: 1.375rem;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
.chip-clay  { background: var(--clay); }
.chip-action { background: var(--action); }
.chip-bed   { background: var(--accent-tint); }
/* 📌 THE WHITE CHIP DROPS ITS KEYLINE, and that is the guide's own ink
   budget rather than a style choice: "count the 3px keylines in one
   viewport. More than four and the screen goes heavy. The pale chip drops
   its keyline first." With the answer card's own 3px border that keeps a
   four-deduction reader at exactly four. */
.chip-white { background: var(--mark-bed); }
/* The take-home chip. Same colour as the bar's own keep segment, so the
   chips and the bar are one reading rather than two. No sixth colour. */
.chip-keep  { background: var(--accent-on); }
/* 🔴 THE KEYLINE DROP NEEDS THIS SPECIFICITY AND UNTIL TODAY IT DID NOT HAVE
   IT. `.chip-white { border-color: transparent }` on the line above was
   written in Thread 087 and never once took effect: `.card.answer .chips
   .chip` earlier in this block is three classes to its one, so the ink border
   won every time. ⚠️ THE COMMENT ABOVE IT CLAIMED THE INK BUDGET WAS HELD AT
   FOUR KEYLINES AND IT WAS ACTUALLY FIVE — a rule written, believed, and
   silently defeated. 📌 Found on 10 September by RENDERING the new take-home
   chip and seeing a keyline that was supposed to be absent, then measuring
   the white chip and finding the same. The stylesheet had been read several
   times since. Rendering is necessary; reading is not sufficient. */
.card.answer .chips .chip-white,
.card.answer .chips .chip-keep { border-color: transparent; }
/* ⚠️ KEYLINE DROPPED, and that is the ink budget rather than taste. The rule
   above keeps a four-deduction reader at exactly four 3px keylines; a fifth
   chip WITH a keyline would make five. The guide's own answer is that the
   pale chip drops its keyline first, and cream is the palest fill there is.
   Ink on cream is 14.83:1 — recomputed here, not carried. */

.card.answer .proportion-bar {
  display: flex;
  height: 28px;
  margin: 14px 0 0;
  border: 3px solid var(--ink);
  border-radius: var(--radius-tap);
  overflow: hidden;
}
/* The 3px ink divider is an INSET SHADOW, not a border: a border would join
   the box model and the segments would stop summing to the track. Same
   technique, and the same reason, as .bar-fill.secondary above. */
.card.answer .proportion-bar .seg { box-shadow: inset 3px 0 0 var(--ink); }
.card.answer .proportion-bar .seg:first-child { box-shadow: none; }
/* 🔴 CREAM, NOT TEAL, AND THIS IS THE SECOND FAULT RENDERING CAUGHT.
   The export paints the "what you keep" segment teal (#0E4F4A) because in
   the mockup the bar sits on the CREAM ground, where teal reads. Here the
   bar is INSIDE the teal answer card, so a teal segment is the card's own
   background: the bar came out looking like an EMPTY track with a few marks
   at the right-hand end, rather than a mostly-full one. ⚠️ Not wrong —
   unreadable, which is worse, because the segment that vanished is the one
   carrying the good news.
   📌 EXACTLY THE THREAD 086 FAULT AGAIN: a colour lifted from a spec into a
   context whose background that colour now IS. Third instance. The rule
   this project keeps re-learning is to check a colour against the surface it
   will actually land on, not the surface it was drawn on.
   Cream keeps its distance from all four deduction tones, and the pale ones
   stay countable against each other by the 3px ink dividers, which is what
   the guide says those dividers are for. */
.seg-keep   { background: var(--accent-on); }
.seg-clay   { background: var(--clay); }
.seg-action { background: var(--action); }
.seg-white  { background: var(--mark-bed); }
.seg-bed    { background: var(--accent-tint); }

/* ── Stage 4: the components the guide never drew ───────────────────────── */
/* 🔴 THREAD 087. The Visual Style Guide was written against three screens and
   the site has twenty, so roughly a dozen live components had no rule in it
   (18-01 §3). ⚠️ EVERY DECISION BELOW WAS TAKEN FROM A MEASUREMENT, not from
   taste, and each one is written back into the guide — otherwise the guide
   describes a third of the site and the next session invents the rest again.

   📌 THE INK BUDGET WAS MEASURED FIRST AND IT PASSES. The guide: "count the
   3px keylines in one viewport. More than four and the screen goes heavy."
   Rendered at 390×844, a §10 page and the calculator both show ZERO 3px
   keylines above the fold — the rule that keeps them out of prose is holding,
   so nothing below needed to spend budget to buy room. */

/* 🔴 TAP TARGETS — THE ONE REAL FAILURE AGAINST THE GUIDE, AND IT IS THREE
   COMPONENTS. §05 says "44px minimum, keyline included". Measured: every
   <summary> is 32px, and the pension swap control is 24px. Both are things a
   thumb has to hit — the collapsed working is on EVERY §10 page (decision 30)
   and the swap control changes what the calculator asks for.
   ⚠️ Not a new rule, and not the guide being extended: it is the guide's own
   number applied to components it never listed. Same reason the topic nav
   kept its 44px earlier today when tightening it would have been easier. */
summary {
  min-height: 44px;
  display: flex;
  align-items: center;
}
/* ⚠️ TWO SELECTORS BECAUSE A SECOND ONE TURNED UP ON THE OTHER CALCULATOR.
   The first pass caught the pension swap and missed "I already know my plan"
   at 27px on the student-loans tool — same shape, different page, and it was
   found by re-measuring after the fix rather than by assuming the fix was
   complete. 📌 `p > .linkish:only-child` is the general case: a link-styled
   BUTTON alone in its own paragraph is a control, not a word in a sentence.
   An inline .linkish inside running prose is deliberately NOT matched — a
   44px line box inside a paragraph would tear the text apart, and the guide's
   44px is about things a thumb aims at. */
.pension-type-swap .linkish,
p > .linkish:only-child {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ⚠️ HELPER TEXT IS MUTED, NOT BODY INK. §02: "Caption and helper text — 400,
   14px, muted." Measured at #3E382F, which is the BODY ink — correct under
   1b, one step too dark here, and it makes every hint compete with the
   sentence above it. 📌 The rest of the caption family (.visual-caption,
   .card-punch-label, .bar-axis) was already muted and is left alone. */
.hint { color: var(--ink-faint); }

/* 🔴 CE9, Build 038: the marigold-thumb rule that stood here (decision 173
   stage 4) is removed with the sliders themselves — a styling decision about
   a control that no longer exists. No logged decision introduces the
   slider, so removing it contradicts nothing; this one line is the only
   trace it left in this direction's own block. */

/* ⚠️ THE SCROLLING TABLE KEEPS ITS BEHAVIOUR AND GAINS ONE GUARD, NO MORE.
   The working table is 344px inside a 296px column at 390px, and it SCROLLS —
   it is not clipped, which was checked after a screenshot made it look
   clipped. 🔴 What it lacks is any signal that it scrolls, and the guide has
   no rule for one. A fade over the right edge would invent a rule AND sit
   over a digit, so it is NOT taken here: recorded as a guide item instead.
   `overscroll-behavior-x: contain` stops a horizontal swipe on the table
   turning into the browser's back gesture, which is a real fault on iOS and
   costs the reader their answer. */
.table-scroll { overscroll-behavior-x: contain; }

/* ── The masthead mark (Visual Style Guide §07) ─────────────────────────── */
/* 🔴 THREAD 087, DAVID'S INSTRUCTION. Company mark on site-level pages; the
   product's own mark on every page inside a product.
   📌 THE GUIDE'S HIERARCHY IS ONE SENTENCE AND IT IS THE WHOLE RULE HERE:
   "The company mark sits outside any container; every product sits inside
   one." So the company waves are bare and the product glyph is in a white
   squircle — silhouette differentiates, which is why a new product never
   needs a new colour and never needs an illustrator.
   ⚠️ The wordmark stays STYLED TEXT either way. The mark sits beside it; it
   does not replace it, and there is no centred lockup. */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.mark { flex: none; display: block; }
/* 🔴 CE5, Build 038 — the logo, the one part of CE5 free to grow (nothing
   else on the page depends on its size): the wordmark's text and the
   company mark grow together, proportionally (34×27 → 39×31, keeping the
   drawing's own aspect ratio; 26px → 30px text). Cowork's determination,
   not David's ruling — he reviews the before/after render on Preview. */
.wordmark { font-size: 1.875rem; }
.mark-company { width: 39px; height: 31px; }
/* ⚠️ 24px / radius 8 / 2px is the guide's MIDDLE tier, taken whole rather
   than bent. The 44px tier would out-measure the wordmark's cap height and
   put a 3px keyline in furniture that repeats on all twenty pages — a
   quarter of §03's four-keyline budget spent before the page says anything.
   The guide steps radius and keyline down together and this is that step. */
.mark-product {
  width: 24px;
  height: 24px;
  border-radius: 8px;
  border: 2px solid var(--ink);
  background: var(--mark-bed);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.mark-product svg { display: block; fill: var(--ink); }

/* ══════════════════════════════════════════════════════════════════════════
   BUILD 039 — THE LOOK-AND-FEEL BUILD (decisions 246, 247, 248, 249).
   27-Look-And-Feel-Change-List.html is the authority; the item numbers
   below are its numbers. Every measurement was taken with the web font
   asserted loaded (`document.fonts.check('700 16px "Instrument Sans"')`,
   true) and on a rendered page — decision 245's keeper, applied again: a
   selector is a claim about what it reaches, and only rendering tests it.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── JOB TWO: the masthead's alignment, height and colour ──────────────────
   Items 1, 2, 4, 5, 6, 11. */

/* Item 1: the wordmark's centre sat at 44px from the top of the masthead,
   the All Topics pill's centre at 54.7px — 10.7px low. Cause was one
   declaration: `align-items: baseline`, lining up the TEXT BASELINES of a
   30px wordmark and a 13px pill label. `center` lines up the boxes. */
.masthead-inner { align-items: center; }

/* Items 2 and 15 share one fix, written once. `.all-topics` is a
   <details>, and the generic "collapsed working" rule (decision 30, far
   above) gives every <details> a 1px keyline, 0.6rem (9.6px) padding and a
   1.1rem (17.6px) bottom margin meant for a panel of prose — nobody had
   reset it for the masthead's OWN <details>, so the masthead was carrying
   a hidden second box around its pill. Zeroing it here, with the header's
   own padding taken to 10px 0, MEASURED at exactly 71px on the site home
   page (the wordmark's own 48px line box, 20px of header padding, the 3px
   rule below it) and exactly 67px everywhere else (job four's own 44px
   control binds there instead) — see the build note for every width this
   was checked at. This also retires `.all-topics`'s own `margin-left:
   auto` from the base rule far above: `.masthead-actions`, below, carries
   that job now that the pill travels inside it. */
.all-topics {
  border: 0;
  padding: 0;
  margin: 0;
  background: none;
  border-radius: 0;
}
.masthead { padding: 10px 0; }
/* 🔴 A REAL BUG FOUND BY OPENING THE SHEET, NOT BY READING THE RULE ABOVE.
   `details[open] > summary { margin-bottom: 0.7rem }` (decision 30, far
   above) is written for a normal in-flow disclosure, where the gap
   separates the summary from its revealed content. `.all-topics-sheet` is
   `position: absolute` and was never in that flow — but the margin still
   landed on the SUMMARY itself, so opening the control grew `.all-topics`
   by 11.2px and, with it, the whole masthead: MEASURED 67px → 78.2px on
   open, a visible jump neither item 2 nor item 15 asked for and neither
   would have caught by reading the stylesheet. Zeroed here, scoped to
   this control only — the rule still does its job everywhere else a
   <details> reveals content in the normal flow. */
.all-topics[open] > summary { margin-bottom: 0; }

/* Items 4, 5 and 11: the wordmark's colour was an ACCIDENT — see --rust's
   own comment in the palette block above for the full finding. Pinned in
   both link states rather than left to a reader's own browsing history,
   and given to the live product glyphs too (item 5) so the two colours
   can never drift apart again. */
.wordmark,
.wordmark:visited {
  color: var(--rust);
}
/* De-linked on every page but the site home page (item 13) — an <a> only
   there, so this now only ever meets a real link. */
a.wordmark:hover { text-decoration: underline; }

/* Item 5: the masthead's own product glyph, and — because the All Topics
   sheet sits inside header.masthead (item 12's own finding) — every LIVE
   row's glyph in that sheet too, on every page: `.all-topics-sheet
   li.coming .mark-product svg` (far above, unchanged) already overrides
   Coming Soon rows there back to ink-faint with higher specificity, so
   this rule reaching the sheet is exactly item 12's adopted behaviour,
   just in rust instead of clay. Item 6 dims the HOME PAGE's own Coming
   Soon glyphs the same ink-faint the sheet already uses — new here,
   because the home list's shared bare-glyph rule (CE4/CE6, Build 038)
   used to paint every one of its glyphs clay regardless of live/reserved. */
.masthead .mark-product svg,
.topic-nav.home-topics li:not(.coming) .mark-product svg {
  fill: var(--rust);
}
.topic-nav.home-topics li.coming .mark-product svg {
  fill: var(--ink-faint);
}

/* Item 11 (Review 032, Finding 1): CE2's exact shape, reused, for the two
   remaining places the unscoped `a:visited` rule (above) reaches — the
   All Topics sheet's own links, and the skip link. The topic rail and the
   home topic pills are immune already, their own colour rules always
   having won the specificity race; confirmed by rendering a visited state
   rather than by reading the cascade. */
.all-topics-sheet a,
.all-topics-sheet a:visited {
  color: inherit;
}
.skip-link,
.skip-link:visited {
  color: var(--accent-on);
}

/* ── JOB FOUR: the masthead rebuilt, every page but the site home page ─────
   Items 7, 13–20. `.masthead.is-home` is the one marker build-pages.js
   sets (masthead()'s own `isHome` argument) — every rule below is scoped
   off it rather than a second copy of the masthead's markup for a second
   template. Item 20: the site-level masthead (about, privacy, terms, 404,
   money worries) takes every one of these rules too — there are only
   THREE mastheads on this site, not eight, and the site-level one is not
   the site home page. */

/* Item 14: 15px, not 16px. The binding case is "Take-home pay" at 360px,
   which only holds one row at 16px by eating 6.7px of the right-hand
   gutter; "Student loans" — ten characters shorter — fits at 16px, which
   is exactly the inconsistency David asked to avoid. One size, every
   topic, including the site-level "thirtyish". */
.masthead:not(.is-home) .wordmark { font-size: 15px; }

/* Item 20: the site-level masthead's company waves scale with the type,
   the same proportional move CE5 made the other way (34×27 → 39×31) —
   39×31 down to 20×16, aspect ratio preserved. The product glyph's own
   24px bed is untouched: only the bare company mark grew under CE5, so
   only it shrinks back here. */
.masthead:not(.is-home) .mark-company { width: 20px; height: 16px; }

/* Items 15, 16 and 18, together, because they are one flex layout, not
   three. §0c's trap one: flex items shrink before they wrap, and the
   first mock of this silently narrowed the All Topics pill until its own
   label broke onto two lines, which is what made a too-narrow row look
   like it "fit" — `flex: none` on every child and `white-space: nowrap`
   on the pill's own label close that off outright. Below the breakpoint
   (item 18, and at 320px it is not close — the row needs 300.1px of
   content against 272px on offer with the site's 24px gutters, checked at
   name sizes down to 14px and a shortened pill label, every combination
   still eating the right-hand gutter) it falls back to two: the name on
   its own line, the pill-and-Home pair on the next, right-aligned. Plain
   `flex-wrap` handles the first row correctly on its own; what it does
   NOT do safely is keep the pill and the Home control together on the
   second (§0c's trap two — the automatic left margin on `.all-topics`
   used to keep the pill on row one and drop the Home control alone onto
   row two, hard left, seen in
   09-Design-Exports/Thread117-masthead-all-topic-names.png's "Dealing
   with debt" panel) — which is why they are wrapped in
   `.masthead-actions` rather than left as two independent flex children.
   `justify-content: flex-start` left-aligns the name; the wrapper's own
   `margin-left: auto` pushes the pair right as one unit, maximising the
   gap between them — David's own instruction.
   🔴 THE BREAKPOINT IS 360px, ITEM 15/16's OWN NUMBER, RESTORED BY
   BUILD 040 (decisions 250 and 253). Build 039 had moved it to 375px on
   its own authority, and this comment used to defend 375px; both are
   gone. THE REASON, ROUND THE OTHER WAY: item 15/16's "360px" was
   measured BEFORE item 17 added the 44px Home control and its 8px gap
   to this row — 52px of content the number never accounted for. Built,
   at 360px "Take-home pay" (the longer live name) overflowed the
   right-hand gutter by 13.8px, which item 19 says must never happen.
   Decision 250 pays for that 13.8px WITHOUT moving the breakpoint: below
   375px the All Topics pill's label is "Topics" rather than "All Topics"
   (`.all-topics-prefix` below), which saves 20.5px, measured. 374px was
   the exact point the long label clears, hence the 375px pairing.
   ⚠️ WHAT THIS BREAKPOINT DOES AND DOES NOT DO — Review 033 F2 found the
   earlier comment claimed more. It does not MAKE any masthead two rows;
   it only stops FORBIDDING the wrap. Whether a page wraps below 360px
   depends on its own name length and the pair's width, so the three
   masthead types are NOT one consistent shape at 320px — and that is
   RULED, decision 253: the five site-level pages (shorter "thirtyish"
   lockup) fit one row at 320px, both products stay at two. 🚫 Do not add
   a rule to force the site-level pages back to two rows — the
   alternative is a rule whose only job is to forbid a layout that fits. */
.masthead:not(.is-home) .masthead-inner {
  justify-content: flex-start;
}
.masthead-inner > * { flex: none; }
.all-topics summary { white-space: nowrap; }
@media (min-width: 360px) {
  .masthead:not(.is-home) .masthead-inner { flex-wrap: nowrap; }
}
/* Decision 250: "All " is dropped below 375px. display: none, not
   visibility, so the control's accessible name is "Topics" and not both. */
.all-topics-prefix { display: none; }
@media (min-width: 375px) {
  .all-topics-prefix { display: inline; }
}
.masthead-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex: none;
}

/* Item 17: a Home control, right of the All Topics pill. The pill's own
   vocabulary — 44×44px (decision 176's tap-target floor, not shaved),
   2px ink keyline, white bed, the panel radius — so the two read as a
   pair of controls, not a topic mark. Ink, not clay: a control a reader
   taps to leave the page, not a topic. */
.home-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 2px solid var(--ink);
  border-radius: var(--panel-radius);
  background: var(--mark-bed);
  color: var(--ink);
}

/* ── JOB FIVE: the two calculator defects ───────────────────────────────
   Items 21 and 22. Both are illegibility, not preference, and the
   materiality gate does not apply to either — a reader meets a blank
   where a chart and a control should be. */

/* Item 22: both disclosure controls in the answer card are `--accent` on
   an `--accent` card — 1.00:1, completely invisible, and the seven-row
   data table behind the first is unreachable unless a reader happens to
   tap blank space. The cause is an omission from the card's own blanket
   `:where(...)` colour list, far above, which does not include `summary`
   — so a generic `summary { color: var(--accent) }` (decision 30, far
   above) wins unopposed. Fixed with the SAME colour the card already
   gives its own captions and links: 5.76:1. */
.card.answer summary { color: var(--teal-caption); }

/* Item 21: the balance chart's curve is stroked `--accent` on the card's
   own `--accent` background — not faint, mathematically invisible, and
   the gridlines are the only visible part because they are the chart's
   one cream-valued token. RULED: give the plot its OWN cream ground and
   change no chart colour at all — the chart's palette is already a
   cream-ground palette, so a change of ground fixes every part of it at
   once. Option A (the plot only), not option B (the whole
   `.chart-wrap`): the <h3>, the caption and the "See these as numbers"
   table stay on the teal in the card's own voice; panelling the whole
   block would have needed every one of those re-pointed to ink as well. */
.card.answer .chart {
  background: var(--paper);
  border-radius: 10px;
  padding: 8px;
}
/* The one thing the cream ground does NOT fix: `.chart-grid` (far above)
   was drawn to be faint ON CREAM already (`--rule`, 1.26:1 there) and only
   looks right today because the only chart that exists sits on teal.
   Darkened to ink at 16% for the new cream panel, scoped to this card so
   the shared `.chart-grid` rule is free to mean "faint on cream" anywhere
   else a chart is ever placed directly on the page — see the build note
   for the measured result. */
.card.answer .chart .chart-grid {
  stroke: rgba(34, 32, 28, 0.16);
}

/* ══════════════════════════════════════════════════════════════════════════
   END OF THE VISUAL STYLE GUIDE'S BLOCK.
   🔴 ADOPTED. Not staged, not a trial — it is what the site looks like, has
   been deployed to preview, and is the subject of 19-Visual-Style-Guide.html.
   ⚠️ REVERTING IS NO LONGER ONE STEP AND HAS NOT BEEN SINCE 9 SEPTEMBER.
   Deleting this block alone leaves a visibly broken page. The route is:
     1. delete site.css from the opening banner to here
     2. delete renderSplitHtml and its ONE call site in
        sites/thirtyish/assets/take-home-pay/render.js
     3. rm -rf sites/thirtyish/assets/fonts
   ⚠️ AND MARKUP OUTSIDE THIS BLOCK NOW DEPENDS ON RULES INSIDE IT.
   build-pages.js emits .mark-product unconditionally (decision 174) and the
   home page's product rows use it too (decision 176), while .mark-product is
   styled only in here — so a revert strips the styling off marks that stay on
   the page. KNOWN, RECORDED, NOT FIXED: it is on the open register.
   📌 The claim that "nothing else in the repo has been touched" was true on
   the morning of 9 September and has been false since that afternoon.
   ══════════════════════════════════════════════════════════════════════════ */
