/* v2.css — BFC Article Anatomy v2, page rules only.
 *
 * WHY THIS FILE EXISTS (D17). These rules used to be appended to `global.css`. That file is served
 * with `Cache-Control: max-age=31536000` — one year — and every page references it as
 * `global.css?v=7c6d4230`, a token inherited verbatim from the captured template that does NOT
 * change when the file changes. A returning browser therefore holds the old stylesheet for up to a
 * year and has no reason to re-fetch it: the new pages would render with these rules missing.
 *
 * The token cannot simply be bumped — it lives in the cloned template, so changing it alters V1
 * page bytes and breaks the STR byte-identity gate.
 *
 * So V2 rules live here instead, and the build emits this file under a CONTENT-HASHED name
 * (`/styles/v2.<hash>.css`) linked only from V2 pages. Three consequences, all deliberate:
 *   - V1 pages are untouched, so their bytes and their long cache stay exactly as they are;
 *   - the URL changes whenever the content changes, so cache invalidation is structural rather
 *     than dependent on someone remembering to bump a query string;
 *   - a brand-new filename has no cached copy anywhere, so the one-year header works FOR us.
 *
 * Add v2-only rules here, never to global.css. `npm test` asserts that every V2 page references
 * the hash of this file's current contents.
 */

/* ══ V2 DESIGN-SYSTEM REFINEMENT — ratified Aug 2026 ═════════════════════════════
 *
 * A controlled refinement of the V2 baseline, applied BEFORE Batch 3 so Financing is built on the
 * final visual system rather than retrofitted onto it afterwards.
 *
 * WHY EVERY LINE OF IT IS HERE AND NOT IN global.css. The legacy sheet is shared with the deployed
 * STR pages and served under a one-year cache with a token that never changes (D17). Restyling it
 * would restyle live STR pages we are forbidden to touch, and could not be cache-busted anyway.
 * v2.css loads AFTER global.css and only on V2 pages, so an equal-specificity rule here wins for
 * exactly the pages this refinement governs and no others. That is why the overrides below look
 * like duplicates of global rules: they are deliberate, scoped re-declarations.
 *
 * THE FONTS SHIP WITH THE STYLESHEET THAT USES THEM. Lora and JetBrains Mono are imported here
 * rather than added to the captured template, because the template is cloned by V1/STR pages whose
 * bytes are frozen and byte-checked. Coupling the declaration to v2.css means the two can never
 * arrive separately: wherever these rules apply, their faces are already requested.
 */
@import url("https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;1,400&family=JetBrains+Mono:wght@400;500;600&display=swap");

:root{
  /* Lora replaces Newsreader as the DISPLAY face. `--display` drives h1 plus the editorial
     furniture (.dek, .lede, pull quotes); h2/h3 are pulled back to Inter below, because the ruling
     puts Lora on H1 and display moments only and global.css groups `h1,h2,h3` under one token. */
  --display:"Lora",Georgia,serif;

  /* MONO IS RETIRED AS A DECORATIVE FACE. `--mono` has 83 users in global.css — eyebrows,
     breadcrumbs, type badges, chips, captions, fine print — and the ruling is explicit that mono is
     for true numerical and technical contexts only. Rather than re-declare thirty selectors, the
     token itself stops being a monospace: every decorative user becomes Inter in one line, which is
     precisely the intent. The name is kept so nothing downstream has to change.
     Genuine numeric contexts use `--numeric` instead, and must ask for it explicitly. */
  --mono:var(--sans);
  --numeric:"JetBrains Mono",ui-monospace,monospace;

  /* Warm ivory page ground, replacing the cool `--paper` (#f5f7fa). `--paper` itself is NOT
     redefined: it is the fill of panels, inputs, table headers and the figure plate, and warming
     all of them at once would be a redesign rather than a change of ground. */
  --ivory:#faf7f1;
  /* One step deeper, still warm. The full-width newsletter band (`.s6`) uses `--paper` to separate
     itself from the article above and the footer below. Warming the page ground without warming
     that band left a cool stripe across an otherwise warm page — a seam introduced by this change,
     not one that was there before. Flattening it to `--ivory` would remove the separation the band
     exists for, so it moves into the warm family rather than out of the design. */
  --ivory-sink:#f3efe4;
}

body{background:var(--ivory)}

/* The newsletter band's colour is an INLINE style in the captured template
   (`style="background:var(--paper)"`), which outranks any stylesheet rule. Rather than answer that
   with `!important`, this redefines `--paper` ON the element: the inline declaration then resolves
   against the warm value. It works THROUGH the inline style instead of fighting it, needs no
   specificity escalation, and leaves the template untouched. Scoped to `.s6`, so `--paper` keeps its
   cool value everywhere else it is used — panels, inputs, table headers, the figure plate. */
.s6{--paper:var(--ivory-sink)}

/* H2/H3/H4 return to Inter. global.css groups h1-h3 under `--display` and h4 separately; the ruling
   separates them from h1. h4 is included because on these pages it is not an editorial heading at
   all — it is the label on a callout panel ("Key Takeaways", "The Common Mistake"), and the ruling
   puts callout UI in Inter. Equal specificity, later source, so this wins without !important. */
h2,h3,h4{font-family:var(--sans)}

/* The guide-type label stops repeating the hero's gold. The BASE `.typebadge` treatment is already
   the muted navy the ruling asks for (#3d5c7a on #e6eef5); it was only the `.ahero` override that
   forced gold, so this restores the base rather than inventing a third treatment. `!important` is
   required only because the rule it answers uses it. */
.ahero .typebadge{
  color:#3d5c7a!important;background:#e6eef5!important;
  border:1px solid rgba(255,255,255,.16)!important;
}


