/* brand/components.css -- GENERATED by brand/build-tokens.mjs from brand/components/*.css (00-base.css, 10-button.css, 20-forms.css, 30-nav.css, 40-card.css, 50-feedback.css, 60-data.css, 70-motion.css, 80-homeregister.css, 81-alivesignature.css, 90-homeledger.css). Do not hand-edit; edit the part. Requires brand/tokens.css first. */
/* 00-base.css -- reset, type roles, layout primitives, focus. Consumes brand/tokens.css only. */
*, *::before, *::after { box-sizing: border-box; }
html { font-size: 18px; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-weight: var(--weight-regular);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, p, ul, ol, figure, blockquote { margin: 0; }
h1, h2, h3, h4 { font-family: var(--font-display); color: var(--color-text); }
/* Kit-wide heading-to-next-block rhythm (13.10 NOT GO round 2, queen dispatch 2026-09-03T010500Z-662, defect 1):
   the blanket margin:0 reset above was previously restored ONLY under `.prose h2`/`.prose h3` (further down this
   file), so every heading on a page shape that doesn't wrap its body copy in a `.prose`-classed ANCESTOR (every
   staged rebuild page: headings there are siblings of `.prose`-classed paragraphs, not ancestors of them) sat
   0px above whatever followed it. One decision, from the SPACE scale (brand/tokens.js), applied everywhere a
   heading renders. `.prose h2`/`.prose h3` below still win by specificity (a class + tag selector beats a bare
   tag selector) wherever that narrower context legitimately wants its own already-tuned values -- this rule is
   the floor everywhere else, not a replacement for it. Margins collapse with whatever margin-top the next block
   already carries (browser default), so this sets the effective gap directly in the common case where the next
   block has none. */
h1 { margin-bottom: var(--space-6); } /* 32px -- the display/h1 scale carries the most visual weight, needs the most room before body copy (measured: 12px under a 66px PC1 headline read as "almost touching" the price line) */
h2 { margin-bottom: var(--space-5); } /* 24px */
h3 { margin-bottom: var(--space-4); } /* 16px */
h4 { margin-bottom: var(--space-3); } /* 12px */
.t-display, h1.t-display { font-size: var(--text-display); line-height: var(--leading-display); letter-spacing: var(--tracking-display); font-weight: var(--weight-bold); }
h1, .t-h1 { font-size: var(--text-h1); line-height: var(--leading-h1); letter-spacing: var(--tracking-h1); font-weight: var(--weight-bold); }
h2, .t-h2 { font-size: var(--text-h2); line-height: var(--leading-h2); letter-spacing: var(--tracking-h2); font-weight: var(--weight-bold); }
h3, .t-h3 { font-size: var(--text-h3); line-height: var(--leading-h3); font-weight: var(--weight-semibold); }
h4, .t-h4 { font-size: var(--text-h4); line-height: var(--leading-h4); font-weight: var(--weight-semibold); }
.t-small { font-size: var(--text-small); line-height: var(--leading-small); }
.t-caption { font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-text-muted); }
.t-figure { font-family: var(--font-mono); font-size: var(--text-figure); line-height: var(--leading-figure); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; } /* a long unbroken token (a URL, a hash) must never widen the page (08.14: the kit page overflowed at 375 on the fonts URL specimen) */
[data-section="sources"] a { overflow-wrap: anywhere; } /* same class of defect as .mono above, caught 2026-09-03 on the first PC3 leaf page to carry many real citations (rebuild-render-class.mjs's 'sources' case renders each claim's own citation string -- e.g. "SRC:domain.com:https://..." -- as unbroken link text with no natural break point) */
.t-soft { color: var(--color-text-soft); }
.t-muted { color: var(--color-text-muted); }
/* Section tag / eyebrow. Inherits fresh-lens .tag but on text-muted, not the ochre: the ochre reads 3.03:1 at this size (see CONTRAST-REPORT.md). */
.tag { display: block; font-family: var(--font-mono); font-size: var(--text-label); line-height: var(--leading-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin-bottom: var(--space-5); }
.tag--accent { color: var(--color-primary); }
a { color: var(--color-link); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
a:hover { color: var(--color-primary-hover); }
p + p { margin-top: var(--space-4); }
.prose { max-width: var(--measure); }
.prose h2 { margin-top: var(--space-7); margin-bottom: var(--space-4); }
.prose h3 { margin-top: var(--space-6); margin-bottom: var(--space-3); }
.prose ul, .prose ol { padding-left: var(--space-5); margin-top: var(--space-4); }
.prose li + li { margin-top: var(--space-2); }
/* Pull quote: display family, larger, a hanging opening mark. No accent bar (F-AID-01 left-stripe tell). */
.prose blockquote { font-family: var(--font-display); font-size: var(--text-h4); line-height: var(--leading-h4); color: var(--color-text-soft); margin-top: var(--space-5); padding-left: var(--space-5); position: relative; }
/* F1922 (stage 15, qa-seventh-run.md's real orphan-class finding): .lead and .updated were emitted by the
   legal/authority 'body' case (rebuild-render-class.mjs) with no matching kit rule -- rendered fine as plain
   default paragraphs (not broken), just missing the lede/dateline distinction the class names imply. .lead is
   the legal-lead/article-lead opening sentence, conventionally set slightly larger and softer than body copy;
   .updated is the "Effective <date>" line, conventionally set small and muted like the kit's own .t-caption. */
.prose .lead { font-size: var(--text-h4); line-height: var(--leading-h4); color: var(--color-text-soft); }
.prose .updated { font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-text-muted); }
.prose blockquote::before { content: open-quote; position: absolute; left: 0; top: -0.1em; font-size: 2em; line-height: 1; color: var(--color-primary); }
.prose figure { margin-top: var(--space-6); }
.prose figcaption { font-size: var(--text-caption); color: var(--color-text-muted); margin-top: var(--space-2); }
hr { border: 0; border-top: 1px solid var(--color-border); margin: var(--space-7) 0; }
.wrap { max-width: var(--container); margin: 0 auto; padding: 0 var(--margin-mobile); }
.wrap--prose { max-width: var(--container-prose); }
@media (min-width: 720px) { .wrap { padding: 0 var(--margin-tablet); } }
@media (min-width: 1024px) { .wrap { padding: 0 var(--margin-desktop); } }
.band { padding: var(--space-8) 0; }
.band--surface { background: var(--color-surface); }
/* --color-ink-fixed/--color-on-ink-fixed -- REMOVED (2026-09-08, dispatch 2026-09-08T161102Z-1035,
   reply_to F2314): a FIXED token (identical value in both theme blocks) is a theme escape hatch by
   definition, so this slab stopped following the sitewide dark theme -- reading as a second, different
   dark against the page's own near-black background. `.band--ink` now uses ordinary theme-swapping
   roles, same as any other surface, so it always follows the page theme. h1-h4 need no override here:
   the base heading rule above already sets color: var(--color-text). */
.band--ink { background: var(--color-surface-raised); color: var(--color-text); }
.band + .band { border-top: 1px solid var(--color-border); }
@media (min-width: 720px) { .band { padding: var(--space-9) 0; } }
.grid { display: grid; gap: var(--gutter); grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr)); }
.col-4 { grid-column: span 12; } .col-6 { grid-column: span 12; } .col-8 { grid-column: span 12; }
@media (min-width: 720px) { .col-4 { grid-column: span 6; } .col-6 { grid-column: span 6; } .col-8 { grid-column: span 12; } }
@media (min-width: 1024px) { .col-4 { grid-column: span 4; } .col-6 { grid-column: span 6; } .col-8 { grid-column: span 8; } }
.stack > * + * { margin-top: var(--space-4); }
.stack--tight > * + * { margin-top: var(--space-2); }
.stack--loose > * + * { margin-top: var(--space-6); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
/* Focus: one ring, everywhere, never removed. */
:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-xs); }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; left: var(--space-3); top: -100px; padding: var(--space-2) var(--space-3); background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border-strong); border-radius: var(--radius-s); z-index: 100; }
.skip-link:focus-visible { top: var(--space-3); }
img, svg, video { max-width: 100%; height: auto; display: block; }
::selection { background: var(--color-primary); color: var(--color-on-primary); }

/* type roles the kit page and templates use for body and label text (11.12 intake found them undefined) */
.t-body { font-size: var(--text-body); line-height: var(--leading-body, 1.5); }
.t-label { font-family: var(--font-mono); font-size: var(--text-label); line-height: var(--leading-label, 1.2); letter-spacing: var(--tracking-label); text-transform: uppercase; }

/* 10-button.css -- .btn: primary (filled), ghost (outlined), quiet (text). 8 states each. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  font-family: var(--font-display); font-weight: var(--weight-medium); font-size: var(--text-body); line-height: 1;
  min-height: 48px; padding: 0 var(--space-5);
  border-radius: var(--radius-m); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.btn--primary { background: var(--color-primary); color: var(--color-on-primary); border-color: var(--color-primary); }
.btn--primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); color: var(--color-on-primary); transform: translateY(-1px); }
.btn--primary:active { transform: translateY(0); background: var(--color-primary-hover); }
.btn--ghost { background: transparent; color: var(--color-text); border-color: var(--color-text); }
.btn--ghost:hover { background: var(--color-text); color: var(--color-bg); }
.btn--ghost:active { opacity: 0.85; }
.btn--quiet { background: transparent; color: var(--color-link); border-color: transparent; padding-left: var(--space-2); padding-right: var(--space-2); text-decoration: underline; text-underline-offset: 0.18em; }
.btn--quiet:hover { color: var(--color-primary-hover); }
.btn:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; transform: none; pointer-events: none; }
.btn[aria-busy="true"] { position: relative; color: transparent; pointer-events: none; }
.btn[aria-busy="true"]::after {
  content: ""; position: absolute; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  color: var(--color-on-primary); animation: btn-spin 0.8s linear infinite;
}
.btn--ghost[aria-busy="true"]::after, .btn--quiet[aria-busy="true"]::after { color: var(--color-text); }
.btn--error { background: var(--color-error); border-color: var(--color-error); color: var(--color-on-primary); }
.btn--error:hover { filter: brightness(0.92); }
.btn--success { background: var(--color-success); border-color: var(--color-success); color: var(--color-on-primary); }
.btn--sm { min-height: 36px; padding: 0 var(--space-4); font-size: var(--text-small); }
.btn--lg { min-height: 56px; padding: 0 var(--space-6); }
.btn--pill { border-radius: var(--radius-pill); }
.btn--block { width: 100%; }
/* .band--ink's own on-ink button override -- REMOVED (2026-09-08, dispatch 2026-09-08T161102Z-1035,
   reply_to F2314): it depended on the now-deleted --color-ink-fixed/--color-on-ink-fixed(-surface)
   fixed tokens. `.band--ink` is now an ordinary themed surface (00-base.css), so the plain .btn rules
   above already render correctly on it in both themes -- no override needed. */
.cta-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
@media (max-width: 600px) { .cta-row { flex-direction: column; align-items: stretch; gap: var(--space-2); } .cta-row .btn { width: 100%; } }
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .btn, .btn:hover { transform: none; } .btn[aria-busy="true"]::after { animation-duration: 1.6s; } }

/* 20-forms.css -- .field (label + control + hint/error), .input/.select/.textarea, .check, .search. */
.field { display: block; }
.field + .field { margin-top: var(--space-5); }
.field__label { display: block; font-family: var(--font-display); font-weight: var(--weight-medium); font-size: var(--text-small); color: var(--color-text); margin-bottom: var(--space-2); }
.field__label .req { color: var(--color-error); margin-left: 2px; }
.field__hint { display: block; font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-text-muted); margin-top: var(--space-2); }
.field__error { display: block; font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-error); margin-top: var(--space-2); font-weight: var(--weight-medium); }
.field__success { display: block; font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-success); margin-top: var(--space-2); font-weight: var(--weight-medium); }
.input, .select, .textarea {
  display: block; width: 100%;
  font: inherit; font-size: var(--text-body); line-height: 1.4; color: var(--color-text);
  background: var(--color-surface); border: 1px solid var(--color-border-strong); border-radius: var(--radius-s);
  min-height: 48px; padding: var(--space-3) var(--space-4);
  transition: border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
}
.input::placeholder, .textarea::placeholder { color: var(--color-text-muted); opacity: 1; }
.input:hover, .select:hover, .textarea:hover { border-color: var(--color-text-soft); }
.input:focus-visible, .select:focus-visible, .textarea:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-color: var(--color-focus); }
.input:active, .textarea:active { border-color: var(--color-focus); }
.input:disabled, .select:disabled, .textarea:disabled { background: var(--color-bg); color: var(--color-text-muted); cursor: not-allowed; border-style: dashed; }
.input[aria-busy="true"] { background-image: linear-gradient(90deg, transparent 0%, var(--color-bg) 50%, transparent 100%); background-size: 200% 100%; animation: input-shimmer 1.2s linear infinite; }
.field--error .input, .field--error .select, .field--error .textarea, .input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--color-error); background: var(--color-error-soft); }
.field--error .input:focus-visible, .input[aria-invalid="true"]:focus-visible { outline-color: var(--color-error); }
.field--success .input, .field--success .select, .field--success .textarea { border-color: var(--color-success); background: var(--color-success-soft); }
.textarea { min-height: 132px; resize: vertical; }
.select { appearance: none; -webkit-appearance: none; padding-right: var(--space-7); background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - 22px) 50%, calc(100% - 16px) 50%; background-size: 6px 6px; background-repeat: no-repeat; }
/* Checkbox and radio: native control, styled with accent-color, real label hit area. */
.check { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; font-size: var(--text-body); color: var(--color-text); }
.check + .check { margin-top: var(--space-3); }
.check input { flex: none; width: 20px; height: 20px; margin: 3px 0 0; accent-color: var(--color-primary); cursor: pointer; }
.check input:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.check input:disabled, .check input:disabled + span { cursor: not-allowed; opacity: 0.5; }
.check--error input { outline: 2px solid var(--color-error); outline-offset: 1px; }
.check__hint { display: block; font-size: var(--text-caption); color: var(--color-text-muted); }
/* Fieldset group */
.fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
/* Honeypot input (2026-09-03, PC1 transactional batch 3, form-specs.md rule 4): the .hp class every hp_field
   honeypot on the site already carries had no kit rule, so it rendered as a real, empty, unstyled visible input
   box on the /get-started/ render-evidence screenshot -- the live production page hides the identical field with
   `.gs-form .hp{display:none!important}` (its own inline <style>). display:none, not the kit's `.visually-hidden`
   utility above: visually-hidden keeps content in the accessibility tree on purpose (it is for sighted-hidden,
   screen-reader-visible copy); a honeypot wants the opposite -- gone for a real visitor using either sense, still
   present in the raw DOM a non-rendering bot fills blindly. The field's own aria-hidden="true"/tabindex="-1" are
   unchanged and still do their job for anything that DOES render CSS. */
.hp { display: none; }
/* .gs-form vertical rhythm (dispatch 2026-09-11T132500Z-1105, operator walk on /pc1/get-started/: "content and
   buttons being too close together top/bottom touching"). Same defect class as F2377/F2381: the kit's `p + p`
   idiom (00-base.css) only fires between adjacent <p> elements, and .field's own `.field + .field` rule (line 3
   above) only fires between .field wrappers -- .gs-form's five intake rows are bare <label> elements (no
   .field class), so NEITHER idiom ever matched them, and the trailing consent paragraph -> submit button
   transition has no rule at all either. Measured (scripts/scratch-get-started-gap-probe.mjs, both 390px and
   1280px, before this fix): label+label = 1-2px, label->consent .prose = 0px, .prose->button = 0px -- three
   real absent-declaration zero/near-zero gaps, not a rendering illusion.
   A deeper root cause surfaced mid-fix: a bare `<label>` is `display: inline` by default (no rule anywhere sets
   it otherwise), and `margin-top` has NO vertical effect on an inline box -- the computed style showed the
   16px margin applied (selector matched) while the RENDERED gap stayed unchanged, because the box model itself
   ignores it. `.gs-form label { display: block }` is the real fix for that half; the `margin-top` rule alone
   would have been a silent no-op. Separately, the consent paragraph's true previous DOM sibling is the hidden
   `.hp` honeypot input (`<label>...</label><input class="hp">＜p class="prose t-caption"＞`), not the last
   `<label>` itself, so `label + .prose` never matched (CSS `+` is a structural DOM check, independent of the
   `.hp` element's own `display: none`) -- corrected to `.hp + .prose`, which fires on exactly the real
   adjacency. Fixed at the shared register (named pairs, scoped to .gs-form so no other label/prose/button usage
   sitewide is touched), same --space-4 (16px) token every other block-to-block fix in this cycle uses. The
   button->.gs-formstatus gap (8px, var(--space-2)) is left as-is: it is an existing DECLARED value (not an
   absent rule), deliberately tight so the empty status line reads as part of the button's own micro-feedback
   rather than a new paragraph -- a different, intentional design decision, not this defect class. */
.gs-form label { display: block; }
.gs-form label + label,
.gs-form .hp + .prose,
.gs-form .prose + .btn { margin-top: var(--space-4); }
/* Submit-status line (F1906, PC1 transactional batch 3 follow-up): the real fetch('/api/lead',...) handler
   ported from the live page toggles this class between .ok/.err after a real submit; empty by default so it
   takes no visible space until a status exists (matches the live page's own min-height reservation). */
.gs-formstatus { font-family: var(--font-mono); font-size: var(--text-caption); min-height: 1.2em; margin-top: var(--space-2); }
.gs-formstatus.ok { color: var(--color-success); }
.gs-formstatus.err { color: var(--color-error); }
.fieldset__legend { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-h4); padding: 0; margin-bottom: var(--space-3); }
/* Search field: input + button as one control (content search, engine-room filters). */
.search { display: flex; align-items: stretch; border: 1px solid var(--color-border-strong); border-radius: var(--radius-pill); background: var(--color-surface); overflow: hidden; min-height: 48px; }
/* Rhythm gate F2, /search/ page (queen dispatch 2026-09-03T025800Z-666, defect 2): `main form.search` sat
   flush against the following `p.t-caption` at every width (form's own reset gave it no bottom margin, and
   `.t-caption` carries no margin rule of its own -- same root-cause class as F1898/F1899's block-to-block
   gaps). Scoped to `[data-search-page]` (the attribute `scripts/rebuild-search-page.mjs` already puts only on
   the /search/ page's own form) rather than the bare `.search` class, so the shared header search box (every
   page's chrome, `scripts/lib/rebuild-chrome.mjs`) is untouched -- that instance sits inline in a flex nav row
   next to other controls, where an added bottom margin would risk a real, site-wide vertical-alignment
   regression for zero benefit. var(--space-4), the same 16px F1899 already uses for every other block-to-block
   gap this cycle. */
.search[data-search-page] { margin-bottom: var(--space-4); }
.search:focus-within { outline: var(--focus-ring); outline-offset: 2px; border-color: var(--color-focus); }
.search__input { flex: 1; min-width: 0; border: 0; background: transparent; font: inherit; font-size: var(--text-body); color: var(--color-text); padding: 0 var(--space-4) 0 var(--space-5); }
.search__input:focus-visible { outline: none; }
.search__input::placeholder { color: var(--color-text-muted); opacity: 1; }
.search__btn { flex: none; border: 0; background: var(--color-primary); color: var(--color-on-primary); font-family: var(--font-display); font-weight: var(--weight-medium); padding: 0 var(--space-5); cursor: pointer; }
.search__btn:hover { background: var(--color-primary-hover); }
.search__btn:disabled { opacity: 0.45; cursor: not-allowed; }
.search--busy .search__btn { color: transparent; position: relative; }
.search--busy .search__btn::after { content: ""; position: absolute; inset: 0; margin: auto; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--color-on-primary); border-right-color: transparent; animation: btn-spin 0.8s linear infinite; }
.search__results { list-style: none; margin: var(--space-3) 0 0; padding: 0; border: 1px solid var(--color-border); border-radius: var(--radius-m); background: var(--color-surface-raised); box-shadow: var(--shadow-raised); }
.search__results li + li { border-top: 1px solid var(--color-border); }
.search__results a { display: block; padding: var(--space-3) var(--space-4); color: var(--color-text); text-decoration: none; }
.search__results a:hover, .search__results a:focus-visible { background: var(--color-bg); }
.search__results mark { background: var(--color-warning-soft); color: inherit; }
.search__empty { padding: var(--space-4); color: var(--color-text-muted); }
.form-row { display: grid; gap: var(--space-4); }
@media (min-width: 720px) { .form-row { grid-template-columns: 1fr 1fr; } }
@keyframes input-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .input[aria-busy="true"] { animation: none; } }

/* 30-nav.css -- site chrome (same class names tools/site-chrome.js emits, F-AID-05 single source) restyled onto the semantic tokens; breadcrumbs; tabs. */
/* Header: static on mobile (mobile-pass.md: the chrome scrolls away, no sticky chrome under 720), a plain
   sticky bar from 720 up; solid ground, no blur anywhere (operator ruling 2026-09-02, closes Tell M). */
.ins-header { position: static; z-index: 50; border-bottom: 1px solid var(--color-border); background: var(--color-bg); }
@media (min-width: 720px) { .ins-header { position: sticky; top: 0; } }
.ins-header-inner { max-width: var(--container); margin: 0 auto; padding: var(--space-4) var(--margin-mobile); display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); }
@media (min-width: 720px) { .ins-header-inner { padding-left: var(--margin-tablet); padding-right: var(--margin-tablet); } }
@media (min-width: 1024px) { .ins-header-inner { padding-left: var(--margin-desktop); padding-right: var(--margin-desktop); } }
.mark { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 18px; letter-spacing: -0.02em; display: inline-flex; align-items: center; gap: 11px; color: var(--color-text); text-decoration: none; }
.mark:hover { color: var(--color-text); }
.mark svg { width: 28px; height: 28px; }
.mark svg path { stroke: var(--color-primary); }
.mark svg circle { fill: var(--color-secondary); }
/* site-chrome.js emits the de-dotted mark as <svg class="mono">: single-colour variant, primary stroke, no fills. */
.mark svg.mono path { stroke: var(--color-primary); fill: none; }
.navr { display: flex; align-items: center; gap: var(--space-6); font-family: var(--font-display); font-size: 13.5px; flex-shrink: 0; }
/* white-space: nowrap (F1890 fix item 1, 2026-09-02): .navr is a flex row with no flex-wrap set, so it never
   drops a whole item to a second row -- but a flex item's default min-width:auto lets its TEXT shrink-wrap
   below its full-line width once the row runs out of space, which is what actually happened: the two-word
   "How it works" trigger broke onto two lines at 1280 while the row itself stayed one line. nowrap forces each
   label to keep its natural width; flex-shrink:0 on .navr (above) and .ins-header-cta (below) stops the row
   itself from being asked to give up space it doesn't have, so the label can no longer be squeezed at all.
   Doing ONLY this uncovered a second, real problem, caught by re-measuring rather than assumed fixed: the full
   nav row's fixed content (mark 152px + navr 424px + CTA 107px + 3 gaps at 24px = 755px) plus even the search
   box's own minimum content width no longer fit together between the old 720px burger breakpoint and ~900px --
   nowrap had simply moved the squeeze from "How it works" wrapping onto the search box collapsing to an
   invisible 2px sliver, a horizontal-overflow FAIL at gate 10 (render evidence) at 768px. The real fix is the
   mobile-nav breakpoint below: it now covers that whole squeeze zone (burger nav through 1023px, full row only
   from 1024px up, where a live sweep confirms >=189px of real, growing room for the search box) instead of
   trying to cram a full desktop row into a width that never had enough space for it. */