/* .checklist — BFC Article Anatomy v2 "Your Action Plan" (added Aug 2026).
   Its step counter is the one genuinely NUMERIC context on an article page today, so it takes
   `--numeric` (JetBrains Mono) rather than the retired decorative `--mono`. Changed here at the
   declaration rather than overridden below it: an override placed earlier in the file loses to this
   rule and silently does nothing, which is how the first attempt failed.
   Additive: no existing page uses `.checklist` as a block (the legacy `.rtype.checklist` chip is
   a different selector), so V1/STR output is unaffected. Styled as a numbered sibling of
   .takeaways using the locked tokens. */
.checklist{border:1px solid var(--hairline);border-left:2px solid var(--navy);border-radius:3px;background:#fbfcfe;padding:22px 24px;margin:30px 0}
.checklist h2{font-size:1.05rem;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0 0 12px}
.checklist ol{list-style:none;margin:0;padding:0;counter-reset:cl}
.checklist li{counter-increment:cl;position:relative;padding:6px 0 6px 32px;font-size:.98rem;color:#2f3a54}
.checklist li::before{content:counter(cl,decimal-leading-zero);position:absolute;left:0;top:6px;font-family:var(--numeric);font-size:.66rem;color:var(--gold-deep,#8a6a16);font-weight:600}

/* Signature-diagram assets are text-dense: below their natural width they scroll inside the
   figure rather than shrinking to illegibility. The PAGE never scrolls horizontally — the
   figure's own container does. */
.figure{overflow-x:auto}
.figure svg{display:block;width:100%;height:auto;min-width:520px}

/* --- mobile scroll affordance -------------------------------------------------
 * A figure narrower than its content scrolls (above). On a phone that means the reader's first
 * paint of a calculation diagram can be labels with every VALUE off-screen — "Net operating
 * income" with no $15,516 — which reads as missing information rather than as more to see.
 *
 * Ruled: keep the 520px minimum and the scrolling (shrinking these to fit ~350px would trade an
 * incomplete first paint for illegible numbers, which is worse), and add the missing SIGNAL. Two
 * cues, both at the component level — nothing is baked into an SVG, so no approved figure changes.
 */

/* 1 · The right-edge fade is NOT here, deliberately. The obvious implementation — scroll-shadow
 * gradients on the container, two `local` and two `scroll`, which self-hide at each end — was
 * written, rendered, and found to do nothing: these SVGs paint their own opaque background across
 * the whole canvas, so the container's background sits behind the figure where no one can see it.
 * Doing it properly needs the scroll box moved into a child element so an overlay can sit above the
 * content, which is a structural change to every figure and is being ruled on separately. Shipping
 * the gradients meanwhile would have added twelve lines of CSS that render nothing while reading,
 * to anyone maintaining this, as though the fade were handled.
 */

/* 2 · The words, because a shadow alone does not tell a first-time reader what to DO. Shown only
 * when the figure is actually narrower than its content.
 *
 * 564px = the SVG minimum (520px, above) + the figure's horizontal padding (22px a side, in
 * global.css). A container query asks the COLUMN's width rather than the viewport's, so gutters,
 * zoom and a future sidebar cannot put it out of step.
 *
 * It is a LITERAL, and CSS gives no way to make it otherwise: a container query condition cannot
 * read a custom property. So the relationship between these three numbers is asserted in
 * `test/architecture.test.mjs` instead. An earlier version of this comment claimed the breakpoint
 * "follows" if you change the minimum or the padding. It does not — change either and this number
 * must be changed by hand, which is exactly why the test exists. Between the old and new
 * thresholds the cue would otherwise hide while the figure still scrolls, or appear when there is
 * nothing to scroll to. */
.article{container-type:inline-size}
/* `.article .figure-swipe`, not `.figure-swipe`. This is a <p> inside .article, and global.css
 * carries `.article p{margin-bottom:20px;font-size:1.04rem}` — one specificity point higher than a
 * lone class, so the bare selector lost and the cue rendered at 16.6px beside figure text that
 * renders at about 7px. Measured, not guessed: the SVG is drawn on a 700-unit canvas and displayed
 * at 520px, so everything inside it is scaled to 0.74 while HTML text is not. */
.article .figure-swipe{
  display:none;margin:0 0 6px;font-family:var(--mono);font-size:.62rem;
  letter-spacing:.04em;color:var(--gold-deep,#8a6a16);text-align:right;opacity:.85;
  padding-right:23px;   /* line the arrow up with the figure's CONTENT edge: 22px pad + 1px border */
}
@container (max-width:564px){ .article .figure-swipe{display:block} }

/* Authored figure footnote — answers a starred claim inside the diagram. Sentence case and
   left-aligned, deliberately unlike .figcap's uppercase mono label: this is a qualification the
   reader is meant to READ, not a caption. Three Tax nodes carry one. */
/* Below the scroll canvas, in reading order: swipe cue (mobile only) → caption → footnote(s).
   Each is a SIBLING of .figure so only the canvas moves horizontally. The figure's own bottom
   margin is tightened here so the group still reads as one unit. */
.article .figure{margin-bottom:12px}
/* The followers align with the figure's CONTENT edge, not the column edge — 22px of figure padding
   plus its 1px border, the same constant the swipe cue already uses. Inside the box the caption
   inherited that inset for free; outside it has to be stated, or the caption's text sits a
   character-width left of the artwork it describes. */
.article .figcap{margin:0 0 6px;padding:0 23px}
.article .fignote{font-family:var(--mono);font-size:.62rem;line-height:1.5;color:var(--ink-soft);
  text-align:left;margin:0 0 6px;padding:0 23px;letter-spacing:.01em}
.article .figure + .figure-swipe ~ .figcap:last-of-type{margin-bottom:0}