.navr a, .navr-drop-trigger { color: var(--color-text-soft); text-decoration: none; transition: color var(--duration-fast); white-space: nowrap; }
.navr a:hover, .navr-drop-trigger:hover, .navr-drop-trigger[aria-expanded="true"] { color: var(--color-text); }
.navr a[aria-current="page"] { color: var(--color-primary); }
.navr a:focus-visible, .navr-drop-trigger:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.ins-header-cta { font-family: var(--font-display); font-weight: var(--weight-medium); font-size: 14px; padding: 10px 18px; border-radius: var(--radius-pill); background: var(--color-primary); color: var(--color-on-primary); text-decoration: none; white-space: nowrap; }
.ins-header-cta:hover { background: var(--color-primary-hover); color: var(--color-on-primary); }
.nav-burger { display: none; background: none; border: 0; padding: 8px; margin: -8px -6px; cursor: pointer; color: var(--color-text-soft); line-height: 0; }
.nav-burger:hover { color: var(--color-text); }
.nav-burger-box { display: block; position: relative; width: 22px; height: 14px; }
.nav-burger-bar, .nav-burger-bar::before, .nav-burger-bar::after { content: ""; position: absolute; left: 0; width: 22px; height: 2px; border-radius: 2px; background: currentColor; transition: transform var(--duration-medium) var(--ease-standard), opacity var(--duration-medium) var(--ease-standard); }
.nav-burger-bar { top: 6px; } .nav-burger-bar::before { top: -6px; } .nav-burger-bar::after { top: 6px; }
.nav-burger[aria-expanded="true"] .nav-burger-bar { background: transparent; }
.nav-burger[aria-expanded="true"] .nav-burger-bar::before { transform: translateY(6px) rotate(45deg); }
.nav-burger[aria-expanded="true"] .nav-burger-bar::after { transform: translateY(-6px) rotate(-45deg); }
.navr-drop { position: relative; }
.navr-drop-trigger { font: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.navr-drop-caret { font-size: 10px; line-height: 1; transition: transform var(--duration-fast) var(--ease-standard); }
.navr-drop-trigger[aria-expanded="true"] .navr-drop-caret { transform: rotate(180deg); }
.navr-drop-menu { display: none; list-style: none; margin: 0; padding: var(--space-2); position: absolute; top: calc(100% + 14px); left: 50%; transform: translateX(-50%); min-width: 190px; background: var(--color-surface-raised); border: 1px solid var(--color-border); border-radius: var(--radius-m); box-shadow: var(--shadow-raised); z-index: 60; }
.navr-drop-menu.is-open { display: block; }
.navr-drop-menu li + li { margin-top: 2px; }
.navr-drop-menu a { display: block; padding: 9px 12px; border-radius: var(--radius-s); font-size: 13.5px; white-space: nowrap; color: var(--color-text-soft); }
.navr-drop-menu a:hover { background: var(--color-bg); color: var(--color-text); }
.navr-drop-menu a[aria-current="page"] { color: var(--color-primary); }
/* Burger breakpoint widened 720px -> 1023px (F1890 fix item 1, 2026-09-02, see the nowrap comment above): the
   full nav row's fixed members alone (mark + navr + CTA + gaps, ~755px) plus a legible search box do not fit in
   the 721-1023px range at any margin tier this file defines, once the nav labels are no longer allowed to
   shrink-wrap to absorb the shortfall. The burger nav already renders cleanly at every width from 375px up
   (proven by this same review's 375/768 screenshots), so widening its range is a real fix, not a narrower
   workaround -- the full row now only appears once there is genuinely enough width for it (1024px, where the
   desktop margin tier also starts, leaves the search box >=189px and growing). */
@media (max-width: 1023px) {
  .ins-header-inner { position: relative; }
  .nav-burger { display: inline-flex; align-items: center; justify-content: center; }
  .navr { display: none; position: absolute; top: calc(100% + 1px); left: 0; right: 0; flex-direction: column; align-items: stretch; gap: 0; background: var(--color-surface); border-bottom: 1px solid var(--color-border); padding: var(--space-2) 0; }
  .navr.is-open { display: flex; }
  .navr a, .navr-drop-trigger { display: block; padding: var(--space-3) var(--margin-mobile); }
  .navr-drop-menu { position: static; transform: none; box-shadow: none; border: 0; border-radius: 0; background: var(--color-bg); min-width: 0; }
  /* the header row's fixed-width members (wordmark + burger + search + CTA) leave no slack below ~375px;
     trim the CTA's own footprint rather than drop it, so it stays visible outside the burger (F-M-01/F-M-03,
     mobile-pass.md, navigation.md line 81) without pushing the row into horizontal overflow (F1866-class check). */
  .ins-header-cta { padding: 9px 14px; font-size: 13px; }
}
/* Below 375px (F-M-01/F-M-03's own measured floor) the 9px/14px trim above still leaves the CTA's right edge
   ~2px past a 360px viewport (real devices at this width: older/smaller Android phones) -- test/mobile-overflow.
   test.js caught this live (rows #34/#36-38, dispatch 2026-09-11T223428Z-1154). One more step of the same
   trim, not a new visual element: shave 3px off each side of the CTA's horizontal padding, closing the overflow
   with real margin (measured: 6px freed against a ~1.8px shortfall) rather than a hairline fix. */
@media (max-width: 400px) {
  .ins-header-cta { padding: 9px 11px; }
}
/* Footer */
.ins-footer { border-top: 1px solid var(--color-border); padding: var(--space-8) 0 var(--space-8); background: var(--color-bg); color: var(--color-text); }
.ins-footer-inner { max-width: var(--container); margin: 0 auto; padding: 0 var(--margin-mobile); }
@media (min-width: 720px) { .ins-footer-inner { padding: 0 var(--margin-tablet); } }
@media (min-width: 1024px) { .ins-footer-inner { padding: 0 var(--margin-desktop); } }
.ins-footer-cta { text-align: center; margin-bottom: var(--space-7); padding-bottom: var(--space-7); border-bottom: 1px solid var(--color-border); }
.ins-footer-cta p { color: var(--color-text-soft); font-size: 1.05rem; line-height: 1.6; max-width: 44ch; margin: 0 auto var(--space-5); }
.go { font-family: var(--font-display); font-weight: var(--weight-medium); font-size: 15px; padding: 15px 30px; border-radius: var(--radius-m); display: inline-block; text-decoration: none; transition: transform var(--duration-fast) var(--ease-standard); }
.go.teal { background: var(--color-text); color: var(--color-bg); }
.go.teal:hover { transform: translateY(-2px); color: var(--color-bg); }
.ins-footer-nav { display: flex; flex-wrap: wrap; gap: 6px var(--space-6); margin-bottom: var(--space-6); font-family: var(--font-display); font-size: 13.5px; }
.ins-footer-nav a { color: var(--color-text-soft); text-decoration: none; }
.ins-footer-nav a:hover { color: var(--color-text); }
.ins-footer-fine { display: flex; justify-content: space-between; align-items: center; gap: var(--space-5); flex-wrap: wrap; }
.ins-footer-fine .mark { font-size: 16px; }
/* F1925 (stage 16, docs/rebuild/stage16-baseline.md): target-size failed WCAG 2.5.8's 24x24px minimum on these
   footer links/button (measured well under it with padding/margin both 0). A first attempt used real padding
   with a fully-canceling negative margin -- that grows the box but a fully-canceling margin also preserves the
   exact original gap to the next target, so the "safe clickable space" half of the check still failed (measured
   19px, needs 24px). Real padding here with NO margin cancellation, plus the container gap raised 4px -> 8px,
   grows both the target itself and the space around it -- confirmed by a real Lighthouse re-run after this
   version (target-size score 1, both sub-checks pass), not assumed from the first attempt's partial fix.
   Dispatch 1016 fix (2026-09-08): this was flex-direction:column at EVERY width, stacking the six items
   (email, phone, privacy, terms, accessibility, copyright) as five/six separate lines with real vertical
   gaps even on desktop where a single row fits easily -- the "contact info stacks with huge gaps" defect
   the operator walked into. Default now reads as one wrapping row; row-gap keeps the same F1925 8px value
   for whenever a row does wrap, column-gap (24px, --space-5) keeps side-by-side targets' click areas well
   clear of the 24px WCAG 2.5.8 spacing floor. The max-width:600px override below still forces a column
   stack back on narrow viewports, unchanged in shape from before this fix. */
.ins-footer-fine-right { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: flex-end; row-gap: 8px; column-gap: var(--space-5); }
.ins-footer-fine-right a, .footer-email-copy { font-family: var(--font-mono); font-size: 13px; color: var(--color-link); text-decoration: none; background: none; border: 0; padding: 6px 2px; margin: 0; cursor: pointer; }
.ins-footer-fine-right a:hover, .footer-email-copy:hover { color: var(--color-text); }
.ins-footer-fine-right p { font-family: var(--font-mono); font-size: 12.5px; color: var(--color-text-muted); }
.wf-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
@media (max-width: 600px) { .ins-footer-fine { flex-direction: column; align-items: flex-start; gap: 10px; } .ins-footer-fine-right { flex-direction: column; align-items: flex-start; justify-content: flex-start; } }
/* Breadcrumbs (F1890 fix item 4: renderBreadcrumbHtml emits a bare <nav class="crumbs"> with no wrapping
   .wrap div, so it rendered flush against the viewport edge at every width -- every other section on the page
   gets its container max-width + side padding from `.wrap` (00-base.css) or, on the header, from
   `.ins-header-inner`'s own copy of the same three tokens. The breadcrumb has no sibling markup to add a real
   `.wrap` div around without editing rebuild-chrome.mjs's render call sites, so this mirrors `.ins-header-inner`'s
   exact pattern (max-width: var(--container), centered, the same three-tier margin tokens) directly on `.crumbs`
   itself -- same visual alignment as the header/wrap content above and below it, one rule set, no markup change. */
.crumbs { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); display: block; max-width: var(--container); margin: 0 auto; padding: var(--space-3) var(--margin-mobile); }
@media (min-width: 720px) { .crumbs { padding-left: var(--margin-tablet); padding-right: var(--margin-tablet); } }
@media (min-width: 1024px) { .crumbs { padding-left: var(--margin-desktop); padding-right: var(--margin-desktop); } }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.crumbs li + li::before { content: "/"; margin-right: var(--space-2); color: var(--color-border-strong); }
.crumbs a { color: var(--color-text-muted); text-decoration: none; }
.crumbs a:hover { color: var(--color-text); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--color-text); }
/* Tabs (engine room second tab, kit page sections). Roving tabindex is JS's job; the CSS covers every state. */
.tabs { display: block; max-width: 100%; } /* the container the kit documents; the list below scrolls inside it, the page never widens (08.11 orphan closed) */
.tabs__list { display: flex; gap: var(--space-2); border-bottom: 1px solid var(--color-border); margin: 0; padding: 0; list-style: none; overflow-x: auto; }
.tabs__tab { font: inherit; font-family: var(--font-display); font-weight: var(--weight-medium); font-size: var(--text-small); color: var(--color-text-soft); background: none; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; padding: var(--space-3) var(--space-4); cursor: pointer; white-space: nowrap; transition: color var(--duration-fast), border-color var(--duration-fast); }
.tabs__tab:hover { color: var(--color-text); }
.tabs__tab[aria-selected="true"] { color: var(--color-primary); border-bottom-color: var(--color-primary); }
.tabs__tab:focus-visible { outline: var(--focus-ring); outline-offset: -2px; border-radius: var(--radius-xs); }
.tabs__tab:disabled { opacity: 0.45; cursor: not-allowed; }
.tabs__panel { padding-top: var(--space-5); }
.tabs__panel[hidden] { display: none; }

/* 40-card.css -- .card, .badge, .pick (affiliate card with disclosure), .seedling-badge, .stat (tile + sparkline). */
/* Block-to-block rhythm (13.10 walk-through nit, queen dispatch 2026-09-03T013500Z-663, extending F1898 defect 1
   past headings): `var(--space-4)` (16px), the same value 60-data.css's block components now use -- see that
   file's header comment for the full reasoning. `.pick` below is the queen's own named "card to paragraph"
   example, live not hypothetical: PC2's rendered page stacks three `.pick.pick--no-img` cards directly (no
   `.card-grid`/`.stack` wrapper around them), so with no margin at all on `.pick` those cards -- and the
   disclosure paragraph after them -- touched with a real 0px gap. `.card` itself is deliberately left alone here:
   it renders both bare (COMPONENT_RENDERERS 'card') and as a `.card-grid` grid ITEM (`.card--flat`), where a
   fixed margin-bottom on a stretch-aligned grid item can unevenly inflate a row's height against its siblings --
   `.card-grid`'s own `gap` already spaces grid cards apart; only the two non-grid, directly-stacked block types
   below get the fix. */
.card { display: block; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-m); padding: var(--space-5); color: inherit; text-decoration: none; transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard); }
.card--raised { background: var(--color-surface-raised); box-shadow: var(--shadow-raised); }
.card--flat { background: transparent; border-color: transparent; padding: 0; }
a.card:hover, .card--link:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-raised); transform: translateY(-1px); }
a.card:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
a.card:active { transform: none; }
.card[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }
.card[aria-busy="true"] .card__title, .card[aria-busy="true"] .card__body { color: transparent; background: var(--color-bg); border-radius: var(--radius-xs); }
.card--error { border-color: var(--color-error); }
.card--success { border-color: var(--color-success); }
.card__kicker { display: block; font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin-bottom: var(--space-3); }
.card__title, .card__body, .card__meta { display: block; }
.card__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-h4); line-height: var(--leading-h4); color: var(--color-text); }
.card__body { margin-top: var(--space-2); color: var(--color-text-soft); font-size: var(--text-small); line-height: var(--leading-small); }
.card__meta { margin-top: var(--space-4); font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); }
.card__media { margin: calc(-1 * var(--space-5)) calc(-1 * var(--space-5)) var(--space-4); border-radius: var(--radius-m) var(--radius-m) 0 0; overflow: hidden; aspect-ratio: 16 / 9; background: var(--color-bg); }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card-grid { display: grid; gap: var(--gutter); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-bottom: var(--space-4); }
/* Badge: status or category chip. Text sizes stay label-scale; colours are the status pairs. */
.badge { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: 0.06em; text-transform: uppercase; line-height: 1; padding: 6px 10px; border-radius: var(--radius-pill); border: 1px solid var(--color-border); color: var(--color-text-soft); background: var(--color-surface); white-space: nowrap; margin-bottom: var(--space-3); }
.badge--primary { color: var(--color-primary); border-color: var(--color-primary); background: transparent; }
.badge--success { color: var(--color-success); background: var(--color-success-soft); border-color: transparent; }
.badge--warning { color: var(--color-warning); background: var(--color-warning-soft); border-color: transparent; }
.badge--error { color: var(--color-error); background: var(--color-error-soft); border-color: transparent; }
.badge--solid { color: var(--color-on-primary); background: var(--color-primary); border-color: var(--color-primary); }
.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* Affiliate pick card: the disclosure line is part of the component, not optional. */
.pick { display: grid; gap: var(--space-4); grid-template-columns: 96px 1fr; align-items: start; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-m); padding: var(--space-4); margin-bottom: var(--space-4); }
.pick__img { width: 96px; height: 96px; object-fit: contain; background: var(--color-bg); border-radius: var(--radius-s); }
.pick__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-body); color: var(--color-text); }
.pick__why { margin-top: var(--space-2); font-size: var(--text-small); color: var(--color-text-soft); }
.pick__cta { margin-top: var(--space-3); }
/* 13.10 item 4 (queen's 22:26Z 13.8 review, F1890's item 4): this line and .pick__price-note below are prose
   disclosure sentences, not real figures -- the kit's mono face is reserved for real figures only (prices,
   dates, counts; design-decisions.md "Mono face" row), so both now render in the body face instead of reading
   as code/clutter. */
.pick__disclosure { grid-column: 1 / -1; font-family: var(--font-body); font-size: var(--text-caption); color: var(--color-text-muted); border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.pick[aria-busy="true"] .pick__title, .pick[aria-busy="true"] .pick__why { color: transparent; background: var(--color-bg); border-radius: var(--radius-xs); }
@media (max-width: 600px) { .pick { grid-template-columns: 1fr; } .pick__img { width: 100%; height: auto; aspect-ratio: 1; } }
/* Affiliate product card, no product image on record (pc2.schema.json carries no image field): a single-column
   body in place of the image + text grid above. */
.pick--no-img { grid-template-columns: 1fr; }
.pick__body { min-width: 0; }
.pick__price { margin-top: var(--space-2); font-family: var(--font-mono); font-weight: var(--weight-medium); font-size: var(--text-body); color: var(--color-text); font-variant-numeric: tabular-nums; }
.pick__price-date { margin-left: var(--space-2); font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); font-weight: var(--weight-regular); }
/* Real prose sentence ("Price and availability change..."), not a figure, so it opts back out of the mono/
   tabular-nums register .pick__price (its parent) sets for the real dated price above it -- same 13.10 item 4
   fix as .pick__disclosure. */
.pick__price-note { font-family: var(--font-body); font-weight: var(--weight-regular); font-size: var(--text-small); color: var(--color-text-soft); font-variant-numeric: normal; }
.pick__model { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); font-weight: var(--weight-regular); }
.pick__specs { margin-top: var(--space-3); padding-left: var(--space-5); font-size: var(--text-small); color: var(--color-text-soft); }
.pick__specs li { margin: var(--space-1) 0; }
/* checked <date> is a real dated figure (matches .pick__price-date's own register); .pick__sources is the
   13.10 item 1 end-of-card citation line -- prose with a link, not a figure, so it stays in the body face. */
.pick__checked { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); font-weight: var(--weight-regular); }
.pick__sources { margin-top: var(--space-2); font-size: var(--text-caption); color: var(--color-text-muted); }
.pick__sources a { color: var(--color-text-muted); }
.pick__asin { display: block; margin-top: var(--space-2); font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); }
/* Seedling badge: the only Living Websites element on a free claimant's site. */
.seedling-badge { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); text-decoration: none; padding: 6px 12px; border: 1px solid var(--color-border); border-radius: var(--radius-pill); background: var(--color-surface); margin-bottom: var(--space-3); }
.seedling-badge:hover { color: var(--color-text); border-color: var(--color-border-strong); }
.seedling-badge svg { width: 16px; height: 16px; }
.seedling-badge svg path { stroke: var(--color-primary); }
/* Stat tile + sparkline (engine room, daily report, proof wall). Figures are mono: the real-number grammar. */
.stat { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-m); padding: var(--space-4) var(--space-5); display: grid; gap: var(--space-2); min-width: 0; }
/* F1909 (queen dispatch 2026-09-03T054500Z-686): an unbreakable GitHub URL in a proof tile's caption has no
   wrap opportunity, so its intrinsic min-content width forces the grid track wider than the tile -- CSS grid
   items default to min-width:auto, letting a long unbroken string blow out its own track. min-width:0 above lets
   the tile actually shrink to its track; this lets the URL text itself wrap instead of running past the tile's
   edge. Scoped to .stat's own caption, not every .t-caption on the site, since this is the one shape (a bare
   URL, no natural break points) that trips it. */
.stat .t-caption { overflow-wrap: anywhere; }
.stat__label { font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); }
.stat__value { font-family: var(--font-mono); font-weight: var(--weight-medium); font-size: var(--text-h2); line-height: 1; color: var(--color-text); font-variant-numeric: tabular-nums; }
.stat__delta { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); }
.stat__delta--up { color: var(--color-success); }
.stat__delta--down { color: var(--color-error); }
.stat__spark { width: 100%; height: 36px; display: block; }
.stat__spark path { fill: none; stroke: var(--color-primary); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.stat__spark .spark-fill { fill: var(--color-primary); opacity: 0.12; stroke: none; }
.stat--muted .stat__value { color: var(--color-text-muted); }
.stat[aria-busy="true"] .stat__value { color: transparent; background: var(--color-bg); border-radius: var(--radius-xs); }
.stat--error { border-color: var(--color-error); }
.stat-grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin-bottom: var(--space-4); }

/* 50-feedback.css -- .alert, .modal (native <dialog>), .acc (accordion on <details>), .toast. */
/* Block-to-block rhythm (13.10 walk-through nit, queen dispatch 2026-09-03T013500Z-663, extending F1898 defect 1
   past headings): `var(--space-4)` (16px), the same value 60-data.css/40-card.css's other block components now
   use -- see 60-data.css's header comment for the full reasoning. `.alert` and `.acc` are both full-width blocks
   that can render as a section's sole or trailing sibling; giving each real trailing space keeps a future
   paragraph after either from touching, the same class of gap the operator caught on `.kv`. */
.alert { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-radius: var(--radius-m); border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); font-size: var(--text-small); line-height: var(--leading-small); margin-bottom: var(--space-4); }
.alert__icon { width: 20px; height: 20px; margin-top: 1px; }
.alert__icon path, .alert__icon circle { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.alert__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-body); margin-bottom: 2px; }
.alert__body a { color: inherit; }
.alert__actions { grid-column: 2; margin-top: var(--space-3); display: flex; gap: var(--space-3); flex-wrap: wrap; }
.alert--info { border-color: var(--color-primary); background: var(--color-surface); }
.alert--info .alert__icon, .alert--info .alert__title { color: var(--color-primary); }
.alert--success { border-color: transparent; background: var(--color-success-soft); }
.alert--success .alert__icon, .alert--success .alert__title { color: var(--color-success); }
.alert--warning { border-color: transparent; background: var(--color-warning-soft); }
.alert--warning .alert__icon, .alert--warning .alert__title { color: var(--color-warning); }
.alert--error { border-color: transparent; background: var(--color-error-soft); }
.alert--error .alert__icon, .alert--error .alert__title { color: var(--color-error); }
.alert--inline { padding: var(--space-3) var(--space-4); border-radius: var(--radius-s); }
.alert__close { grid-column: 3; align-self: start; background: none; border: 0; padding: 4px; margin: -4px; cursor: pointer; color: var(--color-text-muted); line-height: 0; }
.alert__close:hover { color: var(--color-text); }
.alert:has(.alert__close) { grid-template-columns: auto 1fr auto; }
/* Modal on <dialog>: the platform handles focus trap and Escape. */
.modal { border: 1px solid var(--color-border); border-radius: var(--radius-l); background: var(--color-surface-raised); color: var(--color-text); padding: 0; width: min(560px, calc(100vw - 2 * var(--space-4))); box-shadow: var(--shadow-overlay); }
.modal::backdrop { background: color-mix(in srgb, var(--color-text) 55%, transparent); }
.modal[open] { animation: modal-in var(--duration-medium) var(--ease-out); }
.modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); padding: var(--space-5) var(--space-5) 0; }
.modal__title { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-h3); line-height: var(--leading-h3); }
.modal__close { flex: none; background: none; border: 1px solid transparent; border-radius: var(--radius-s); padding: 6px; cursor: pointer; color: var(--color-text-muted); line-height: 0; }
.modal__close:hover { color: var(--color-text); border-color: var(--color-border); }
.modal__body { padding: var(--space-4) var(--space-5); color: var(--color-text-soft); }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--space-3); padding: 0 var(--space-5) var(--space-5); flex-wrap: wrap; }
.modal--danger .modal__title { color: var(--color-error); }
.modal[aria-busy="true"] .modal__body { opacity: 0.5; }
/* Accordion on <details> (inherits fresh-lens .faq/.qa, same markup). */
.acc { border-top: 1px solid var(--color-border); margin-bottom: var(--space-4); }
.acc__item { border-bottom: 1px solid var(--color-border); }
.acc__item summary { cursor: pointer; list-style: none; padding: var(--space-4) 0; font-family: var(--font-display); font-weight: var(--weight-medium); font-size: var(--text-body); color: var(--color-text); display: flex; align-items: center; gap: var(--space-3); }
.acc__item summary::-webkit-details-marker { display: none; }
.acc__item summary::after { content: "+"; margin-left: auto; font-family: var(--font-display); font-size: 1.3em; line-height: 1; color: var(--color-primary); transition: transform var(--duration-medium) var(--ease-standard); }
.acc__item[open] summary::after { transform: rotate(45deg); }
.acc__item summary:hover { color: var(--color-primary-hover); }
.acc__item summary:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-xs); }
.acc__item[aria-disabled="true"] summary { color: var(--color-text-muted); cursor: not-allowed; pointer-events: none; }
.acc__body { padding: 0 0 var(--space-4); color: var(--color-text-soft); line-height: 1.7; max-width: var(--measure); }
.faq { border-top: 1px solid var(--color-border); } .qa { border-bottom: 1px solid var(--color-border); }
/* Toast: transient, bottom-right, never blocking. */
.toast { position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 90; max-width: 360px; display: flex; gap: var(--space-3); align-items: flex-start; padding: var(--space-4); border-radius: var(--radius-m); background: var(--color-text); color: var(--color-bg); box-shadow: var(--shadow-overlay); font-size: var(--text-small); animation: toast-in var(--duration-medium) var(--ease-out); }
.toast::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; margin-top: var(--space-2); background: var(--color-primary); }
.toast--success::before { background: var(--color-success); }
.toast--error::before { background: var(--color-error); }
.toast__close { background: none; border: 0; color: inherit; opacity: 0.7; cursor: pointer; padding: 0; margin-left: auto; }
.toast__close:hover { opacity: 1; }
@keyframes modal-in { from { opacity: 0; transform: translateY(var(--motion-travel)); } to { opacity: 1; transform: none; } }
@keyframes toast-in { from { opacity: 0; transform: translateY(var(--motion-travel)); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .modal[open], .toast { animation: none; } }

/* 60-data.css -- .table (default + dense engine-room variant, sortable headers), .pager, .kv (key-value list), .progress. */
/* Block-to-block rhythm (13.10 walk-through nit, queen dispatch 2026-09-03T013500Z-663, extending F1898 defect 1
   from headings to every other block-level content type that can sit as a sibling before a <p> or another block
   inside a section's `.wrap`): F1898 gave every heading a real margin-bottom but left `.table`/`.table-wrap`/
   `.kv`/`.progress` at `margin: 0`/no margin rule at all, so a definition list (PC4's "PHONE / EMAIL") or a table
   running straight into the paragraph under it still reads as touching -- exactly the gap class the operator's
   own words named ("spacing between sentences, or paragraphs"), just on a non-heading sibling this time. One
   consistent value, `var(--space-4)` (16px) -- the same gap the kit already uses whenever one full paragraph
   follows another (`p + p`, below) -- applied to every such component so it behaves like a paragraph would,
   rather than a new arbitrary number per component. */
.table-wrap { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-m); background: var(--color-surface); margin-bottom: var(--space-4); }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-small); line-height: 1.45; margin-bottom: var(--space-4); }
.table caption { text-align: left; font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-body); padding: var(--space-4) var(--space-4) var(--space-2); color: var(--color-text); }
.table th, .table td { text-align: left; vertical-align: top; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-border); }
.table thead th { font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); font-weight: var(--weight-medium); background: var(--color-bg); position: sticky; top: 0; z-index: 1; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--color-bg); }
.table tr[aria-selected="true"] td { background: var(--color-success-soft); }
.table td.num, .table th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.table td.num { color: var(--color-text); }
.table .up { color: var(--color-success); } .table .down { color: var(--color-error); } .table .flat { color: var(--color-text-muted); }
.table--dense th, .table--dense td { padding: var(--space-2) var(--space-3); font-size: var(--text-caption); }
.table--dense thead th { font-size: 0.667rem; }
.table--striped tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--color-bg) 60%, transparent); }
.table th[aria-sort] { cursor: pointer; }
.table th[aria-sort] button { font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.table th[aria-sort] button:hover { color: var(--color-text); }
.table th[aria-sort] button:focus-visible { outline: var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.table th[aria-sort] button::after { content: "\25BE"; font-size: 0.9em; line-height: 1; opacity: 0.35; }
.table th[aria-sort="ascending"] button::after { content: "\25B4"; opacity: 1; }
.table th[aria-sort="descending"] button::after { opacity: 1; }
.table[aria-busy="true"] tbody td { color: transparent; }
.table[aria-busy="true"] tbody td::before { content: ""; display: block; height: var(--space-4); background: var(--color-bg); border-radius: var(--radius-xs); }
.table__empty td { text-align: center; color: var(--color-text-muted); padding: var(--space-7) var(--space-4); }
.table__error td { color: var(--color-error); background: var(--color-error-soft); }
.table td .badge { vertical-align: middle; }
/* Pagination */
.pager { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-family: var(--font-mono); font-size: var(--text-caption); }
.pager a, .pager button, .pager span { display: inline-flex; align-items: center; justify-content: center; min-width: 36px; height: 36px; padding: 0 var(--space-2); border-radius: var(--radius-s); border: 1px solid transparent; color: var(--color-text-soft); text-decoration: none; background: none; font: inherit; cursor: pointer; }
.pager a:hover, .pager button:hover { border-color: var(--color-border-strong); color: var(--color-text); }
.pager [aria-current="page"] { background: var(--color-text); color: var(--color-bg); border-color: var(--color-text); }
.pager a:focus-visible, .pager button:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.pager [aria-disabled="true"], .pager button:disabled { opacity: 0.4; pointer-events: none; }
.pager__gap { color: var(--color-text-muted); }
.pager__summary { margin-left: auto; color: var(--color-text-muted); }
/* Key-value list (report headers, order summaries) */
/* margin-top (2026-09-03, PC1 transactional batch 3): the F1898/13.10-nit "one consistent value" rule above gave
   .kv a real margin-BOTTOM but never a margin-TOP, so a .kv sitting after a plain <p> (not a heading -- headings
   already carry their own margin-bottom) still ran straight into it at 0px (rebuild-rhythm-gate.mjs caught this
   live on /packages/thanks/'s "Write or call any time." -> <dl class="kv"> pair, the first real page to put a kv
   after a paragraph instead of a heading). Same var(--space-4) value, so it collapses harmlessly with a
   preceding heading's larger margin-bottom (max() wins) and only ever adds real space where none existed. */
.kv { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-5); font-size: var(--text-small); margin: var(--space-4) 0 var(--space-4) 0; }
.kv dt { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); }
.kv dd { margin: 0; color: var(--color-text); }
.kv dd.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* Progress (page-growth toward a target; value is real or absent, never decorative) */
.progress { display: block; width: 100%; height: 8px; border-radius: var(--radius-pill); background: var(--color-border); overflow: hidden; margin-bottom: var(--space-4); }
.progress > span { display: block; height: 100%; background: var(--color-primary); border-radius: inherit; transition: width var(--duration-slow) var(--ease-out); }
.progress--success > span { background: var(--color-success); }
.progress--warning > span { background: var(--color-warning); }
.progress--error > span { background: var(--color-error); }
.progress[aria-busy="true"] > span { width: 30% !important; animation: progress-slide 1.2s var(--ease-standard) infinite; }
@keyframes progress-slide { from { transform: translateX(-100%); } to { transform: translateX(400%); } }
@media (prefers-reduced-motion: reduce) { .progress[aria-busy="true"] > span { animation: none; width: 100% !important; opacity: 0.4; } }

/* 70-motion.css -- reveal-on-enter (progressive enhancement, inherited from fresh-lens), motion hierarchy, reduced motion. */
/* Primary attention: fade + 8px rise, once, on enter. Only when JS adds .js-motion to <html>; content is fully visible in plain CSS. */
.js-motion [data-reveal] { opacity: 0; transform: translateY(var(--motion-travel)); transition: opacity var(--duration-slow) var(--ease-out), transform var(--duration-slow) var(--ease-out); }
.js-motion [data-reveal].is-revealed { opacity: 1; transform: none; }
.js-motion [data-reveal][data-reveal-delay="1"] { transition-delay: 60ms; }
.js-motion [data-reveal][data-reveal-delay="2"] { transition-delay: 120ms; }
.js-motion [data-reveal][data-reveal-delay="3"] { transition-delay: 180ms; }
/* Secondary attention: colour and border only, no movement. Backgrounds never animate except the band morph fresh-lens already owns. */
.motion-secondary { transition: color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
/* Live indicator: the one permitted ambient motion, decorative only, never wired to a real rate (anti-fabrication rule). */
.live-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--color-primary); animation: live-dot 2.4s ease-in-out infinite; vertical-align: middle; }
@keyframes live-dot { 0%, 100% { transform: scale(0.7); opacity: 0.55; } 50% { transform: scale(1); opacity: 1; } }
/* Determinism switch (12.9, F-AID-04): the pixel-diff gate sets data-freeze-motion on <html> before capture; every animation and transition stops at its final state. Never set on a served page. */
html[data-freeze-motion] *, html[data-freeze-motion] *::before, html[data-freeze-motion] *::after { animation: none !important; transition: none !important; }
html[data-freeze-motion] [data-reveal] { opacity: 1 !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
  .js-motion [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .live-dot { animation: none; opacity: 0.7; transform: none; }
  *, *::before, *::after { scroll-behavior: auto !important; }
}

/* 80-homeregister.css -- the round-2 free-site register (docs/rebuild/design-decisions.md "Homepage direction
   round"), folded into the kit as named, reusable parts (queen dispatch 2026-09-02T155000Z-648 task 2a) so the
   class renderer can emit them from a record/layout, not one-off canvas markup. Ported from the operator-cleared
   canvas source (gen2.py, C:/Users/bbenn/AppData/Local/Temp/.../lw-home-round/) with every colour re-expressed as
   an existing kit token (--color-text/--color-bg/--color-secondary already equal the canvas's literal #1B231D /
   #F6F7F4 / #B8853A in the light theme) rather than the canvas's hardcoded hex, so this part passes the
   tokens-only gate and stays theme-consistent instead of forking a second palette. `.band--ink` (00-base.css)
   is reused for every ink ground below; as of 2026-09-08 (dispatch -1035) it is an ordinary themed surface
   (surface-raised bg + text foreground), not a fixed dark slab, so plain `.btn` rules apply on it unchanged --
   no separate on-ink button swap exists anymore.
   Two real defects F1870 found in the canvas reference are fixed here, not reproduced: the fan-in entrance travel
   is `var(--motion-travel)` (8px, and 0 under reduced motion via tokens.css's own media query) instead of the
   canvas's hardcoded 18px, and the stagger delay is explicitly zeroed under reduced motion so a 0ms-duration
   animation with a nonzero delay never flashes the pre-entrance (opacity:0) state. */

/* -- ink header variant -- RETIRED (2026-09-08, dispatch 2026-09-08T161102Z-1035, reply_to F2314). A
   per-page-kind chrome variant (a second header just for offer/pricing pages) is the same class of drift
   as a fixed token: one brand-kit change (the sitewide-dark ruling) shouldn't require finding and fixing
   N different chrome variants. There is now ONE header, `.ins-header`, themed via --color-bg/--color-text/
   --color-primary only -- every page kind renders the same class (scripts/lib/rebuild-chrome.mjs's
   renderHeader() no longer takes an `ink` option). -- */

/* -- ochre display-headline accent (design-decisions.md "Ochre returns as a display accent"): a span wrapping
   ONE word inside an otherwise-normal `.t-display`/h1/h2. Never used at small text sizes -- the ochre fails the
   4.5:1 threshold below display scale (see 00-base.css's `.tag` comment); this part carries no small-text rule
   to enforce that at the component level, so it is a per-use content discipline, same as the existing `.tag`. -- */
.accent-ochre { color: var(--color-secondary); }

/* -- category strip: a full-width ochre mono uppercase strip, dot-separated (design-decisions.md "the ochre
   category strip is part of the hook band, not a ninth section"). Renders inside the hero/hook section, never
   as its own top-level `.band`. -- */
/* the hero band's own bottom padding would otherwise leave an empty ink gap below the strip (the strip renders
   outside `.wrap`, as the last child of the SAME <section>, per design-decisions.md "part of the hook band, not
   a ninth section") -- `.band--flush-bottom` (set alongside `.category-strip` by the renderer) removes it so the
   strip is the section's true visual edge. */
.band--flush-bottom { padding-bottom: 0; }
/* CTA clearance from the strip (13.10 NOT GO round 2, queen dispatch 2026-09-03T010500Z-662, defect 2):
   `.category-strip` renders as a sibling AFTER `.wrap`, inside the same flush-bottom section -- `padding-bottom:
   0` above correctly keeps the STRIP flush with the section's own true bottom edge (nothing after it), but left
   no clearance between the hero copy ABOVE the strip and the strip's own top. When `.hero-grid__copy` was the
   taller grid column (align-items: center means the shorter column centers within the taller one's height, so
   copy's own bottom landed exactly on `.wrap`'s bottom, which is exactly where the strip begins), the "Get
   started" button's bottom edge measured 0px from the strip's top edge at several widths -- never a true
   bounding-box intersection, which is why no existing overlap-only gate caught it. Fixed with a real margin-top
   on the strip itself: this only ever adds space BEFORE the strip (between the hero content and the ochre bar),
   never after it, so the flush-to-section-bottom behaviour above is untouched. var(--space-6) = 32px, the same
   kit-wide value 00-base.css's h1 rhythm rule now uses -- one spacing decision, not two, for one visual gap. */
/* -- contrast fix (2026-09-10, dispatch -1076, porting main-repo commit 36591e7c): color was var(--color-text),
   which flips to a light value under the sitewide dark default -- 2.86:1 against this strip's own ochre
   background, fails AA. var(--color-on-primary) is the existing token already designed to read against a
   themed accent fill (see ::selection in 00-base.css); no new token invented. #07090C on #B8853A = 6.13:1. */
.category-strip { background: var(--color-secondary); color: var(--color-on-primary); padding: var(--space-4) 0; margin-top: var(--space-6); }
.category-strip__list { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2) var(--space-5); list-style: none; margin: 0; padding: 0; font-family: var(--font-mono); font-size: var(--text-small); font-weight: var(--weight-medium); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.category-strip__list li::after { content: "\00b7"; margin-left: var(--space-5); opacity: 0.6; }
.category-strip__list li:last-child::after { content: ""; margin-left: 0; }

/* -- the fanned-card signature (design-decisions.md "A decorative fan-in on the signature cards, once"): 5
   cards, tilted -4/+3/-2/+4/-3deg, a one-time entrance on load, honouring reduced motion via the token contract
   (see file header). The persistent tilt is a plain `transform` outside the animation, so it survives reduced
   motion unchanged -- only the entrance (opacity + rise) is what reduced motion removes. -- */
.fan-cards { display: flex; justify-content: center; align-items: flex-end; position: relative; z-index: 2; }
.fan-card {
  width: 188px; min-height: 168px; background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-s); padding: var(--space-4) var(--space-4) var(--space-3); box-shadow: var(--shadow-raised);
  margin: 0 -8px; display: flex; flex-direction: column; gap: 9px; transform-origin: 50% 100%;
  animation: fan-card-in var(--duration-slow) var(--ease-out) both;
}
.fan-card:nth-child(1) { transform: rotate(-4deg); animation-delay: 0ms; }
.fan-card:nth-child(2) { transform: rotate(3deg); animation-delay: 60ms; }
.fan-card:nth-child(3) { transform: rotate(-2deg); animation-delay: 120ms; z-index: 1; }
.fan-card:nth-child(4) { transform: rotate(4deg); animation-delay: 180ms; }
.fan-card:nth-child(5) { transform: rotate(-3deg); animation-delay: 240ms; }
@keyframes fan-card-in { from { opacity: 0; transform: translateY(var(--motion-travel)) rotate(0deg); } }
@media (prefers-reduced-motion: reduce) { .fan-card { animation-delay: 0ms; } }
.fan-card__preview { height: 44px; border-radius: var(--radius-xs); background: var(--color-bg); border: 1px solid var(--color-border); display: flex; align-items: flex-end; padding: 6px; gap: 4px; }
.fan-card__bar { width: 14px; background: var(--color-success-soft); border: 1px solid var(--color-primary); border-bottom: 0; border-radius: 2px 2px 0 0; }
.fan-card__row { height: 8px; border-radius: 2px; background: var(--color-border); }
.fan-card__row--short { width: 60%; }
.fan-card__label { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin-top: 4px; }
.fan-card__badge { align-self: flex-start; font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-primary); border: 1px solid var(--color-primary); border-radius: var(--radius-pill); padding: 2px 7px; }
@media (max-width: 719px) {
  .fan-cards { flex-wrap: nowrap; justify-content: center; }
  .fan-card { width: 104px; min-height: 128px; margin: 0 -12px; padding: var(--space-3); gap: 6px; }
  .fan-card:nth-child(5) { display: none; }
  .fan-card__preview { height: 30px; }
}

/* -- split light/ink card (design-decisions.md "the register carries through every page class"; the "what
   living means" contrast card): one card, two halves, left light with rows, right ink with rows + an ochre
   link line. -- */
/* Block-to-block rhythm (13.10 walk-through nit, queen dispatch 2026-09-03T013500Z-663, extending F1898 defect 1
   past headings, same `var(--space-4)` value and reasoning as 60-data.css's header comment): `.split-card`,
   `.topic-cards`, and `.figure-row` below are the other full-width block types this file renders as a section
   sibling that could sit directly before a `<p>` or another block. */
.split-card { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-radius: var(--radius-l); overflow: hidden; box-shadow: var(--shadow-raised); margin-bottom: var(--space-4); }
.split-card__half { padding: var(--space-7); display: flex; flex-direction: column; gap: var(--space-4); }
.split-card__half--light { background: var(--color-surface); }
/* --color-ink-fixed/--color-on-ink-fixed -- REMOVED (2026-09-08, dispatch 2026-09-08T161102Z-1035,
   reply_to F2314): same defect and same fix as .band--ink in 00-base.css. This half is now an ordinary
   themed surface, so it always follows the page theme; the base .split-card__rows > div border-bottom
   (var(--color-border), below) already themes correctly on it, no override needed; h3/h4 already get
   var(--color-text) from the base heading rule (00-base.css). */
.split-card__half--ink { background: var(--color-surface-raised); color: var(--color-text); }
.split-card__rows { display: flex; flex-direction: column; }
.split-card__rows > div { padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border); font-size: var(--text-small); line-height: var(--leading-small); }
.split-card__link { color: var(--color-secondary); font-size: var(--text-small); text-decoration-thickness: 1px; }
/* was color: var(--color-bg) (2026-09-08, dispatch -1035 sweep): that read as "the light ground colour",
   used as a foreground on the (formerly fixed-dark) ink half -- the same defect class, one step removed:
   --color-bg flips to near-black under the sitewide dark theme, which would have made this hover state
   unreadable against --color-surface-raised now that the half is themed normally. var(--color-text)
   is the correct themed foreground here, same as every other on-surface hover state in this kit. */
.split-card__link:hover { color: var(--color-text); }
@media (max-width: 719px) { .split-card { grid-template-columns: minmax(0, 1fr); } .split-card__half { padding: var(--space-6); } }

/* -- ochre-numbered topic cards: a top rule, an ochre numeral, a title, a body line. -- */
.topic-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-6); margin-top: var(--space-4); margin-bottom: var(--space-4); }
.topic-card { border-top: 1px solid var(--color-border); padding-top: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); text-decoration: none; color: inherit; }
.topic-card:hover .topic-card__title { color: var(--color-primary); }
.topic-card:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-xs); }
.topic-card__num { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-h2); line-height: 1; color: var(--color-secondary); }
.topic-card__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-body); color: var(--color-text); }
.topic-card__body { font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-text-muted); }
@media (max-width: 719px) { .topic-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); } }

/* -- ink statement band: one large centred sentence on ink, mono figures, the live dot (reused unchanged --
   `.live-dot` already carries its own reduced-motion override, 70-motion.css; this part never redefines it, the
   real defect F1870 found was in the canvas's own local recreation, not in this kit). Extends `.band--ink`. -- */
.statement-band { text-align: center; }
.statement-band__lead { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-h1); line-height: var(--leading-h1); max-width: 30ch; margin: 0 auto; text-wrap: balance; }
.figure-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-6); margin-top: var(--space-8); margin-bottom: var(--space-4); text-align: left; max-width: 640px; margin-left: auto; margin-right: auto; }
/* .figure/.figure__value/.figure__unit/.figure__date used var(--color-bg) as a foreground colour (2026-09-08,
   dispatch -1035 sweep): the same defect one step removed -- --color-bg was standing in for "the light
   ground colour", correct only while this statement-band sat on a genuinely fixed-dark .band--ink. Now that
   .band--ink is themed normally (surface-raised bg + text foreground, above), --color-bg flips to near-black
   under the sitewide dark theme, which would render these mono figures unreadable. var(--color-text) is the
   correct themed foreground; the divider uses var(--color-border), the kit's own decorative-hairline token
   (exempt from the contrast floor by design, see brand/tokens.js's file header), instead of hand-mixing one. */
.figure { display: flex; flex-direction: column; gap: var(--space-2); border-top: 1px solid var(--color-border); padding-top: var(--space-4); }
.figure__value { font-family: var(--font-mono); font-weight: var(--weight-medium); font-size: var(--text-h1); line-height: 1; color: var(--color-text); font-variant-numeric: tabular-nums; }
/* 13.10 NOT GO round 2 (queen dispatch 2026-09-03T010500Z-662, defect 4b): the noun attached to the number
   itself ("1 page", not a bare "1"), styled down from the huge mono figure size so it reads as a unit label
   riding beside the number, not a second giant digit. */
.figure__unit { font-family: var(--font-body); font-weight: var(--weight-regular); font-size: var(--text-small); color: color-mix(in oklab, var(--color-text) 68%, var(--color-secondary)); }
.figure__label { font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-secondary); display: flex; align-items: center; gap: var(--space-2); }
.figure__date { font-family: var(--font-mono); font-size: var(--text-caption); color: color-mix(in oklab, var(--color-text) 68%, var(--color-secondary)); }
@media (max-width: 719px) { .figure-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); } }

/* -- ink funnel variant: `.band--ink` (00-base.css) already covers this fully -- no new CSS needed. Applying
   `.band--ink` to the funnel `<section>` IS the ink funnel; plain `.btn` rules apply on it unchanged (2026-09-08,
   dispatch -1035: `.band--ink` is now an ordinary themed surface, no separate on-ink button swap exists). -- */

/* -- hero grid: the alive signature as the hero's own right half (queen dispatch 2026-09-02T165800Z-650,
   operator rec 1, verbatim "make the colony the hero's right half at twice the size" -- "the colony IS the
   hero's second half, not a diagram below it"). Two columns at desktop widths, a single stacked column below
   the SAME 719px threshold every other part of this file already uses (mobile-pass.md's existing PC1 hero
   mobile-stacking rule, extended rather than reinvented) -- the signature stacks AFTER the copy on mobile
   (`order: 2`), matching copy-to-preserve.md's "free claim first in reading order" rule for this hero. Scoped
   to the record's own `aliveSignature`-flagged hero markup (scripts/rebuild-render-class.mjs's hero case) --
   a plain fanned-card ink hero (no template opts into that flag yet) keeps its existing single-column stacked
   layout, since the operator's ruling named the colony specifically, not every ink hero. -- */
.hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-8); align-items: center; }
.hero-grid__copy { min-width: 0; }
.hero-grid__signature { min-width: 0; }
@media (max-width: 719px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
  .hero-grid__copy { order: 1; }
  .hero-grid__signature { order: 2; }
}

/* -- the price line as the offer, not metadata (operator rec 4, second half, verbatim "the price line ... sits
   in small monospace and reads as metadata rather than the offer; give it the weight the offer needs"): the
   statement-band's own mono-figure register (`.figure__value`, above) instead of the old plain `.t-figure`
   treatment. The rendered digit strings are byte-identical to before (only the wrapping span/class changed in
   scripts/rebuild-render-class.mjs), so gate 7's no-fabricate plain-substring match still finds them. -- */
.price-line { margin-top: var(--space-3); display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--space-2); row-gap: 2px; }
.price-line__figure { font-family: var(--font-mono); font-size: var(--text-h3); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.price-line__sep { font-family: var(--font-body); font-size: var(--text-small); font-weight: var(--weight-regular); opacity: 0.75; }
/* NOT CHANGED (dispatch 2026-09-10T143500Z-1074, corolla F50/queen premise-check): the dispatch reported this
   text renders as #352A1C on a #171D21 surface (1.21:1, fail) and asked for full-strength --color-secondary
   instead. Live-rendered on all 5 real pages that carry this element (pc1/packages/{core,essential,foundation,
   growth}/ + pc1/pricing/), the actual nearest opaque background is `.band--ink`'s own background --
   var(--color-text), which under the sitewide dark-theme default (commit db59baa3) resolves to #EAF2F0, not
   #171D21 -- confirmed by direct getComputedStyle() probe and by rebuild-a11y-scan.mjs itself once its oklab
   blind spot (below) was patched. Rasterizing the existing color-mix to real RGB gives #352A1C, and #352A1C on
   #EAF2F0 measures 12.31:1 -- a strong PASS, not the reported 1.21:1 fail. Swapping to full-strength
   --color-secondary as the dispatch asked would have made this WORSE (#B8853A on #EAF2F0 = 2.86:1, fails) --
   tried and reverted here, see oversight/results/2026-09-10T143500Z-1074-a11y-contrast-fix.md for the numbers.
   Left as-is; #171D21 (--color-surface-raised) does not appear as this element's background on any live page
   found. If a #171D21 card context exists elsewhere, it needs its own named finding, not a guess applied here. */
.price-line__qualifier { flex-basis: 100%; font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: color-mix(in oklab, var(--color-bg) 70%, var(--color-secondary)); }

/* 81-alivesignature.css -- the living signature (queen dispatch 2026-09-02T161800Z-649, part 3 of -648: "the
   living aspect ... creative and fancy", inside the three truths: alive means true, one signature not scattered
   motion, the July colony hero is the lineage). Concept A from docs/rebuild/alive-signature-brainstorm.md,
   recommended and built there BEFORE this file was written.

   Real-data contract: every card's title/path/date and the running count are read from data/alive-signature-
   feed.json and data/site-telemetry.json by scripts/rebuild-render-class.mjs's aliveColony() -- this file draws
   NOTHING itself; it only positions and animates what the renderer already filled in from real records. If the
   feed is empty (a fresh checkout before the feed script has ever run), the renderer falls back to the existing
   decorative `.fan-cards` (80-homeregister.css) instead of rendering an empty or fabricated colony.

   Motion contract, load-bearing: every element that moves does so ONCE, on load, as part of the SAME one-time
   entrance sequence (threads draw in, then the hub and all four cards settle) -- a re-enactment of real,
   already-happened, dated events, never a repeating/looping claim of ongoing activity (the lineage file's own
   v8-growth used an infinite 9s loop; truth #1 forbids implying a new page is born on a fixed short cycle,
   since that is not true, so this port removes the loop rather than reproducing it -- see the brainstorm doc's
   Concept A section). The newest card (`.colony__card--new`) and its thread (`.colony__thread--new`) still
   settle LAST and carry the strongest visual weight (secondary-colour border/thread, the headline-weight title
   and date below) -- it is still the one re-enactment the whole signature is built around; the 3 "steady" cards
   and the hub now also play the SAME single entrance (fade/rise, once) instead of appearing with no motion at
   all, so the whole colony reads as one coordinated arrival rather than "three static things plus one that
   moves." After the entrance settles, the hub dot alone picks up a continuous ambient breath -- decorative
   only, the same `.live-dot` (70-motion.css) contract, explicitly never wired to a real rate and explicitly
   outside the one-time entrance (see the revision note below).

   Freeze-switch contract (docs/rebuild/motion-review-12-10.md, the row this file's dispatch added): follows the
   SAME technique `.fan-card` (80-homeregister.css) already uses -- the animated end-state (opacity, transform,
   stroke-dashoffset) is declared ONLY inside the `@keyframes ... from { }` block, never as a base rule on the
   class itself. `html[data-freeze-motion] *` (70-motion.css) already sets `animation: none !important` on
   every element; because nothing here sets an "un-animated" base value, removing the animation naturally
   reverts the element to its default, fully-visible, undashed state -- no extra freeze override needed, and
   none is added (avoids a second, easy-to-miss !important surface).

   SCALED + STAGED revision (queen dispatch 2026-09-02T165800Z-650, operator ruling on the F1872 prototype:
   "I like it, but agree with your recs"). Four changes, presentation/staging only -- the real-data contract
   above is untouched:
   (1) sized up to sit as the hero's own right half (`.hero-grid__signature`, 80-homeregister.css) instead of a
       small schematic below the hero -- see the "hero-grid scale" section below.
   (2) the entrance widens to three chained stages, still ONE entrance, once, inside this section only: all
       four threads draw in, then the hub and all four cards settle, then the hub picks up a continuous ambient
       breath (the live-dot's own decorative-only, never-a-real-rate contract, explicitly excluded from the
       one-time entrance and explicitly stopped -- not slowed -- under reduced motion).
   (3) the newest card's title and date get the statement-band's own mono-figure weight, so the real dated fact
       reads as the page's headline claim, not incidental card metadata.
   Every element that moves still traces to the same two real files named above; nothing new was made to move.

   REST-STATE revision (queen dispatch 2026-09-02T183500Z-653, operator ruling: "Approved. Yes, with one move:
   keep the structure visible at rest"). Not a new element and not new motion -- two colour-only fixes to the
   SETTLED state the three-stage entrance above already lands on:
   (a) `.colony__thread` (the 3 non-newest threads) drew at `color-mix(in oklab, var(--color-bg) 22%,
       transparent)` -- a live t+10s render measured this as `oklab(0.9745 ... / 0.22)`, i.e. a near-white
       stroke at 22% alpha on the ink band's dark ground, and the resulting screenshot showed literally no
       visible line for 3 of the 4 threads (only `.colony__thread--new`'s solid, un-mixed `--color-secondary`
       stroke was visible) -- caught by measuring the computed style and looking at the actual PNG, not assumed
       from the CSS. Raised to 48% alpha: still visibly quieter than the ochre newest-thread accent (never
       claims equal weight with the one real re-enactment the signature is built around), but now a real,
       readable line at rest, not a ghost.
   (b) `.colony__hub-label` ("LIVING") measured with adequate contrast already (an opaque warm-light colour on
       the dark ink ground) and read clearly in the same t+10s screenshot -- strengthened anyway from a 72%
       bg/28% secondary blend to 58%/42% for real margin, since the operator named the label explicitly and a
       small caption-sized mono label has little room to spare.
   Nothing here touches `stroke-dashoffset`, any `animation-*` property, or the hub-dot's own ambient breathe
   (`colony-hub-breathe`, unchanged) -- the one-time entrance still plays once and settles exactly as before;
   only what the SETTLED colours already were changes. */

/* Four-corner hub layout (revised after the first render showed the fan-style overlap positions colliding --
   real card heights, driven by real variable-length titles, do not fit the original tighter fan coordinates
   cleanly). Each card owns one quadrant of the box with a wide dead zone between quadrants, so overlap cannot
   happen regardless of how many lines a given real title wraps to; the hub sits in the middle with a thread to
   each corner. Less literally "fanned" than the lineage file's cascade, more legible -- named as a deliberate
   adaptation, not a defect, in the review package. */
.colony { position: relative; max-width: 600px; height: 340px; margin: var(--space-8) auto 0; }
.colony__threads { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Stage 1 (0-480ms): every thread draws in (stroke-dashoffset). 300 is a safe over-estimate of every path's
   real length (the longest hub-to-corner curve measures roughly 250-260 units in the 560x620 reference box
   below) -- a dasharray value at or above the true path length is what makes the "hidden at full offset, fully
   drawn at zero offset" reveal technique work; extra slack beyond the real length is harmless (docs/rebuild/
   alive-signature-brainstorm.md's geometry note). The newest thread keeps its own stronger colour/weight and a
   slightly later delay so it still reads as the one the sequence is building toward, not a fourth identical
   line. */
.colony__thread {
  fill: none; stroke: color-mix(in oklab, var(--color-bg) 48%, transparent); stroke-width: 2;
  stroke-dasharray: 300; animation: colony-thread-in var(--duration-slow) var(--ease-out) both; animation-delay: 0ms;
}
.colony__thread--new { stroke: var(--color-secondary); stroke-width: 2; animation-delay: 60ms; }
@keyframes colony-thread-in { from { stroke-dashoffset: 300; } }

/* Stage 2 (~340-1000ms, overlapping stage 1's tail): the hub fades/scales in, then the four cards settle in
   turn -- steady cards first, the newest card last, so it still visibly arrives as the sequence's climax. */
.colony__hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 3; display: flex;
  flex-direction: column; align-items: center; gap: 4px;
  animation: colony-hub-in var(--duration-slow) var(--ease-out) both; animation-delay: 340ms;
}
@keyframes colony-hub-in { from { opacity: 0; transform: translate(-50%, -50%) scale(0.85); } }

/* Stage 3 (~950ms on, continuous): the hub dot alone picks up a slow ambient breath -- same decorative-only,
   never-wired-to-a-real-rate contract as `.live-dot` (70-motion.css), and explicitly stopped (not slowed)
   under reduced motion, same as that rule's own override. It starts only once stage 2 has fully settled, so it
   never reads as a second entrance -- it is idle/ambient motion on an already-settled element, the same
   category the motion spec already permits per page. */
.colony__hub-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--color-bg);
  animation: colony-hub-breathe 3.2s var(--ease-standard) infinite; animation-delay: 950ms;
}
@keyframes colony-hub-breathe { 0%, 100% { transform: scale(0.82); opacity: 0.72; } 50% { transform: scale(1); opacity: 1; } }
.colony__hub-label { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: color-mix(in oklab, var(--color-bg) 58%, var(--color-secondary)); white-space: nowrap; }

.colony__card {
  position: absolute; width: 168px; z-index: 2; background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-s); box-shadow: var(--shadow-raised); overflow: hidden;
  animation: colony-card-in var(--duration-slow) var(--ease-out) both;
}
@keyframes colony-card-in { from { opacity: 0; transform: translateY(var(--motion-travel)) scale(0.94); } }

.colony__card-bar { background: var(--color-bg); padding: 4px 7px; font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); border-bottom: 1px solid var(--color-border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.colony__card-body { padding: var(--space-3); display: flex; flex-direction: column; gap: 4px; }
.colony__card-title { font-family: var(--font-body); font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--color-text); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.colony__card-date { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); }

/* The newest card's title carries the statement-band's own display register (operator rec 3, verbatim "let the
   newest card carry its date as the headline fact") -- the real dated fact reads as the page's proof claim, not
   incidental card metadata. Title moves to the display face at a heavier weight for the same reason.
   DATE SIZE CORRECTED (13.10 NOT GO round 2, queen dispatch 2026-09-03T010500Z-662, defect 4a): the prior pass
   also bumped `.colony__card-date` up to --text-h4 for this one card, which the operator's own full-page render
   read as visibly larger than the other three cards' dates -- a real type-size inconsistency across four cards
   that are otherwise the same shape. Fixed by matching the date's SIZE to the other three cards (--text-caption,
   same as the base `.colony__card-date` rule above); the colour + weight distinction that marks this card as the
   newest stays, since that reads as intentional emphasis rather than a mismatch, and the operator named "type
   size" specifically. */
.colony__card--new { border-color: var(--color-secondary); border-width: 1.5px; }
.colony__card--new .colony__card-bar { background: color-mix(in oklab, var(--color-secondary) 14%, var(--color-surface)); color: var(--color-secondary); }
.colony__card--new .colony__card-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-small); line-height: var(--leading-small); }
.colony__card--new .colony__card-date { color: var(--color-secondary); font-weight: var(--weight-medium); }

.colony__card--a { left: 0; top: 0; animation-delay: 380ms; }
.colony__card--b { right: 0; top: 0; animation-delay: 420ms; }
.colony__card--c { left: 0; bottom: 0; animation-delay: 460ms; }
.colony__card--new { right: 0; bottom: 0; animation-delay: 520ms; }

.colony__count { font-family: var(--font-mono); font-size: var(--text-caption); color: color-mix(in oklab, var(--color-bg) 70%, var(--color-secondary)); margin: var(--space-3) 0 0; }
.colony__count strong { font-weight: var(--weight-medium); color: var(--color-bg); font-variant-numeric: tabular-nums; }

/* Reduced motion: every entrance delay zeroes (same technique F1870 already used on `.fan-card` -- a 0ms
   animation with a leftover delay would otherwise flash the pre-entrance state); the breath STOPS, not just
   speeds up, matching `.live-dot`'s own reduced-motion override -- a continuous decorative pulse is exactly
   the kind of non-essential motion `prefers-reduced-motion` exists to remove. Every selector below is listed
   individually at the same specificity as the rule it overrides (1 class each) so the later position in this
   file, not a specificity trick, is what wins -- same convention the base entrance rules above already rely on. */
@media (prefers-reduced-motion: reduce) {
  .colony__thread, .colony__thread--new,
  .colony__hub,
  .colony__card--a, .colony__card--b, .colony__card--c, .colony__card--new {
    animation-delay: 0ms;
  }
  .colony__hub-dot { animation: none; opacity: 0.85; transform: none; }
}

/* Desktop scale (operator rec 1, verbatim "make the colony the hero's right half at twice the size"): only
   inside `.hero-grid__signature` (80-homeregister.css) -- the base `.colony` above stays at its original F1872
   size for any future non-grid context. Gated to the SAME `min-width: 720px` breakpoint the mobile block below
   already uses, deliberately -- an ungated override here would out-specificity the mobile block's `.colony`
   rule (two classes beats one) regardless of viewport, since CSS specificity does not know about media queries.
   Width and height cannot both literally double (a two-column half of a 1160px container has roughly 500-550px
   to work with, not 1200px). A first pass at height:620px (a literal ~1.8x) rendered with a large dead gap in
   the middle of the box -- the four small corner cards do not fill that much vertical room, so the extra height
   just became empty space, not visual weight (caught by screenshot, not assumed). Settled on height:460px
   (~1.35x) plus every card growing ~1.3x (168px -> 224px) and the newest card's own type growing further still
   (below) -- named here plainly as the real, deliberate interpretation of "twice the size": the combination of
   a dedicated half-hero column, larger cards, and headline-weight newest-card type reads as roughly doubled
   prominence without the literal-height approach's wasted middle, not a silent shortfall. */
@media (min-width: 720px) {
  .hero-grid__signature .colony { max-width: none; width: 100%; height: 460px; margin: 0; }
  /* Percentage, not a fixed px, and for a real reason: a fixed 224px card (this box's own width at a wide
     1280px viewport) real-overflowed into its sibling card at 768px, where the grid COLUMN itself is only
     ~300-330px wide (a 768px viewport minus wrap padding and the hero-grid gap, halved) -- two fixed 224px
     cards do not fit side by side in a ~320px column, and position:absolute cards do not wrap or shrink on
     their own (caught by screenshot at 768, not assumed safe from the 1280 render alone). `clamp()` against the
     card's own containing block (`.colony`, itself 100% of the grid column) keeps every card proportional to
     whatever column width the viewport actually gives it, capped at the same 224px the 1280 render was tuned
     against and floored at 130px so text stays legible at the narrowest width this rule still applies to
     (720px, just above the mobile breakpoint where the layout changes shape entirely, below). */
  .hero-grid__signature .colony__card { width: clamp(130px, 42%, 224px); }
}

@media (max-width: 719px) {
  .colony { max-width: 100%; height: auto; display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-6); }
  .colony__threads, .colony__hub { display: none; }
  .colony__card { position: static; width: 100%; }
  .colony__card-body { padding: var(--space-3) var(--space-4); }
  .colony__card-title { -webkit-line-clamp: 2; }
}

/* 90-homeledger.css -- the homepage's own Thesis B register (corolla, homepage r2, queen dispatch
   2026-09-05T225300Z-849): the dated ledger as the hero, a portrait territory-survey inset, a static
   "recently claimed" strip below the fold. This page is dark SITEWIDE via `[data-theme="dark"]` on
   `<html>` -- every class below is written against the semantic tokens directly (--color-text, not
   --color-bg-as-foreground), so it is correct under dark theme with no special-casing. (Historical note,
   2026-09-08 dispatch -1035: 80-homeregister.css's `.band--ink`/`.split-card__half--ink` used to be a
   FIXED-token dark slab distinct from the page theme; that trick is retired -- `.band--ink` is now an
   ordinary themed surface too, so there is no longer a double-invert risk to guard against here, though
   this file's own sections still never combine with it.) Scoped to the homepage's own sections only;
   every other PC1 pillar page (how-it-works, packages, etc.) is untouched until corolla's round 3 (-848)
   lands its own composed register for that class. */

/* .ledger-hero is now a plain wrapper, not a grid container (Unit 2, dispatch -1070): the two-column split
   it used to own directly (copy / territory panel) is superseded by `.hero-grid` (80-homeregister.css),
   which openerHero() now renders for this section (copy / ledger figures). `.ledger-hero` survives only to
   scope the ledger-row motion selectors below and to give `territoryMapPanel()`'s output (now a full-width
   block after the hero-grid, not a grid column) a shared ancestor. */
.ledger-hero { display: block; }
.ledger-hero__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); }
.ledger-hero__lede { font-size: 1.125rem; line-height: 1.6; color: var(--color-text-soft); max-width: 48ch; margin: var(--space-4) 0 0; }
/* territoryMapPanel() no longer sits inside a shared grid with the copy column (Unit 2, -1070) -- give it
   its own top margin and a capped width so the portrait map doesn't stretch full-bleed under the hero. */
.territory-panel { margin-top: var(--space-6); max-width: 420px; }

.ledger { display: flex; flex-direction: column; border-top: 1px solid var(--color-border); margin-top: var(--space-1); }
.ledger-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-5); padding: var(--space-4) 0; border-bottom: 1px solid var(--color-border); }
.ledger-row:last-child { border-bottom: none; }
.ledger-fig { font-family: var(--font-mono); font-weight: var(--weight-medium); font-size: 2.25rem; line-height: 1; color: var(--color-text); font-variant-numeric: tabular-nums; }
.ledger-fig--accent { color: var(--color-primary); }
.ledger-fig--date { font-size: 1.35rem; color: var(--color-secondary); }
.ledger-detail { font-size: var(--text-small); color: var(--color-text-soft); text-align: right; }
.ledger-detail small { display: block; font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); margin-top: 2px; }

.ledger-cta-row { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
/* Clearance from the lede paragraph above (operator walk finding, dispatch -1083, 2026-09-10): openerHero()
   assembles the hero-grid copy column as h1 + kicker + `.ledger-hero__lede` (a <p>) + this row (a plain
   <div>), so 00-base.css's `p + p { margin-top: var(--space-4) }` idiom -- the rule that already spaces every
   other case's `<p class="cta-row">` off its preceding `<p class="prose">` -- never fires here, because a div
   is not a p. That left literally 0px between the lede's text baseline and the CTA buttons at every viewport,
   worst at the narrow/stacked breakpoint (80-homeregister.css's `.hero-grid` collapses to one column under
   720px) where the operator caught it live on pc1 (next.livingwebsites.ca/pc1/). Fixed with the same adjacent-
   sibling idiom, same token value the rest of the kit already uses for this exact lede-to-CTA gap, scoped to
   only the lede->row adjacency so the OTHER `.ledger-cta-row` caller (`.close-band`'s own flex row, which
   already gets clearance from its sibling `--space-8` flex gap) is untouched. */
.ledger-hero__lede + .ledger-cta-row { margin-top: var(--space-4); }

/* Same defect class as the F2377 fix immediately above, found by the rendered-gap probe this dispatch built
   (scripts/rebuild-opener-gap-probe.mjs), not by a fresh operator walk: on PC2 kind 'problem'/'hub' opener
   pages, `case 'problem':`/`case 'intro':` (scripts/rebuild-render-class.mjs) append `.pc2-stat-rail` and
   `.pick__disclosure-band` (both plain <div>s) as DOM-adjacent siblings after the opener's own
   `<p class="prose">` lede (or after each other, on 'intro'/hub records that render both a stat rail and a
   trailing prose paragraph) -- the same "a <div> sibling after a <p> never matches `p + p`" gap, just with a
   different pair of classes. 58 real zero-gap pairs measured across 29 live pages (/pc2/picks/, every
   /pc2/picks/best-... leaf page, and the PC2 hub) before this fix; 0 after. Same fix shape: named adjacent-sibling
   rules, same `--space-4` token the rest of this rhythm class already uses, scoped to exactly the pairs the
   render module actually produces (no wildcard `div + div` that could reflow an unrelated future pairing). */
.prose + .pc2-stat-rail,
.pc2-stat-rail + .prose,
.prose + .pick__disclosure-band,
.pc2-stat-rail + .pick__disclosure-band { margin-top: var(--space-4); }

.territory-panel { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-m); padding: var(--space-5); position: relative; min-height: 400px; display: flex; flex-direction: column; height: 100%; }
.territory-panel__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin-bottom: var(--space-3); }
.territory-panel__map { flex: 1; width: 100%; min-height: 0; }
.territory-panel__list { display: none; }
.territory-panel__caption { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); line-height: 1.55; margin-top: var(--space-3); }

/* Ledger-hero motion signature (queen dispatch 2026-09-08T034259Z-1017, closing F2309's diagnosed gap:
   corolla's r2 token block specced a real one-time entrance -- staggered ledger-figure rise, SVG thread-draw,
   flag-plant -- that had never been wired into the rebuild pipeline). Reuses brand/components/81-
   alivesignature.css's ALREADY-RATIFIED motion tokens verbatim (480ms --duration-slow, cubic-bezier(.16,1,.3,1)
   --ease-out, 8px --motion-travel) -- no new duration/easing/travel value is introduced anywhere in this block.
   Same "the animated end-state lives only in the keyframe's `from{}` block" freeze-switch technique
   81-alivesignature.css's own header documents: nothing here sets an un-animated base value, so
   `html[data-freeze-motion] *` (70-motion.css, animation: none !important) and the global
   `@media (prefers-reduced-motion: reduce)` zeroing of --duration-slow/--motion-travel (brand/tokens.css) both
   already revert every element below to its plain, fully-visible, undrawn-line-free base state with no extra
   override -- the explicit reduced-motion block further down only zeroes animation-delay, matching
   81-alivesignature.css's own convention (a 0-duration animation with a leftover delay can still flash the
   pre-entrance state in some engines).
   Scoped entirely to `.ledger-hero`/`.territory-panel`, which only ever render on the homepage's own
   `ledger-hero` section (kind 'home', data-section="ledger-hero" data-signature="") -- the ONLY entrance
   recipe in that section, so rebuild-motion-screen.mjs's 12.4 check (no shared entrance recipe across
   DIFFERENT sections) stays clear: `.colony`'s own colony-thread-in/colony-hub-in/colony-card-in recipes
   (81-alivesignature.css) are never rendered on this same page (kind 'home' uses 'ledger-hero', not the older
   aliveSignature ink-hero case), so no name collision is possible today. Fires ONCE on load, never loops --
   the "recently claimed" strip below stays static by design (corolla's own r2 fold note), untouched here. */
.ledger-hero .ledger > .ledger-row {
  animation: ledger-row-rise var(--duration-slow) var(--ease-out) both;
}
@keyframes ledger-row-rise { from { opacity: 0; transform: translateY(var(--motion-travel)); } }
/* Four staggered starts, named verbatim in the dispatch: 340/380/420/460ms. A record with fewer than 4 real
   ledger rows (an honest-degrade case, e.g. missing 28-day impressions/visitors) simply leaves the unused
   nth-child delay unclaimed -- no error, no gap in the sequence that IS rendered. */
.ledger-hero .ledger > .ledger-row:nth-child(1) { animation-delay: 340ms; }
.ledger-hero .ledger > .ledger-row:nth-child(2) { animation-delay: 380ms; }
.ledger-hero .ledger > .ledger-row:nth-child(3) { animation-delay: 420ms; }
.ledger-hero .ledger > .ledger-row:nth-child(4) { animation-delay: 460ms; }

/* Territory-map connector threads: SVG stroke-dasharray draw-in, same technique 81-alivesignature.css's
   `.colony__thread` already uses. 400 is a safe over-estimate of the longest real hub-to-node line this panel's
   360x500 viewBox can produce (diagonal to a corner is ~347 units) -- extra slack beyond the true length is
   harmless (same note as the colony threads' own 300 value). Overrides the inline `stroke-dasharray="4 6"`
   dotted-line presentation attribute the group carries (a CSS class beats a presentation attribute) for the
   duration of the reveal -- after the entrance settles the line reads as one continuous connector rather than
   staying dotted, the same trade corolla's own r2 canvas makes (its `.thread` class does the identical
   override). Decorative geometry only, carries no figure of its own -- unchanged from the panel's existing
   comment on this point. */
.territory-panel__map .thread {
  stroke-dasharray: 400;
  animation: territory-thread-reveal var(--duration-slow) var(--ease-out) both;
}
@keyframes territory-thread-reveal { from { stroke-dashoffset: 400; opacity: 0; } }
/* Small per-thread offsets so all six do not draw in perfectly synchronised (corolla's own canvas staggers
   each thread 0/40/80/100/140/160ms) -- still one entrance, still fires once. Explicit index modifier classes
   (not :nth-of-type) because the flag poles below are ALSO `<path>` siblings in the same <svg> -- nth-of-type
   counts every same-tag sibling regardless of class, which would silently renumber threads once flag-pole
   paths render alongside them. */
.territory-panel__map .thread--0 { animation-delay: 0ms; }
.territory-panel__map .thread--1 { animation-delay: 40ms; }
.territory-panel__map .thread--2 { animation-delay: 80ms; }
.territory-panel__map .thread--3 { animation-delay: 100ms; }
.territory-panel__map .thread--4 { animation-delay: 140ms; }
.territory-panel__map .thread--5 { animation-delay: 160ms; }

/* The three dated indexation flags (real milestones read from data/proof/record.js -- see
   territoryMapPanel()'s comment in scripts/rebuild-render-class.mjs for the exact source). Pole draws in like a
   thread, pennant + dates pop in last, after the ledger rows have mostly settled (440/480/520ms poles,
   520ms flagpop -- corolla's own r2 canvas timing). */
.territory-panel__map .flagpole {
  stroke-dasharray: 40;
  animation: territory-thread-reveal var(--duration-slow) var(--ease-out) both;
}
.territory-panel__map .flagpole--0 { animation-delay: 440ms; }
.territory-panel__map .flagpole--1 { animation-delay: 480ms; }
.territory-panel__map .flagpole--2 { animation-delay: 520ms; }
.territory-panel__map .flagpop {
  animation: ledger-row-rise var(--duration-slow) var(--ease-out) both;
  animation-delay: 520ms;
}

/* Reduced motion: same per-element animation-delay:0 technique 81-alivesignature.css's own reduced-motion
   block uses. --duration-slow/--motion-travel are already globally zeroed (brand/tokens.css), so this only
   needs to stop the delay from staging a flash of the pre-entrance state (fill-mode "both" applies the
   keyframe's `from{}` state for the FULL delay period, even at 0 duration, so a non-zeroed delay still hides
   content for that long under reduced motion).
   `.thread`/`.flagpole`/`.flagpop`'s own per-index delay rules above are class-only (`.territory-panel__map
   .thread--0` etc, 2 classes), so this override (also 2 classes on those selectors) ties on specificity and
   wins by appearing later in the file, matching 81-alivesignature.css's own convention exactly. `.ledger-row`
   is the one exception, caught by measuring the LIVE computed style under `prefers-reduced-motion: reduce`
   (not assumed from the CSS alone): its per-row delay is set via `:nth-child(N)` (needed so plain `.ledger-row`
   divs get different delays with no per-row class from the renderer), which is ONE SELECTOR HEAVIER than this
   override -- a bare specificity tie-break would let `:nth-child(1)`'s 340ms delay win even here. `!important`
   on that one declaration only, not the others, since only it needs to out-rank a heavier same-media selector
   rather than just an equal-specificity one. */
@media (prefers-reduced-motion: reduce) {
  .ledger-hero .ledger > .ledger-row {
    animation-delay: 0ms !important;
  }
  .territory-panel__map .thread,
  .territory-panel__map .flagpole,
  .territory-panel__map .flagpop {
    animation-delay: 0ms;
  }
}

/* Territory page-cluster dots (queen dispatch 2026-09-08T034259Z-1017, unit 1: "each territory drawn as a
   dotted page-cluster, not a single label" -- corolla's r2 canvas draws a scatter of small page-marks inside
   each territory shape, not one dot). Decorative scatter only, same posture as the connector threads above:
   the real, honest count is the text label beside it ("N pages"), never the dot count itself -- a 28-page
   territory (/insights/) cannot legibly draw 28 dots in a ~14px cluster, so the scatter is capped and is never
   read as a literal tally. No new colour token: reuses --color-text-muted, same as the existing node text. */
.territory-panel__map .page-dot { fill: var(--color-text-muted); }

/* Dispatch 1016 fix (2026-09-08): the grid belongs on the section's inner .wrap, not the band
   itself -- the served markup's only child of <section class="band band--surface recent-strip">
   is <div class="wrap">, so a grid on the section made .wrap the sole grid item, landing it in
   the fixed 200px column and stacking the kicker + list inside that narrow width (the "stuck to
   the left, super tall" defect the operator walked into). Scoped to .recent-strip > .wrap, never
   the bare .wrap class, since .wrap is a shared container used unstyled on every other band. */
.recent-strip { background: var(--color-surface); border-bottom: 1px solid var(--color-border); }
.recent-strip > .wrap { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.recent-strip__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); padding-top: 3px; }
.recent-strip__list { display: flex; flex-direction: column; }
.recent-strip__row { display: flex; align-items: baseline; gap: var(--space-4); padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border); }
.recent-strip__row:last-child { border-bottom: none; }
.recent-strip__date { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-secondary); min-width: 88px; }
.recent-strip__title { font-size: var(--text-small); color: var(--color-text-soft); line-height: 1.45; }

.value-register { display: grid; grid-template-columns: 200px repeat(3, minmax(0, 1fr)); gap: var(--space-6); align-items: start; }
.value-register__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); padding-top: 4px; }
.value-register__item { border-inline-start: 1px solid var(--color-border); padding-left: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }
.value-register__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: 1.19rem; color: var(--color-text); }
.value-register__body { font-size: var(--text-small); line-height: 1.6; color: var(--color-text-muted); }

.cost-compare { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-7); }
.cost-compare__col { display: flex; flex-direction: column; gap: var(--space-3); }
.cost-compare__col--muted { opacity: 0.66; }
.cost-compare__col--split { border-inline-start: 1px solid var(--color-border); padding-left: var(--space-7); }
.cost-compare__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); }
.cost-compare__kicker--accent { color: var(--color-primary); }
.cost-compare__headline { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 1.6rem; line-height: 1.15; color: var(--color-text); }
.cost-compare__path { font-family: var(--font-mono); font-size: var(--text-small); color: var(--color-text-muted); line-height: 1.9; }
.cost-compare__path--accent { color: var(--color-primary); }
.cost-compare__body { font-size: var(--text-small); line-height: 1.6; color: var(--color-text-muted); }

.close-band { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); flex-wrap: wrap; }
.close-band__contact { display: flex; flex-direction: column; gap: var(--space-2); }
.close-band__title { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 1.6rem; color: var(--color-text); margin: 0; }
.close-band__kv { font-family: var(--font-mono); font-size: var(--text-small); color: var(--color-text-muted); }

/* -- PC1 pillar 'listing' register/ladder (corolla, PC1 pillar r3, queen dispatch
   2026-09-06T015100Z-871): replaces the class's old .card-grid listing rendering. A plain register
   (title + body, one row per real destination) when items carry no price; a price ladder
   (packages-hub) when they do -- each row's own price at mono display scale, an unpriced tier
   rendering the same dashed empty-slot corolla's token block specifies rather than a blank. -- */
.listing-ladder__heading { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: 1.4rem; color: var(--color-text); margin: 0 0 var(--space-5); }
.listing-ladder__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin: var(--space-6) 0 var(--space-3); }
.listing-ladder { display: flex; flex-direction: column; border-top: 1px solid var(--color-border); }
.listing-ladder__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-2) var(--space-5); padding: var(--space-4) 0; border-bottom: 1px solid var(--color-border); text-decoration: none; color: inherit; }
.listing-ladder__row:hover .listing-ladder__title { color: var(--color-primary); }
.listing-ladder__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: 1.05rem; color: var(--color-text); }
.listing-ladder__body { grid-column: 1 / -1; font-size: var(--text-small); line-height: 1.6; color: var(--color-text-muted); }
.listing-ladder--priced .listing-ladder__row { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; }
.listing-ladder__price { font-family: var(--font-mono); font-weight: var(--weight-medium); font-size: 1.05rem; color: var(--color-secondary); white-space: nowrap; }
.listing-ladder__price-sep { color: var(--color-text-muted); font-weight: var(--weight-regular); }
/* corolla's own token block names a literal #4A3A22 for this border; derived here instead via
   color-mix (this kit is tokens-only, test/brand-components.test.js's own "no raw colour literal"
   gate) -- an ochre-tinted dark border reads the same deliberate "empty, not invented" signal
   without adding a new named token for a single one-off use. */
.listing-ladder__price--empty { color: var(--color-text-muted); border: 1px dashed color-mix(in oklab, var(--color-secondary) 35%, var(--color-bg)); border-radius: var(--radius-s); padding: 2px 10px; }
@media (max-width: 719px) {
  .listing-ladder__row { grid-template-columns: minmax(0, 1fr); }
  .listing-ladder__price { justify-self: start; }
}

@media (max-width: 719px) {
  /* .ledger-hero's own grid-template-columns rule is retired with the base rule above (Unit 2, -1070) --
     the hero-grid it now wraps already collapses to one column below 720px (80-homeregister.css). */
  .territory-panel { min-height: 0; max-width: none; }
  .territory-panel__map { display: none; }
  .territory-panel__list { display: flex; flex-direction: column; }
  .territory-panel__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); padding: var(--space-2) 0; border-bottom: 1px solid var(--color-border); font-family: var(--font-mono); font-size: var(--text-small); }
  .territory-panel__row:last-child { border-bottom: none; }
  .territory-panel__row-label { color: var(--color-text-soft); }
  .territory-panel__row-count { color: var(--color-text-muted); }
  .recent-strip > .wrap, .value-register { grid-template-columns: minmax(0, 1fr); }
  .cost-compare { grid-template-columns: minmax(0, 1fr); }
  .cost-compare__col--split { border-inline-start: none; padding-left: 0; border-top: 1px solid var(--color-border); padding-top: var(--space-5); }
}

/* -- PC2 picks register, corolla r4 (queen dispatch 2026-09-06T022300Z-876): the full-width above-the-fold
   disclosure strip (G7's other half -- the short one-liner COMPONENT_RENDERERS.pick already renders adjacent to
   the first affiliate anchor); the empty-price pill (P6, same dashed-ochre "deliberate absence" pattern as r3's
   .listing-ladder__price--empty); and the plain who-this-isn't-for band (P7: part of the answer, not a warning
   box), same 200px-kicker/1fr-body shape as .recent-strip above. -- */
.pick__disclosure-band { border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border); padding: var(--space-4) 0; display: flex; align-items: baseline; gap: var(--space-5); flex-wrap: wrap; }
.pick__disclosure-band__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-secondary); flex-shrink: 0; }
.pick__disclosure-band p { margin: 0; font-size: var(--text-small); color: var(--color-text-muted); }
.pick__price--empty { font-family: var(--font-mono); font-size: var(--text-caption); color: var(--color-text-muted); border: 1px dashed color-mix(in oklab, var(--color-secondary) 35%, var(--color-bg)); border-radius: var(--radius-s); padding: 2px 8px; white-space: nowrap; }
.pc2-note { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: var(--space-6); align-items: start; padding: var(--space-6) 0; }
.pc2-note__kicker { font-family: var(--font-mono); font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-text-muted); margin: 0; }
.pc2-note__body { font-size: var(--text-small); line-height: 1.6; color: var(--color-text-soft); margin: 0; }
@media (max-width: 719px) {
  .pc2-note { grid-template-columns: minmax(0, 1fr); }
}

/* -- PC3 guides register, corolla r5 (queen dispatch 2026-09-06T031300Z-882): V3 (evidence is a state, not a
   section, and an empty one says why) + V4 (a source renders as publisher, domain, date checked) + V8 (depth is
   shown as depth). Reuses the existing dashed-ochre "deliberate absence" border pattern already built for
   .listing-ladder__price--empty / .pick__price--empty above for the OWED state; the DELIBERATE state is the
   same ochre, solid rather than dashed -- corolla's own distinction, a dashed border means owed, a solid one
   means a decision the page already made and defended. -- */
.evidence-state { border: 1px solid var(--color-border); border-radius: var(--radius-m); padding: var(--space-5); margin-top: var(--space-4); }
.evidence-state--owed { border: 1px dashed color-mix(in oklab, var(--color-secondary) 45%, var(--color-bg)); }
.evidence-state--deliberate { border: 1px solid var(--color-secondary); }
.evidence-state__figure { font-family: var(--font-mono); font-weight: var(--weight-bold); font-size: var(--text-h2); line-height: 1; color: var(--color-secondary); margin: 0; }
.evidence-state__label { font-family: var(--font-mono); font-size: var(--text-small); color: var(--color-text-muted); margin: var(--space-2) 0 var(--space-3); }
/* No border-left accent bar here on purpose -- test/brand-kit-page.test.js's design-tell screen flags a fixed-
   width border-left declaration as a generated-template structural signature (left-stripe-tell); italic +
   quote marks carry the "this is a quoted sentence" signal instead, matching .prose blockquote's own
   border-free pattern one file up (00-base.css) rather than inventing a second quote convention. */
.evidence-state__quote { margin: 0 0 var(--space-3); font-family: var(--font-display); font-style: italic; font-size: var(--text-body); color: var(--color-text-soft); }
.evidence-state__quote::before { content: '\201C'; }
.evidence-state__quote::after { content: '\201D'; }
.evidence-state__aside { font-size: var(--text-small); color: var(--color-text-muted); margin: 0; }

.source-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.source-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3); padding-bottom: var(--space-4); border-bottom: 1px solid var(--color-border); }
.source-row:last-child { border-bottom: none; padding-bottom: 0; }
.source-row__type { font-size: var(--text-caption); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-secondary); flex-shrink: 0; }
.source-row__title { color: var(--color-primary); text-decoration: none; }
.source-row__title:hover { text-decoration: underline; }
.source-row__meta { margin-left: auto; font-size: var(--text-caption); color: var(--color-text-muted); white-space: nowrap; }

/* grid-column: 1 / -1 forces a full-row span (2026-09-06, caught reviewing a real screenshot): .card-grid's own
   auto-fit columns (40-card.css) otherwise place this card in whatever next grid CELL is free -- at wide
   viewports that is beside its own parent, not visually under it, defeating V8's "depth is shown as depth"
   entirely. Spanning the full row guarantees it always renders on its own indented row, directly under
   wherever it falls in reading order (immediately after its real parent, per pillarListing's own item order). */
.card--nested { grid-column: 1 / -1; margin-left: var(--space-6); border-color: transparent; background: transparent; padding-top: var(--space-2); padding-bottom: var(--space-2); }
.card--nested .card__title { font-size: var(--text-body); }
@media (max-width: 719px) {
  .card--nested { margin-left: var(--space-4); }
  .source-row__meta { margin-left: 0; }
}
