/* =====================================================================
   VETS FRANCHISE — site stylesheet

   One file, no preprocessor (the SEO skill forbids a bundler, and
   scripts/contrast-check.mjs reads this file directly in CI before the
   .NET build — a build step would make the gated file an artifact).

   Structure is enforced, not merely agreed:
     - The tokens layer mirrors docs/design-system/_tokens.scss exactly.
       Design/SiteCssTests.cs fails the build on any drift, and on any raw
       hex literal outside this layer.
     - Every component gets a banner comment naming it.

   Surfaces, not selectors, decide text colour. Every dark surface sets the
   --surface-* aliases once (see LAYOUT) and every component reads them, so
   a lede, a breadcrumb or a step description can never render ink-on-green
   because someone forgot to add its selector to a list. Light islands inside
   a dark surface (the lead form, the snapshot card) re-declare the light set.

   Do not add a colour, font, radius or shadow that is not a token.
   ===================================================================== */

@layer tokens, base, layout, components, prose, utilities;

/* =====================================================================
   FONTS — self-hosted (SIL OFL), latin subsets only.
   @font-face sits outside the layers: its descriptors are not cascaded.

   Anton is used for exactly one thing: the two-line uppercase headline
   (h1 and section h2). Everything else, including every sub-heading, card
   title, figure label and button, is Inter. The hero H1 is the LCP element,
   so the fallback is metric-matched to avoid reflow on swap.
   ===================================================================== */
@font-face {
  font-family: 'Anton';
  src: url('/fonts/anton-latin-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2122, U+2212;
}

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-latin-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2122, U+2212;
}

/* Metric-matched fallbacks: what the browser renders during the swap. */
@font-face {
  font-family: 'Anton Fallback';
  src: local('Arial Narrow'), local('Arial');
  size-adjust: 82%;
  ascent-override: 102%;
  descent-override: 22%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Inter Fallback';
  src: local('Segoe UI'), local('Helvetica Neue'), local('Arial');
  size-adjust: 100%;
  ascent-override: 96%;
  descent-override: 24%;
  line-gap-override: 0%;
}

/* =====================================================================
   TOKENS — mirrors docs/design-system/_tokens.scss
   ONE DELIBERATE DEVIATION (decision DD1, 2026-09-22): --color-sand-dim
   is #9A7836 here, not the customer site's #B58E44. At #B58E44 the accent
   headline line on bone is 2.72:1, below the 3:1 large-text floor.
   ===================================================================== */
@layer tokens {
  :root {
    /* ---------- Color: brand ---------- */
    --color-field:        #2A3B2F;   /* field green: primary dark section, scrolled nav */
    --color-field-light:  #3A4D3F;
    --color-field-dark:   #1E2B22;   /* hero base, footer, map panels */
    --color-bone:         #F5F2EC;   /* primary light section background */
    --color-linen:        #ECE7DC;   /* alternate light section */
    --color-white:        #FFFFFF;   /* cards and inputs on bone/linen */
    --color-ink:          #0E1116;   /* text on light; ink sections */
    --color-sand:         #D4A85C;   /* accent on dark: headline accent, eyebrow dot, open map dots */
    --color-sand-dim:     #9A7836;   /* accent headline on light, display sizes only — see DD1 above */
    --color-sand-ink:     #7F6128;   /* sand-toned SMALL text on light, 4.5:1+ */
    --color-flag:         #B5232C;   /* primary conversion buttons only */
    --color-flag-hover:   #971C24;
    --color-signal-open:  #2E8B57;   /* "open territory" status mark only (filled check); never text, never an action */

    /* ---------- Color: text alphas ---------- */
    --color-ink-60:          rgba(14, 17, 22, 0.65);    /* secondary text on light (5.7:1 on bone) */
    --color-ink-40:          rgba(14, 17, 22, 0.42);    /* decorative/meta only, never required text */
    --color-bone-on-dark:    #F5F2EC;
    --color-bone-on-dark-70: rgba(245, 242, 236, 0.75);
    --color-bone-on-dark-50: rgba(245, 242, 236, 0.50); /* meta only on field/ink */
    --color-bone-on-dark-04: rgba(245, 242, 236, 0.04); /* territory map: state fill */
    --color-bone-on-dark-28: rgba(245, 242, 236, 0.28); /* territory map: owner-in-place dot */
    --color-sand-10:         rgba(212, 168, 92, 0.10);  /* territory map: state with an open territory */
    --color-sand-38:         rgba(212, 168, 92, 0.38);  /* territory map: pulse ring on an open dot */
    --color-hairline:        rgba(14, 17, 22, 0.12);
    --color-hairline-dark:   rgba(245, 242, 236, 0.18);
    --color-star:            #FBBC05;                    /* review stars only */

    /* ---------- Type families ---------- */
    --font-display: 'Anton', 'Anton Fallback', 'Oswald', 'Impact', sans-serif;  /* two-line headlines only */
    --font-body:    'Inter', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;

    /* ---------- Body sizes (px, fixed) ---------- */
    --text-xs: 13px;   /* eyebrows, labels, captions, legal */
    --text-sm: 15px;   /* secondary body, nav links, card text */
    --text-md: 17px;   /* body */
    --text-lg: 19px;   /* lede */

    /* ---------- Headline tiers (desktop; tablet/mobile overridden below) ---------- */
    --text-display:     84px;  /* full-width hero H1 */
    --text-hero-split:  56px;  /* H1 beside a card, and every interior page H1 */
    --text-section:     48px;  /* section H2 */
    --text-article:     44px;  /* post/guide H1 */
    --text-2xl:         30px;  /* Inter sub-headings: prose H2, panel titles */
    --text-xl:          22px;  /* Inter card titles, prose H3, FAQ question */
    --text-figure-lg:   48px;  /* count boxes */
    --text-figure-md:   36px;  /* floating stat */
    --text-figure-sm:   24px;  /* snapshot values */

    /* ---------- Line height / tracking ---------- */
    --lh-display: 1.0;
    --lh-heading: 1.15;
    --lh-snug:    1.3;
    --lh-body:    1.55;
    --lh-prose:   1.7;
    --ls-display: 0.01em;
    --ls-eyebrow: 0.14em;
    --ls-button:  0.01em;
    --ls-label:   0.06em;
    --ls-tight:  -0.015em;    /* Inter sub-headings */

    /* ---------- Spacing ---------- */
    --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
    --space-5: 24px; --space-6: 32px; --space-7: 48px; --space-8: 64px;
    --space-9: 96px; --space-10: 128px;

    /* ---------- Section rhythm ---------- */
    --section-pad-sm: 48px;
    --section-pad-md: 76px;
    --section-pad-lg: 104px;

    /* ---------- Layout ---------- */
    --container-max:     1240px;
    --container-padding: clamp(20px, 5vw, 48px);
    --container-narrow:  760px;   /* forms, FAQ, short prose */
    --container-prose:   820px;   /* long-form, ~75 characters per line */
    --nav-height:          80px;   /* ONE height, scrolled or not — see the site-nav component */

    /* ---------- Shape ---------- */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 16px;
    --radius-pill: 999px;
    --border-thin: 1px;
    --border-thick: 2px;

    /* ---------- Elevation ---------- */
    --shadow-sm:  0 1px 2px rgba(14, 17, 22, 0.06);
    --shadow-md:  0 8px 24px rgba(14, 17, 22, 0.08);
    --shadow-lg:  0 24px 60px rgba(14, 17, 22, 0.18);
    --shadow-nav: 0 4px 20px rgba(14, 17, 22, 0.25);

    /* ---------- Motion ---------- */
    --dur-fast: 180ms;
    --dur-base: 320ms;
    --dur-slow: 480ms;
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

    /* ---------- Textures ---------- */
    --texture-camo-url:      url('/img/textures/camo-normal.webp');
    --texture-camo-size:     600px 600px;
    --texture-camo-opacity:  0.14;
    --texture-grain-opacity: 0.16;

    /* ---------- Focus (the reference designs define none) ---------- */
    --focus-ring-dark:  0 0 0 3px var(--color-sand);   /* on field / ink / video */
    --focus-ring-light: 0 0 0 3px var(--color-field);  /* on bone / linen / white */

    /* ---------- Z-index ---------- */
    --z-nav: 100;
    --z-mobile-menu: 200;
  }

  /* Breakpoints match the live build: 1199 / 991 / 767 */
  @media (max-width: 991px) {
    :root {
      --section-pad-md: 64px;
      --section-pad-lg: 84px;
      --text-display:    60px;
      --text-hero-split: 46px;
      --text-section:    40px;
      --text-article:    36px;
      --text-2xl:        27px;
      --nav-height:      68px;
    }
  }

  @media (max-width: 767px) {
    :root {
      --section-pad-sm: 36px;
      --section-pad-md: 52px;
      --section-pad-lg: 64px;
      --text-display:    44px;
      --text-hero-split: 40px;
      --text-section:    34px;
      --text-article:    30px;
      --text-2xl:        25px;
      --text-xl:         20px;
      --text-figure-lg:  36px;
      --text-figure-sm:  20px;
    }
  }
}

/* =====================================================================
   BASE
   ===================================================================== */
@layer base {
  *, *::before, *::after { box-sizing: border-box; }

  /* The hidden attribute must win over a component's own display, or a filtered-out card that
     is display:flex stays on screen. */
  [hidden] { display: none !important; }

  html {
    -webkit-text-size-adjust: 100%;
    scroll-padding-top: calc(var(--nav-height) + var(--space-4));
    /* The reduced-motion block below forces this back to auto. */
    scroll-behavior: smooth;
  }

  body {
    margin: 0;
    background: var(--color-bone);
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: var(--text-md);
    line-height: var(--lh-body);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 400; }
  p, ul, ol, figure, blockquote { margin: 0; }
  img, svg, video { max-width: 100%; height: auto; display: block; }

  a { color: inherit; }

  /* Every interactive element gets a visible ring. Dark surfaces re-declare
     --focus-ring on themselves so the ring inverts automatically. */
  :focus-visible {
    outline: none;
    box-shadow: var(--focus-ring, var(--focus-ring-light));
  }

  button, input, select, textarea { font: inherit; color: inherit; }

  /* == component: skip-link == */
  .skip {
    position: absolute;
    left: -9999px;
    z-index: calc(var(--z-mobile-menu) + 1);
  }
  .skip:focus {
    left: var(--space-4);
    top: var(--space-4);
    background: var(--color-white);
    color: var(--color-ink);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-pill);
    box-shadow: var(--shadow-md);
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

/* =====================================================================
   LAYOUT — containers, sections and the surface contract.
   ===================================================================== */
@layer layout {
  /* == component: surface ==
     The light set is the default. Every dark surface overrides it in one
     place; every component reads from it. A component never names a
     colour token for text directly unless it means that exact colour on
     every surface (the flag button, the review star). */
  :root {
    --surface-text:         var(--color-ink);
    --surface-text-muted:   var(--color-ink-60);
    --surface-text-faint:   var(--color-ink-40);
    --surface-accent:       var(--color-sand-ink);   /* small accent text: eyebrow lead, links, icons */
    --surface-accent-display: var(--color-sand-dim); /* the second headline line */
    --surface-hairline:     var(--color-hairline);
    --surface-hairline-strong: rgba(14, 17, 22, 0.24);
    --surface-tint:         rgba(14, 17, 22, 0.04);   /* icon wells, subtle fills */
    --surface-card:         var(--color-white);
    --surface-dot:          var(--color-sand-ink);
  }

  .section--field,
  .section--field-camo,
  .section--ink,
  .hero,
  .final-cta,
  .footer,
  .nav,
  .mobile-menu,
  .panel--you,
  .panel--field,
  .inline-cta,
  .map--compact,
  .count {
    --surface-text:         var(--color-bone-on-dark);
    --surface-text-muted:   var(--color-bone-on-dark-70);
    --surface-text-faint:   var(--color-bone-on-dark-50);
    --surface-accent:       var(--color-sand);
    --surface-accent-display: var(--color-sand);
    --surface-hairline:     var(--color-hairline-dark);
    --surface-hairline-strong: rgba(245, 242, 236, 0.36);
    --surface-tint:         rgba(245, 242, 236, 0.06);
    --surface-card:         var(--color-field-dark);
    --surface-dot:          var(--color-sand);
    --focus-ring:           var(--focus-ring-dark);
    color: var(--surface-text);
  }

  /* Light islands inside a dark surface. */
  .form,
  .snapshot,
  .panel--us,
  .stat-grid,
  .loc-card,
  .author-card,
  .post-card,
  .takeaways,
  .fdd-lookup {
    --surface-text:         var(--color-ink);
    --surface-text-muted:   var(--color-ink-60);
    --surface-text-faint:   var(--color-ink-40);
    --surface-accent:       var(--color-sand-ink);
    --surface-accent-display: var(--color-sand-dim);
    --surface-hairline:     var(--color-hairline);
    --surface-hairline-strong: rgba(14, 17, 22, 0.24);
    --surface-tint:         rgba(14, 17, 22, 0.04);
    --surface-card:         var(--color-white);
    --surface-dot:          var(--color-sand-ink);
    --focus-ring:           var(--focus-ring-light);
    color: var(--surface-text);
  }

  /* == component: container == */
  .container {
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-padding);
  }
  .container--narrow { max-width: calc(var(--container-narrow) + var(--container-padding) * 2); }
  .container--prose  { max-width: calc(var(--container-prose)  + var(--container-padding) * 2); }

  /* == component: section == */
  .section { padding-block: var(--section-pad-md); position: relative; }
  .section--compact  { padding-block: var(--section-pad-sm); }
  /* The answer card is a raised card between two bands, so it gets a little more air than a
     compact section of plain content: pad-sm plus 16, which scales with the token per breakpoint. */
  .section--compact:has(> .container > .answer) { padding-block: calc(var(--section-pad-sm) + var(--space-4)); }
  .section--showcase { padding-block: var(--section-pad-lg); }

  .section--bone  { background: var(--color-bone); }
  .section--linen { background: var(--color-linen); }
  .section--field, .section--field-camo { background: var(--color-field); }
  .section--ink { background: var(--color-ink); }

  /* Adjacent light sections get a hairline so the rhythm reads without a colour change. */
  .section--bone + .section--bone,
  .section--linen + .section--linen { border-top: var(--border-thin) solid var(--color-hairline); }

  /* The camo texture asset has not been delivered (the token points at a file
     that does not exist). Until it lands the element renders nothing, rather
     than a 404 per page. It stays in the markup so the section keeps its
     shape when the texture arrives. */
  .section__camo { display: none; }
  .section > .container { position: relative; }
}

/* =====================================================================
   COMPONENTS
   ===================================================================== */
@layer components {

  /* == component: icon == */
  .icon {
    width: 1em;
    height: 1em;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* == component: icon-well ==
     A framed icon: the one shape every icon on the site sits in, so a
     point list, a snapshot row and a panel tag all read as one system. */
  .icon-well {
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    flex: none;
    border-radius: var(--radius-md);
    border: var(--border-thin) solid var(--surface-hairline);
    background: var(--surface-tint);
    color: var(--surface-accent);
  }
  .icon-well .icon { width: 20px; height: 20px; }
  .icon-well--sm { width: 36px; height: 36px; }
  .icon-well--sm .icon { width: 18px; height: 18px; }

  /* == component: eyebrow ==
     One per section, never on a card. */
  .eyebrow {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: var(--text-xs);
    font-weight: 500;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--surface-text-muted);
    margin-bottom: var(--space-5);
  }
  .eyebrow b { font-weight: 600; color: var(--surface-accent); }
  .eyebrow__dot {
    position: relative;
    width: 6px;
    height: 6px;
    flex: none;
    border-radius: var(--radius-pill);
    background: var(--surface-dot);
  }
  .eyebrow__dot--pulse::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: inherit;
    animation: vets-pulse 2s var(--ease-out) infinite;
  }
  @keyframes vets-pulse {
    from { transform: scale(1);   opacity: 0.4; }
    to   { transform: scale(2.4); opacity: 0; }
  }

  /* == component: split-headline ==
     Anton, uppercase, stacked in two lines; the accent is always a WHOLE line,
     never a single word. The only place the display face is used. */
  .headline {
    font-family: var(--font-display);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: var(--ls-display);
    line-height: var(--lh-display);
    text-wrap: balance;
  }
  .headline__line { display: block; }
  .headline__accent { color: var(--surface-accent-display); }

  .headline--display    { font-size: var(--text-display); }
  .headline--hero-split { font-size: var(--text-hero-split); }
  .headline--section    { font-size: var(--text-section); }
  .headline--article    { font-size: var(--text-article); line-height: var(--lh-heading); }

  /* The card tier is a sub-heading, not a headline: Inter, sentence case. */
  .headline--card {
    font-family: var(--font-body);
    font-weight: 700;
    font-size: var(--text-xl);
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug);
    text-transform: none;
  }

  /* == component: subhead ==
     Inter sub-headings for cards, panels, steps and forms. */
  .subhead {
    font-weight: 700;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug);
    font-size: var(--text-xl);
  }
  .subhead--lg { font-size: var(--text-2xl); line-height: var(--lh-heading); }
  .subhead--sm { font-size: var(--text-lg); }

  /* == component: lede == */
  .lede {
    font-size: var(--text-lg);
    line-height: var(--lh-body);
    max-width: 600px;
    color: var(--surface-text-muted);
    margin-top: var(--space-5);
    text-wrap: pretty;
  }

  /* == component: section-header == */
  .section-header { max-width: 720px; margin-bottom: var(--space-6); }
  /* A header with a lede spans the container: eyebrow and headline on the left, the lede on the
     right, aligned to the headline's baseline. Stacking all three in a 720px column left the right
     half of every section empty on a 1240px container, which read as unfinished. */
  .section-header:not(.section-header--centered):has(> .lede) {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--space-8);
    align-items: end;
  }
  .section-header:not(.section-header--centered):has(> .lede) > * { grid-column: 1; }
  .section-header:not(.section-header--centered):has(> .lede) > .lede {
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: end;
    margin: 0;
    padding-left: var(--space-6);
    border-left: var(--border-thick) solid var(--surface-accent);
  }
  @media (max-width: 991px) {
    .section-header:not(.section-header--centered):has(> .lede) { display: block; max-width: 720px; }
    .section-header:not(.section-header--centered):has(> .lede) > .lede {
      margin-top: var(--space-5); padding-left: var(--space-5);
    }
  }
  .section-header--centered { margin-inline: auto; text-align: center; }
  .section-header--centered .eyebrow { justify-content: center; }
  .section-header--centered .lede { margin-inline: auto; }

  /* == component: button ==
     Flag red means "take the primary action" and is never decoration. */
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 14px var(--space-5);
    border: var(--border-thin) solid transparent;
    border-radius: var(--radius-pill);
    background: none;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                color var(--dur-fast) var(--ease-out);
  }
  .button__label {
    font-size: var(--text-sm);
    font-weight: 600;
    letter-spacing: var(--ls-button);
    line-height: 1.2;
  }
  .button .icon { width: 16px; height: 16px; transition: transform var(--dur-fast) var(--ease-out); }
  .button:hover .icon { transform: translateX(3px); }

  .button--primary { background: var(--color-flag); color: var(--color-white); }
  .button--primary:hover { background: var(--color-flag-hover); }

  .button--secondary { border-color: var(--surface-hairline-strong); color: var(--surface-text); }
  .button--secondary:hover { border-color: var(--surface-text); }

  .button--ghost { border-color: var(--surface-hairline-strong); color: var(--surface-text); }
  .button--ghost:hover { border-color: var(--surface-text); background: var(--surface-tint); }

  .button--sm { padding: 10px var(--space-4); }
  .button--lg { padding: 18px var(--space-6); }
  .button--full { width: 100%; }

  /* == component: text-link == */
  .text-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--surface-text);
    text-decoration: none;
    border-bottom: var(--border-thick) solid var(--surface-accent);
    padding-bottom: 2px;
    transition: color var(--dur-fast) var(--ease-out);
  }
  .text-link:hover { color: var(--surface-accent); }
  .text-link .icon { width: 15px; height: 15px; }

  /* == component: related == the "Keep reading" links at the foot of an article. */
  .related__list { display: grid; gap: var(--space-4); margin-top: var(--space-4); list-style: none; padding: 0; }

  /* == component: breadcrumb == */
  .breadcrumb { font-size: var(--text-xs); color: var(--surface-text-muted); }
  .breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
                   list-style: none; padding: 0; margin: 0; }
  .breadcrumb li { display: flex; align-items: center; gap: 10px; }
  .breadcrumb li + li::before { content: ""; width: 3px; height: 3px; border-radius: 50%;
                                background: currentColor; opacity: 0.6; }
  .breadcrumb a { text-decoration: none; }
  .breadcrumb a:hover { color: var(--surface-text); }
  .breadcrumb [aria-current="page"] { color: var(--surface-accent); font-weight: 500; }

  /* == component: status-badge == */
  .status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 6px var(--space-4);
    border: var(--border-thin) solid var(--surface-hairline-strong);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--surface-text);
    margin-bottom: var(--space-5);
  }
  .status__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
  .status--open      { color: var(--surface-accent); border-color: currentColor; }
  .status--in-discussion { color: var(--surface-text); border-color: var(--surface-hairline-strong); }
  .status--claimed   { color: var(--surface-text-muted); }
  .status--operating { border-color: transparent; background: var(--surface-tint); }

  /* == component: tag == */
  .tag {
    display: inline-flex;
    padding: 6px var(--space-4);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
  }

  /* == component: point-list ==
     Each point is a framed icon (or, with no icon, a sand bar) beside a bold
     title and a muted line. Icons sit on the first line of the title. */
  .points { list-style: none; padding: 0; margin: 0; }
  .point {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-5);
    align-items: start;
    padding-block: var(--space-5);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .point:last-child { border-bottom: var(--border-thin) solid var(--surface-hairline); }
  .point__marker { width: 4px; align-self: stretch; border-radius: var(--radius-pill); background: var(--surface-dot); }
  .point__title { font-size: var(--text-md); font-weight: 700; letter-spacing: var(--ls-tight);
                  line-height: var(--lh-snug); max-width: 62ch; }
  .point__title a { text-decoration: none; }
  .point__title a:hover { color: var(--surface-accent); }
  .point__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-2);
                 max-width: 78ch; }
  /* A cited figure gets its own line under the title. Inline, a resolved claim pushes the title
     into a second line and an unresolved one (a dev chip) wraps it badly. */
  .point__value { display: block; font-size: var(--text-lg); font-weight: 700;
                  letter-spacing: var(--ls-tight); color: var(--surface-accent); margin-top: var(--space-1); }
  .point__value:empty { display: none; }
  .point .icon-well { margin-top: -6px; }

  /* Two-up grid of points for pages with six or more. */
  .points--grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--space-8); }
  .points--grid .point:last-child { border-bottom: none; }
  .points--grid .point:nth-last-child(2):nth-child(odd) { border-bottom: none; }

  /* == component: count-box == */
  .count {
    padding: var(--space-6);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-lg);
    background: var(--color-field-dark);
  }
  .count__figure {
    font-family: var(--font-display);
    font-size: var(--text-figure-lg);
    line-height: 1;
    color: var(--surface-accent);
  }
  .count__label {
    font-size: var(--text-xs);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--surface-text-muted);
    margin-top: var(--space-3);
  }

  /* == component: stat-grid ==
     Every figure carries a superscript keyed to the source-footnotes block.
     No icons: the number is the content. */
  .stat-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--border-thin);
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-lg);
    background: var(--color-hairline);
    overflow: hidden;
  }
  .stat { padding: var(--space-6); background: var(--color-white); }
  .stat__figure { font-family: var(--font-display); font-size: var(--text-figure-md); line-height: 1; }
  .stat__label { font-size: var(--text-sm); font-weight: 600; margin-top: var(--space-3); }
  .stat__compare { font-size: var(--text-xs); color: var(--color-ink-60); margin-top: var(--space-2); }
  .stat sup { font-size: 0.5em; vertical-align: super; color: var(--color-ink-60); margin-left: 2px; }

  /* == component: territory-map ==
     Static inline SVG from Datasets/generated/us-map.json (scripts/build-map.mjs);
     no runtime d3. Lives on a dark surface — states are 4% bone — and reads the
     dark surface aliases. The selected dot is sand with a bone ring, NOT flag
     red: §7 says red never decorates, and the panel's "Ask about this market"
     button is the action. Every open dot is a real link; the panel and the
     arrow keys are enhancement. */
  .map { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-6); align-items: start; }
  .map__frame { position: relative; }
  .map__svg { display: block; width: 100%; height: auto; }
  .map__state {
    fill: var(--color-bone-on-dark-04);
    stroke: var(--color-hairline-dark);
    stroke-width: 0.8;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
    transition: fill var(--dur-base) var(--ease-out);
  }
  .map__state.is-active { fill: var(--color-sand-10); }
  .map--focus .map__state:not(.is-focus) { stroke: var(--color-bone-on-dark-04); }
  .map__dot { fill: var(--color-sand); }
  .map__dot--claimed { fill: var(--color-bone-on-dark-28); }
  .map__dot--operating { fill: var(--color-bone-on-dark-50); }
  .map__pulse {
    fill: none;
    stroke: var(--color-sand-38);
    stroke-width: 1.5;
    transform-box: fill-box;
    transform-origin: center;
    animation: map-pulse 2.4s var(--ease-out) infinite;
  }
  .map__dot-link { cursor: pointer; }
  .map__dot-link:focus { outline: none; }
  .map__dot-link:hover .map__dot,
  .map__dot-link:focus-visible .map__dot,
  .map__dot-link.is-selected .map__dot { stroke: var(--color-bone-on-dark); stroke-width: 2; }
  .map__dot-link.is-filtered-out,
  .map__dot--claimed.is-filtered-out,
  .map__dot--operating.is-filtered-out { display: none; }
  .map__legend {
    display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
    list-style: none; padding: 0; margin: var(--space-4) 0 0;
    font-size: var(--text-xs); font-weight: 500; letter-spacing: var(--ls-label); text-transform: uppercase;
    color: var(--surface-text-muted);
  }
  .map__legend li { display: inline-flex; align-items: center; gap: var(--space-2); }
  .map__swatch { width: 10px; height: 10px; border-radius: 50%; background: var(--color-sand); }
  .map__swatch--claimed { background: var(--color-bone-on-dark-28); }
  .map__swatch--operating { background: var(--color-bone-on-dark-50); }
  .map__panel {
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--surface-card);
    border: var(--border-thin) solid var(--surface-hairline);
  }
  .map__panel-label {
    font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-eyebrow); text-transform: uppercase;
    color: var(--surface-accent); margin: 0;
  }
  .map__panel-title {
    font-size: var(--text-xl-desktop); font-weight: 700; letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug); margin: var(--space-2) 0 0;
  }
  .map__panel .status { margin: var(--space-4) 0 0; }
  .map__panel-meta { font-size: var(--text-sm); color: var(--surface-text-muted); margin: var(--space-3) 0 0; line-height: var(--lh-body); }
  .map__panel-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: var(--space-5) 0 0; }
  @keyframes map-pulse {
    0%   { transform: scale(0.6); opacity: 1; }
    100% { transform: scale(2.2); opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .map__pulse { animation: none; opacity: 0.7; }
  }
  @media (max-width: 991px) {
    .map { grid-template-columns: 1fr; }
  }

  /* == component: filter-pills ==
     Plain buttons; without JavaScript every card is simply shown. */
  .filter-pills { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .pill {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: 8px var(--space-4);
    border-radius: var(--radius-pill);
    border: var(--border-thin) solid var(--surface-hairline-strong);
    background: transparent;
    color: var(--surface-text);
    font: inherit; font-size: var(--text-sm); font-weight: 500;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
  }
  .pill:hover { border-color: var(--surface-text); }
  .pill[aria-pressed="true"] { background: var(--surface-text); color: var(--surface-card); border-color: var(--surface-text); }
  .pill:focus-visible { outline: none; box-shadow: var(--focus-ring); }

  /* == component: nearby-markets ==
     The closest open territories to a metro: a regional crop of the static
     territory map, with dashed links from this metro to each neighbour, beside
     a card per neighbour. On a field surface so the map reads the same as the
     national one; the cards are light islands. Distances are straight-line and
     the caption says so. */
  .nearby { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--space-6); align-items: start; }
  .nearby--no-map { grid-template-columns: 1fr; }
  .nearby__map { margin: 0; }
  .nearby__svg {
    display: block; width: 100%; height: auto; aspect-ratio: 4 / 3;
    border-radius: var(--radius-lg);
    border: var(--border-thin) solid var(--surface-hairline);
    background: var(--color-field-dark);
  }
  .nearby__links line { stroke: var(--color-sand-38); }
  .nearby__here { fill: var(--color-bone-on-dark); }
  .nearby__here-ring { fill: none; stroke: var(--color-sand); }
  .nearby__label {
    fill: var(--color-bone-on-dark-70);
    font-family: var(--font-body);
    font-weight: 600;
    paint-order: stroke;
    stroke: var(--color-field-dark);
    stroke-width: 3px;
    stroke-linejoin: round;
  }
  .nearby__label--here { fill: var(--color-bone-on-dark); font-weight: 700; }
  /* Phones: the map is drawn for a 640px column, so at ~370px its 13-unit labels rendered at about
     7px and the dots at 3. Sizes here are in map units via --u (one design pixel, set on the svg),
     so they hold whatever crop a metro gets. Labels shift right and down to clear the larger dot. */
  @media (max-width: 639px) {
    .nearby__label { font-size: calc(var(--u) * 22px); stroke-width: calc(var(--u) * 5px);
                     transform: translate(calc(var(--u) * 5px), calc(var(--u) * 3px)); }
    .nearby__label--here { font-size: calc(var(--u) * 26px); transform: translate(calc(var(--u) * 6px), calc(var(--u) * 3px)); }
    .nearby__svg .map__dot, .nearby__here { r: calc(var(--u) * 9px); }
    .nearby__here-ring { r: calc(var(--u) * 15px); stroke-width: calc(var(--u) * 3px); }
  }
  .nearby__svg a:hover .map__dot,
  .nearby__svg a:focus-visible .map__dot { stroke: var(--color-bone-on-dark); stroke-width: 2px; }
  .nearby__caption {
    display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5);
    margin-top: var(--space-4);
    font-size: var(--text-xs); color: var(--surface-text-muted);
  }
  .nearby__key { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: 500; letter-spacing: var(--ls-label); text-transform: uppercase; }
  .nearby__swatch { width: 10px; height: 10px; border-radius: 50%; background: var(--color-sand); }
  .nearby__swatch--here { background: var(--color-bone-on-dark); box-shadow: 0 0 0 2px var(--color-sand); }
  .nearby__note { flex-basis: 100%; }

  .nearby__list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-4); }
  .nearby--no-map .nearby__list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .nearby__installations { margin-top: var(--space-8); }

  .near-card {
    display: block;
    padding: var(--space-5);
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-md);
    background: var(--color-white);
    color: var(--color-ink);
    text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  }
  .near-card:hover { border-color: var(--color-sand-ink); box-shadow: var(--shadow-md); transform: translateY(-1px); }
  .near-card:focus-visible { outline: none; box-shadow: var(--focus-ring-dark); }
  .near-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); }
  .near-card__city { display: block; font-size: var(--text-lg); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); }
  .near-card__metro { display: block; font-size: var(--text-xs); color: var(--color-ink-60); margin-top: 2px; }
  .near-card__distance { flex: none; text-align: right; font-size: var(--text-xs); color: var(--color-ink-60); line-height: 1.2; }
  .near-card__distance b { font-size: var(--text-figure-sm); font-weight: 700; color: var(--color-ink); letter-spacing: var(--ls-tight); }
  .near-card__distance small { display: block; font-size: var(--text-xs); text-transform: capitalize; }
  .near-card__facts {
    list-style: none; padding: var(--space-4) 0 0; margin: var(--space-4) 0 0;
    border-top: var(--border-thin) solid var(--color-hairline);
    display: grid; gap: var(--space-2);
    font-size: var(--text-sm); color: var(--color-ink-60);
  }
  .near-card__facts li { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); align-items: start; }
  .near-card__facts .icon { width: 15px; height: 15px; margin-top: 3px; color: var(--color-sand-ink); }
  /* An open territory's status mark: a filled green disc, the one place --color-signal-open is
     used. The disc takes currentColor; the knocked-out check is white (see the sprite). The ring
     stroke is dropped so the disc edge stays crisp at 15px. */
  .icon.icon--open { color: var(--color-signal-open); stroke: none; }
  .near-card__facts .icon--open { width: 17px; height: 17px; margin-top: 2px; }
  /* Phones: a fact's trailing detail wraps as one unit ("Austin, TX · ~772 mi", "(2020–2024 ACS
     5-year)") instead of breaking mid-phrase at a hyphen or before the distance. */
  @media (max-width: 639px) {
    .near-card__keep { white-space: nowrap; }
    .near-card__source { white-space: nowrap; font-size: var(--text-xs); }
  }
  .near-card__cta {
    display: inline-flex; align-items: center; gap: var(--space-2);
    margin-top: var(--space-4);
    font-size: var(--text-sm); font-weight: 600; color: var(--color-sand-ink);
  }
  .near-card__cta .icon { width: 16px; height: 16px; transition: transform var(--dur-fast) var(--ease-out); }
  .near-card:hover .near-card__cta .icon { transform: translateX(3px); }
  @media (prefers-reduced-motion: reduce) {
    .near-card, .near-card:hover { transform: none; }
    .near-card:hover .near-card__cta .icon { transform: none; }
  }
  @media (max-width: 991px) {
    .nearby { grid-template-columns: 1fr; }
    .nearby--no-map .nearby__list { grid-template-columns: 1fr; }
  }

  /* == component: count-strip ==
     Four count boxes across, for the home page's territory band. Counts from
     the catalog only: what is on the map, never how anything performs. */
  .count-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); margin: var(--space-7) 0 0; }
  .count-strip .count { margin: 0; display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: var(--space-2); }
  .count-strip dd { margin: 0; }
  @media (max-width: 991px) { .count-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

  /* == component: founder-facts ==
     The founder strip's fact list: icon, label, value. Light surface. */
  .founder-facts { margin: 0; display: grid; gap: var(--space-4); }
  .founder-facts__row { display: grid; grid-template-columns: auto 1fr; gap: var(--space-4); align-items: center;
                        padding-bottom: var(--space-4); border-bottom: var(--border-thin) solid var(--surface-hairline); }
  .founder-facts dt { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--surface-text-muted); }
  .founder-facts dd { margin: 2px 0 0; font-size: var(--text-md); font-weight: 600; letter-spacing: var(--ls-tight); }

  /* == component: point-cards ==
     A point list as a row of cards, for three or four points that deserve
     equal weight. The same markup as .points; the modifier only lays it out. */
  .points--cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-5); }
  .points--cards .point {
    display: flex; flex-direction: column; gap: var(--space-4);
    padding: var(--space-6);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-lg);
    background: var(--surface-card);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .points--cards .point:hover { border-color: var(--surface-accent); box-shadow: var(--shadow-md); }
  .points--cards .point + .point { border-top: var(--border-thin) solid var(--surface-hairline); }
  .points--cards .point__title { font-size: var(--text-lg); }
  .points--cards .point__text { max-width: none; }
  @media (max-width: 991px) { .points--cards { grid-template-columns: 1fr; } }

  /* == component: faq-layout ==
     The heading column sits beside the questions instead of above them, so a
     short FAQ does not leave a band of empty space to the right. Sticky on
     wide screens so the heading stays with the list. */
  .faq-layout { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: var(--space-8); align-items: start; }
  .faq-layout__head { position: sticky; top: calc(var(--nav-height) + var(--space-6)); }
  .faq-layout__head .section-header { margin-bottom: 0; }
  .faq-layout__head .lede { margin-top: var(--space-5); }
  @media (max-width: 991px) {
    .faq-layout { grid-template-columns: 1fr; gap: var(--space-6); }
    .faq-layout__head { position: static; }
  }

  /* == component: territory-summary ==
     The home page's territory band: a light section, heading and four small
     figures on the left, the national map in a compact dark card on the right.
     A summary, not the territory index; /territories carries the full map. */
  .territory-summary { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: var(--space-8); align-items: center; }
  .territory-summary__lede { font-size: var(--text-md); color: var(--surface-text-muted); margin-top: var(--space-5); max-width: 46ch; }
  .map--compact {
    display: block;
    padding: var(--space-5) var(--space-5) var(--space-4);
    border-radius: var(--radius-lg);
    background: var(--color-field);
    box-shadow: var(--shadow-md);
  }
  .map--compact .map__legend { margin-top: var(--space-3); }
  .summary-stats {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4) var(--space-6);
    margin: var(--space-6) 0 0;
    padding-top: var(--space-5);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .summary-stats div { display: flex; flex-direction: column-reverse; justify-content: flex-end; }
  .summary-stats dt { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--surface-text-muted); margin-top: var(--space-1); }
  .summary-stats dd { margin: 0; font-family: var(--font-display); font-size: var(--text-figure-md); line-height: 1; color: var(--surface-accent); }
  @media (max-width: 991px) {
    .territory-summary { grid-template-columns: 1fr; gap: var(--space-6); }
  }

  /* == component: territory-directory ==
     The full territory list as a directory: states flow into columns, one line
     per metro with a status dot. Replaces a card grid that ran twenty screens
     long. The search and pills filter it; without JavaScript it all shows. */
  .directory-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-5) var(--space-7); }
  .directory-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
  .directory-search {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: 0 var(--space-4);
    border: var(--border-thin) solid var(--surface-hairline-strong);
    border-radius: var(--radius-pill);
    background: var(--color-white);
    min-width: 260px;
  }
  .directory-search .icon { width: 16px; height: 16px; color: var(--color-sand-ink); flex: none; }
  .directory-search input {
    border: 0; outline: 0; background: transparent; width: 100%;
    padding: 9px 0; font: inherit; font-size: var(--text-sm); color: var(--color-ink);
  }
  .directory-search:focus-within { box-shadow: var(--focus-ring-light); border-color: var(--color-field); }
  .pill__count { font-size: var(--text-xs); opacity: 0.7; }

  .directory {
    columns: 4 220px;
    column-gap: var(--space-7);
    margin-top: var(--space-7);
    padding-top: var(--space-6);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .directory__group { break-inside: avoid; margin: 0 0 var(--space-6); }
  .directory__state {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
    margin: 0 0 var(--space-2); padding-bottom: var(--space-2);
    border-bottom: var(--border-thick) solid var(--color-sand);
    font-size: var(--text-sm); font-weight: 700; letter-spacing: var(--ls-label); text-transform: uppercase;
  }
  .directory__state a { text-decoration: none; color: var(--color-ink); }
  .directory__state a:hover { color: var(--color-sand-ink); }
  .directory__count { font-size: var(--text-xs); font-weight: 600; color: var(--color-ink-60); }
  .directory__list { list-style: none; padding: 0; margin: 0; }
  .directory__item {
    display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3);
    padding: 6px var(--space-2); margin-inline: calc(var(--space-2) * -1);
    border-radius: var(--radius-sm);
    text-decoration: none; color: var(--color-ink); font-size: var(--text-sm);
    transition: background var(--dur-fast) var(--ease-out);
  }
  .directory__item:hover { background: var(--color-white); }
  .directory__item:hover .directory__city { color: var(--color-sand-ink); }
  .directory__city { font-weight: 600; }
  .directory__status { font-size: var(--text-xs); color: var(--color-ink-60); }
  .directory__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-ink-40); }
  .directory__dot--open { background: var(--color-sand-ink); box-shadow: 0 0 0 3px var(--color-sand-10); }
  .directory__dot--in-discussion { background: var(--color-sand-dim); }
  .directory__dot--operating { background: var(--color-field); }
  .directory__empty { margin-top: var(--space-5); font-size: var(--text-sm); color: var(--color-ink-60); }
  @media (max-width: 767px) {
    .directory-search { min-width: 0; width: 100%; }
    .directory { columns: 2 150px; column-gap: var(--space-5); }
  }

  /* == component: article-layout ==
     Guides, posts and comparisons at full container width like every other
     section: a readable article column and a sticky sidebar with the table of
     contents and the next step. The prose measure is kept by the column. */
  .article-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--space-8); align-items: start; }
  .article-layout__main { min-width: 0; max-width: 820px; }
  .article-layout__sticky { position: sticky; top: calc(var(--nav-height) + var(--space-6)); display: grid; gap: var(--space-6); }
  .article-layout__side .toc { margin: 0; }
  .side-cta {
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-field);
    --surface-text: var(--color-bone-on-dark);
    --surface-text-muted: var(--color-bone-on-dark-70);
    --surface-accent: var(--color-sand);
    --focus-ring: var(--focus-ring-dark);
    color: var(--surface-text);
  }
  .side-cta__label { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-eyebrow); text-transform: uppercase; color: var(--surface-accent); margin: 0; }
  .side-cta__title { font-size: var(--text-xl-desktop); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); margin: var(--space-2) 0 0; }
  .side-cta__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin: var(--space-3) 0 var(--space-5); line-height: var(--lh-body); }
  .side-cta .button--secondary { color: var(--surface-text); border-color: var(--color-hairline-dark); }
  @media (max-width: 991px) {
    .article-layout { grid-template-columns: 1fr; }
    .article-layout__main { max-width: none; }
    .article-layout__sticky { position: static; }
    .article-layout__side .toc { display: none; }
  }

  /* == component: vets-advantage ==
     The pro-VETS panel on every comparison page: four facts the site states
     elsewhere, on the field surface so it reads as VETS's own column does. */
  .advantage {
    margin-top: var(--space-7);
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-field);
    border-top: var(--border-thick) solid var(--color-sand);
    --surface-text: var(--color-bone-on-dark);
    --surface-text-muted: var(--color-bone-on-dark-70);
    --surface-accent: var(--color-sand);
    --surface-tint: rgba(245, 242, 236, 0.06);
    --surface-hairline: var(--color-hairline-dark);
    --focus-ring: var(--focus-ring-dark);
    color: var(--surface-text);
  }
  .advantage__label { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-eyebrow); text-transform: uppercase; color: var(--surface-accent); margin: 0; }
  .advantage__title { font-size: var(--text-xl-desktop); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); margin: var(--space-2) 0 0; }
  .advantage__list { list-style: none; padding: 0; margin: var(--space-5) 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4) var(--space-6); }
  .advantage__list li { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); align-items: start; }
  .advantage__list b { display: block; font-size: var(--text-sm); font-weight: 700; }
  .advantage__list span:not(.icon-well) { display: block; font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: 2px; line-height: var(--lh-body); }
  .advantage .text-link { color: var(--surface-accent); }
  @media (max-width: 767px) { .advantage__list { grid-template-columns: 1fr; } }

  /* == component: loc-card == */
  .loc-card {
    display: block;
    padding: var(--space-5);
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-md);
    background: var(--color-white);
    text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .loc-card:hover { border-color: var(--color-sand-ink); box-shadow: var(--shadow-md); }
  .loc-card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
  .loc-card__city { font-size: var(--text-lg); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); }
  .loc-card__arrow { width: 18px; height: 18px; color: var(--color-sand-ink); }
  .loc-card__meta { font-size: var(--text-sm); color: var(--color-ink-60); margin-top: var(--space-2); }

  /* == component: snapshot-card ==
     A light card on the dark hero: the facts read as facts, not as chrome.
     Every value is a claim; in Production an unapproved row disappears. */
  /* Compact on purpose: it is a sidebar of short facts, not a feature. Values are body size
     and semibold, not lede size and bold; the label is the only rule under the heading, and
     rows are split by hairlines only between each other. */
  .snapshot {
    padding: var(--space-5);
    border-radius: var(--radius-lg);
    background: var(--color-bone);
    box-shadow: var(--shadow-md);
  }
  .snapshot__label {
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    color: var(--color-sand-ink);
    padding-bottom: var(--space-3);
    border-bottom: var(--border-thin) solid var(--color-hairline);
  }
  .snapshot__list { list-style: none; padding: 0; margin: 0; }
  /* Label above value, not beside it. Side by side, a long label ("Estimated initial
     investment") is squeezed into a third column by the value and wraps to three lines. */
  .snapshot__row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-3);
    padding-block: var(--space-3);
  }
  .snapshot__row + .snapshot__row { border-top: var(--border-thin) solid var(--color-hairline); }
  .snapshot__row:last-child { padding-bottom: 0; }
  .snapshot .icon-well--sm { width: 32px; height: 32px; }
  .snapshot .icon-well--sm .icon { width: 16px; height: 16px; }
  .snapshot__key { display: block; font-size: var(--text-xs); font-weight: 500;
                   letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-ink-60); }
  .snapshot__value { display: block; font-size: var(--text-sm); font-weight: 600;
                     letter-spacing: var(--ls-tight); line-height: var(--lh-snug); margin-top: 2px; }
  .snapshot__value:empty { display: none; }
  .snapshot__value--accent { color: var(--color-sand-ink); }
  .snapshot__note { font-size: var(--text-xs); color: var(--color-ink-60); margin-top: var(--space-4); line-height: 1.5; }

  /* == component: panels == */
  .panels { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }
  .panel { padding: var(--space-7); border-radius: var(--radius-lg); }
  .panel--you   { background: var(--color-ink); }
  /* field-DARK, not field: a field panel sits on a field section, and the two matching made the
     card invisible — it read as a paragraph floating in the band. field-light would separate too,
     but sand on it is 4.13:1, under the floor the panel tag needs. */
  .panel--field { background: var(--color-field-dark); border: var(--border-thin) solid var(--color-hairline-dark); }
  .panel--us    { background: var(--color-white); border: var(--border-thin) solid var(--color-hairline); }
  .panel__tag {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--surface-accent);
  }
  .panel__tag .icon { width: 16px; height: 16px; }
  .panel__title {
    font-size: var(--text-2xl);
    font-weight: 700;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-heading);
    margin-top: var(--space-4);
  }
  .panel__text { margin-top: var(--space-4); color: var(--surface-text-muted); }

  /* == component: process-steps ==
     The number sits beside the title on one line; the description hangs
     under the title, not under the number. */
  .proc__steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6);
                 list-style: none; padding: 0; margin: 0; counter-reset: step; }
  .proc__steps--list { grid-template-columns: 1fr; gap: var(--space-5); }
  .proc-step {
    display: grid;
    grid-template-columns: 36px 1fr;
    column-gap: var(--space-4);
    row-gap: var(--space-2);
    align-items: center;
    align-content: start;   /* implicit rows would otherwise stretch and drift the titles between columns */
  }
  .proc-step__marker {
    display: inline-grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border: var(--border-thick) solid var(--surface-accent);
    border-radius: 50%;
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--surface-accent);
  }
  .proc-step__title { font-size: var(--text-lg); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); }
  .proc-step__text { grid-column: 2; font-size: var(--text-sm); color: var(--surface-text-muted); }

  /* == component: faq ==
     Native details/summary: the answer is in the DOM and indexable with JS off,
     and the FAQPage schema is built from the same data so the texts cannot diverge. */
  .faq { list-style: none; padding: 0; margin: 0; }
  .faq__item { border-top: var(--border-thin) solid var(--surface-hairline); }
  .faq__item:last-child { border-bottom: var(--border-thin) solid var(--surface-hairline); }
  .faq__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    padding: var(--space-5) 0;
    cursor: pointer;
    font-size: var(--text-md);
    font-weight: 600;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug);
    list-style: none;
  }
  .faq__summary::-webkit-details-marker { display: none; }
  .faq__summary:hover { color: var(--surface-accent); }
  .faq__icon {
    display: inline-grid;
    place-items: center;
    width: 28px;
    height: 28px;
    flex: none;
    border-radius: 50%;
    border: var(--border-thin) solid var(--surface-hairline-strong);
    color: var(--surface-accent);
    font-weight: 500;
    transition: transform var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
  }
  .faq__details[open] .faq__icon { transform: rotate(45deg); background: var(--surface-tint); }
  .faq__body { padding: 0 var(--space-8) var(--space-5) 0; max-width: 72ch; color: var(--surface-text-muted); }
  .faq-group { margin-top: var(--space-8); }
  .faq-group:first-child { margin-top: 0; }
  .faq-group .headline--card { margin-bottom: var(--space-4); }

  /* == component: lead-form == */
  .form {
    padding: var(--space-7);
    border-radius: var(--radius-lg);
    background: var(--color-white);
    box-shadow: var(--shadow-lg);
  }
  .form__title { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); }
  .form__intro { font-size: var(--text-sm); color: var(--color-ink-60); margin-top: var(--space-2); margin-bottom: var(--space-6); }
  .form__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
  .field { display: block; margin-bottom: var(--space-4); }
  .field__label { display: block; font-size: var(--text-xs); font-weight: 600;
                  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-ink-60);
                  margin-bottom: var(--space-2); }
  .input, .select, .textarea {
    width: 100%;
    padding: 12px var(--space-4);
    border: var(--border-thin) solid rgba(14, 17, 22, 0.22);
    border-radius: var(--radius-md);
    background: var(--color-white);
    font-size: var(--text-md);
    line-height: 1.4;
    transition: border-color var(--dur-fast) var(--ease-out);
  }
  .input::placeholder, .textarea::placeholder { color: var(--color-ink-40); }
  .input:hover, .select:hover, .textarea:hover { border-color: rgba(14, 17, 22, 0.4); }
  .input:focus-visible, .select:focus-visible, .textarea:focus-visible { border-color: var(--color-field); }
  .textarea { resize: vertical; min-height: 110px; }
  .field__error { display: block; font-size: var(--text-xs); color: var(--color-flag); margin-top: var(--space-2); }
  .form__alert { font-size: var(--text-sm); font-weight: 600; color: var(--color-flag); margin-bottom: var(--space-4); }
  .field__error:empty { display: none; }

  /* Honeypot: off-screen, not display:none — some bots skip hidden inputs,
     which defeats the point. */
  .honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

  /* == component: consent-check == */
  .consent { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); align-items: start;
             font-size: var(--text-xs); color: var(--color-ink-60); line-height: 1.5; }
  .consent input {
    appearance: none;
    width: 20px; height: 20px;
    margin: 0;
    border: var(--border-thin) solid rgba(14, 17, 22, 0.35);
    border-radius: var(--radius-sm);
    background: var(--color-white);
    cursor: pointer;
  }
  .consent input:checked { background: var(--color-field); border-color: var(--color-field); }
  .consent input:checked::after {
    content: "";
    display: block;
    width: 5px; height: 10px;
    margin: 2px auto;
    border: solid var(--color-bone);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
  }

  /* == component: disclaimer == */
  .disclaimer { font-size: var(--text-xs); color: var(--surface-text-muted); max-width: 70ch; line-height: 1.5; }
  .disclaimer + .disclaimer { margin-top: var(--space-3); }

  /* == component: non-affiliation == */
  .non-affiliation {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-md);
    font-size: var(--text-xs);
    color: var(--surface-text-muted);
  }
  .non-affiliation .icon { width: 16px; height: 16px; margin-top: 2px; }

  /* == component: data-sources ==
     The metro page's source notes as one compact band: the credit on the left, the numbered notes
     flowing in a wrapped row on the right. The counter prints each number, which is the superscript
     on the stat card that cites it. */
  .data-sources { padding-block: var(--space-7); scroll-margin-top: var(--nav-height); }
  .data-sources__grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
                        gap: var(--space-4) var(--space-8); align-items: start; }
  .data-sources__lead { margin-top: var(--space-3); font-size: var(--text-xs); line-height: 1.5;
                        color: var(--surface-text-muted); max-width: 46ch; }
  .data-sources__list { list-style: none; margin: 0; padding: 0; counter-reset: source;
                        display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
                        font-size: var(--text-sm); color: var(--surface-text); }
  .data-sources__list li { counter-increment: source; display: inline-flex; align-items: baseline; gap: var(--space-2);
                           white-space: nowrap; }
  .data-sources__list li::before { content: counter(source); font-size: var(--text-xs); font-weight: 700;
                                   color: var(--color-sand-ink); font-variant-numeric: tabular-nums; }
  .data-sources__vintage { color: var(--surface-text-muted); }
  @media (max-width: 767px) {
    .data-sources { padding-block: var(--space-6); }
    .data-sources__grid { grid-template-columns: 1fr; }
  }

  /* == component: source-footnotes == */
  .sources { font-size: var(--text-xs); color: var(--surface-text-muted); }
  .sources ol { padding-left: var(--space-5); margin: var(--space-3) 0 0; }
  .sources li + li { margin-top: var(--space-2); }

  /* == component: key-takeaways == */
  .takeaways { padding: var(--space-6); border-radius: var(--radius-lg); background: var(--color-linen); }
  .takeaways__title { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); }
  .takeaways .point { padding-block: var(--space-3); }
  .takeaways .point:first-child { border-top: none; }
  .takeaways .point:last-child { border-bottom: none; }
  .takeaways .point__text { color: var(--color-ink); margin-top: 0; }

  /* == component: empty-state ==
     The honest "nothing here yet". Centered, one message, one action. */
  .empty-state {
    max-width: 560px;
    margin-inline: auto;
    text-align: center;
  }
  .empty-state .icon-well { margin-inline: auto; margin-bottom: var(--space-5); }
  .empty-state .lede { margin: 0 auto; }
  .empty-state__action { margin-top: var(--space-6); }

  /* == component: final-cta ==
     A flat field-green band. No stripes, no texture.

     It used to be centred inside a 720px column, which made the one section
     that closes every page on the site the only one that did not use the full
     width — and it squeezed the three assurances into columns so narrow that
     "Fourteen days, minimum" wrapped onto two lines. It is now a two-column
     band on the same grid as everything else: the ask on the left, what
     happens next on the right. */
  .final-cta {
    background: var(--color-field);
    border-top: var(--border-thin) solid var(--color-hairline-dark);
    padding-block: var(--section-pad-md);
  }
  .final-cta__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--space-9);
    align-items: start;
  }
  .final-cta .lede { max-width: 46ch; }
  .final-cta__buttons { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-7); }
  .final-cta__guide { margin-top: var(--space-6); }

  /* What actually happens next. Every one of these is a commitment we make or a
     rule that binds us, never a statement about how anything turns out — the
     band that closes ~240 pages is the last place to get that wrong. */
  .final-cta__assurances {
    display: grid;
    gap: 0;
    padding-top: var(--space-2);
  }
  .assurance {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-5);
    align-items: start;
    padding-block: var(--space-5);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .assurance:first-child { border-top: none; padding-top: 0; }
  .assurance__title { font-size: var(--text-md); font-weight: 700; letter-spacing: var(--ls-tight);
                      line-height: var(--lh-snug); }
  .assurance__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-2);
                     max-width: 46ch; }

  .final-cta__legal {
    margin-top: var(--space-8);
    padding-top: var(--space-5);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .final-cta__legal .disclaimer { color: var(--surface-text-faint); max-width: 84ch; }

  /* == component: site-nav ==
     ALWAYS a solid band. It used to be transparent over a hero and solid elsewhere, which made the
     header look like two different headers depending on the page. The transparency only ever paid
     off over hero media, and there is none: every hero is flat field-dark, so a transparent nav
     just removed the edge between the header and the page. */
  .nav {
    position: fixed;
    inset: 0 0 auto;
    z-index: var(--z-nav);
    height: var(--nav-height);
    display: flex;
    align-items: center;
    background: var(--color-field);
    border-bottom: var(--border-thin) solid var(--color-hairline-dark);
    transition: height var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
  }
  /* Scrolled adds a shadow and nothing else. It used to shrink the bar, which made the header a
     different size on a page with a hero than on a page without one — pages with no hero start in
     this state. */
  .nav.is-scrolled { box-shadow: var(--shadow-nav); }
  .nav__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); }

  .nav__logo { display: inline-flex; align-items: center; text-decoration: none; flex: none; }
  .nav__logo img { height: 34px; width: auto; }

  .nav__links { display: flex; align-items: center; gap: var(--space-1); list-style: none; margin: 0; padding: 0; }
  .nav__links a {
    display: inline-block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--surface-text-muted);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
  }
  .nav__links a:hover { color: var(--surface-text); background: var(--surface-tint); }
  .nav__links a[aria-current="page"] { color: var(--surface-text); }
  .nav__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 10px var(--space-5);
    border-radius: var(--radius-pill);
    background: var(--color-bone);
    color: var(--color-ink);
    font-size: var(--text-sm);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--dur-fast) var(--ease-out);
  }
  .nav__cta .icon { width: 15px; height: 15px; }
  .nav__cta:hover { background: var(--color-sand); }
  .nav__toggle { display: none; width: 44px; height: 44px; align-items: center; justify-content: center;
                 border: var(--border-thin) solid var(--surface-hairline-strong); border-radius: var(--radius-pill);
                 background: none; color: inherit; cursor: pointer; }
  .nav__toggle .icon { width: 20px; height: 20px; }

  /* == component: mobile-menu == */
  .mobile-menu {
    position: fixed;
    inset: 0;
    z-index: var(--z-mobile-menu);
    display: none;
    flex-direction: column;
    padding: 0 var(--container-padding) var(--space-8);
    background: var(--color-field-dark);
    overflow-y: auto;
  }
  .mobile-menu[data-open="true"] { display: flex; }
  /* The overlay's top row IS the header bar, pixel for pixel: same height, same field background,
     same bottom rule, full bleed. It used to be a 44px row under 24px of padding on field-dark, so
     opening the menu dropped the logo ~12px and changed the bar's colour. */
  .mobile-menu__top {
    display: flex; align-items: center; justify-content: space-between; flex: none;
    height: var(--nav-height);
    margin-inline: calc(-1 * var(--container-padding));
    padding-inline: var(--container-padding);
    background: var(--color-field);
    border-bottom: var(--border-thin) solid var(--color-hairline-dark);
  }
  .mobile-menu__links { list-style: none; padding: 0; margin: var(--space-5) 0 0; }
  .mobile-menu__links a {
    display: block;
    padding-block: var(--space-4);
    border-bottom: var(--border-thin) solid var(--surface-hairline);
    font-size: var(--text-xl);
    font-weight: 600;
    letter-spacing: var(--ls-tight);
    text-decoration: none;
  }
  .mobile-menu__links a[aria-current="page"] { color: var(--surface-accent); }
  .mobile-menu__cta { margin-top: var(--space-7); }

  /* == component: site-footer == */
  .footer { background: var(--color-field-dark); padding: var(--space-8) 0 var(--space-6);
            border-top: var(--border-thin) solid var(--color-hairline-dark); }
  .footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: var(--space-7);
                  padding-bottom: var(--space-7);
                  border-bottom: var(--border-thin) solid var(--surface-hairline); }
  .footer__brand .nav__logo img { height: 30px; }
  .footer__tagline { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-4); max-width: 34ch; }
  .footer__heading { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-label);
                     text-transform: uppercase; color: var(--surface-text-muted); }
  .footer__links { list-style: none; padding: 0; margin: var(--space-4) 0 0; }
  .footer__links li + li { margin-top: var(--space-2); }
  .footer__links a { font-size: var(--text-sm); text-decoration: none; color: var(--surface-text); opacity: 0.85; }
  .footer__links a:hover { opacity: 1; color: var(--surface-accent); }
  .footer__legal { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--space-7);
                   padding-top: var(--space-6); font-size: var(--text-xs); color: var(--surface-text-muted); }
  .footer__legal .footer__links { margin: 0; }
  .footer__legal .footer__links a { font-size: var(--text-xs); }

  /* == component: hero ==
     Flat field-dark. The gradient overlay only applies when a media element
     is present; there is none yet (brand video and photography undelivered). */
  .hero {
    position: relative;
    background: var(--color-field-dark);
    padding-top: calc(var(--nav-height) + var(--space-6));
    padding-bottom: var(--space-6);
    overflow: hidden;
  }

  /* Authored artwork behind the hero: contour lines in the accent colour at a
     low opacity. Every hero gets one, so no page is a flat block of green, and
     it costs a couple of KB of path data rather than a photograph. It sits
     under hero__media, so real photography covers it when it arrives. */
  .hero__motif {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    opacity: 0.16;
  }
  .hero__motif svg { width: 100%; height: 100%; display: block; }
  .hero__motif path { fill: none; stroke: var(--color-sand); stroke-width: 1.25; }
  .hero__media { position: absolute; inset: 0; }
  .hero__media img, .hero__media video { width: 100%; height: 100%; object-fit: cover;
                                         filter: saturate(0.8) brightness(0.9); }
  .hero__overlay { display: none; }
  .hero__media + .hero__overlay {
    display: block;
    position: absolute;
    inset: 0;
    background:
      linear-gradient(100deg, rgba(30, 43, 34, 0.92) 0%, rgba(30, 43, 34, 0.8) 40%, rgba(42, 59, 47, 0.55) 100%);
  }
  .hero__inner { position: relative; }
  /* The card column is capped: at 0.85fr it grew to ~460px on a 1240px container and read as a
     second headline competing with the first. It is a sidebar, sized like one. */
  .hero__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
                gap: var(--space-8); align-items: center; }
  .hero .breadcrumb { margin-bottom: var(--space-5); }
  .hero .lede { max-width: 560px; }
  .hero__cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4);
                   margin-top: var(--space-6); }
  .hero--home { padding-top: calc(var(--nav-height) + var(--space-7)); padding-bottom: var(--space-7); }

  /* == component: dev-banner ==
     Development only. Content that has not cleared legal review renders with this
     and NoIndex(); in Production the same record 410s instead. */
  .dev-banner { background: var(--color-flag); color: var(--color-white);
                padding: var(--space-3) var(--space-5); font-size: var(--text-xs); font-weight: 700;
                letter-spacing: var(--ls-label); text-transform: uppercase; text-align: center; }

  /* Unresolved claims and disclaimers render as a small red chip in Development so
     the author sees exactly which id failed, in the author's font, not the page's. */
  .dev-missing-claim, .dev-missing-disclaimer {
    display: inline-block;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0;
    line-height: 1.4;
    text-transform: none;
    text-align: left;
    padding: 2px var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--color-flag);
    color: var(--color-white);
  }

  /* == component: answer ==
     The opening 40-60 word answer every page owes its title question, plus the
     three things a reader would otherwise hunt for.

     It is a COMPACT STRIP, not a section of its own. Two earlier attempts —
     a lone prose paragraph, then a wide three-column block — both produced a
     tall band holding one paragraph, which is the thing that kept looking
     broken. It is short, it sits tight under the hero, and the facts give it
     something to be.

     The text is --text-md, the same size as body copy everywhere else. It was
     larger, and nothing else on any page was set at that size, so it read as a
     different typeface rather than as emphasis.

     It is a BRIEFING CARD (2026-09-25): a white card on the light section, a
     field-green rail carrying the label, and the facts on a linen band across
     its foot. It replaced a sand rule over loose text, which read as a divider
     with a paragraph under it rather than as a thing of its own. */
  .answer {
    display: grid;
    grid-template-columns: minmax(150px, 200px) minmax(0, 1fr);
    background: var(--surface-card);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    overflow: hidden;
  }
  /* The rail is a dark surface of its own, so it reads the dark surface's
     accent rather than the light section's. Sand on field is the accent pair. */
  .answer__label {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: 0;
    padding: var(--space-6) var(--space-5);
    background: var(--color-field);
    color: var(--color-sand);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: var(--ls-eyebrow);
    text-transform: uppercase;
    line-height: var(--lh-snug);
  }
  /* Decoration: a plain five-point star, the site's existing mark. No insignia,
     no seal, and sand, never flag red (§2.6, §7). */
  .answer__label::before {
    content: "";
    width: 18px;
    height: 18px;
    background: currentColor;
    clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%,
                       21% 91%, 32% 57%, 2% 35%, 39% 35%);
  }
  .answer__body { display: flex; flex-direction: column; min-width: 0; }
  .answer__text {
    font-size: var(--text-md);
    line-height: var(--lh-body);
    color: var(--surface-text);
    max-width: 72ch;
    text-wrap: pretty;
    padding: var(--space-6) var(--space-7) 0;
  }
  .answer__text + .answer__text { margin-top: var(--space-4); padding-top: 0; }
  .answer__body > .answer__text:last-child { padding-bottom: var(--space-6); }

  /* Three facts on a linen band across the foot of the card. Every one restates
     something the page already says; a VETS figure only arrives by claim id. */
  .answer__facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin: var(--space-6) 0 0;
    background: var(--color-linen);
  }
  .answer__fact {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--space-4);
    row-gap: 2px;
    align-content: start;
    padding: var(--space-5) var(--space-6);
  }
  .answer__fact + .answer__fact { box-shadow: inset var(--border-thin) 0 0 var(--surface-hairline); }
  /* The sprite glyph itself is the well: an outer <svg> honours padding, so
     the markup on every page stays as it is. It spans both rows so the label
     and the value read as one block. */
  .answer__fact > .icon {
    grid-row: span 2;
    box-sizing: border-box;
    width: 40px;
    height: 40px;
    padding: 10px;
    border-radius: var(--radius-md);
    background: var(--surface-card);
    color: var(--surface-accent);
    box-shadow: var(--shadow-sm);
  }
  .answer__fact dt {
    font-size: var(--text-xs);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--surface-text-muted);
  }
  .answer__fact dd { margin: 0; font-size: var(--text-lg); font-weight: 700; color: var(--surface-text);
                     letter-spacing: var(--ls-tight); line-height: var(--lh-snug); text-wrap: balance; }

  /* == component: story ==
     Narrative prose in a section, beside something that gives the column a
     reason to stop. Loose paragraphs dropped straight into a container ran the
     full 1240px, which is about 150 characters a line and unreadable, and the
     band around them looked empty because nothing else was in it. */
  .story { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); gap: var(--space-8);
           align-items: start; }
  .story__body > p { max-width: 62ch; }
  .story__body > p + p { margin-top: var(--space-5); }
  .story__lead { font-size: var(--text-lg); line-height: var(--lh-body); }
  .story__aside { position: relative; padding-top: var(--space-2); }

  /* == component: split ==
     Who owns what. Two columns with a rule between them, because the point of
     the thing is the division. */
  .split { display: grid; grid-template-columns: 1fr 1fr; gap: 0;
           border: var(--border-thin) solid var(--surface-hairline); border-radius: var(--radius-lg);
           overflow: hidden; background: var(--surface-card); }
  .split__side { padding: var(--space-6); }
  .split__side + .split__side { border-left: var(--border-thin) solid var(--surface-hairline); }
  .split__side--ours { background: var(--surface-tint); }
  .split__head { display: flex; align-items: center; gap: var(--space-3); }
  .split__head .icon { width: 20px; height: 20px; color: var(--surface-accent); }
  .split__who { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); }
  .split__note { font-size: var(--text-xs); color: var(--surface-text-muted); margin-top: var(--space-2); }
  .split__list { list-style: none; padding: 0; margin: var(--space-5) 0 0; display: grid; gap: var(--space-3); }
  .split__list li { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3);
                    font-size: var(--text-sm); align-items: start; }
  .split__list .icon { width: 15px; height: 15px; color: var(--surface-accent); margin-top: 4px; }

  /* == component: star-band ==
     A decorative field of stars, for the veteran-facing pages.

     Stars and the palette, nothing else. CLAUDE.md section 2.6 forbids any DoD,
     branch or unit insignia or seal and anything that implies endorsement, so
     there is no eagle, no rank chevron and no seal here — a generic star is not
     an insignia. Flag red stays out of it too: section 7 reserves that colour
     for the primary action and it never decorates.

     aria-hidden and pointer-events none: it carries no meaning. */
  .star-band {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    opacity: 0.5;
  }
  /* Fill on the svg, not the path: the visible stars are <use> copies of the path in <defs>, and a
     copy inherits from ITS parents. With the rule on the path the copies rendered default black —
     near-invisible on ink, which read as the stars having gone. */
  .star-band svg { width: 100%; height: 100%; display: block; fill: var(--surface-accent); }
  .section > .star-band + .container { position: relative; }

  /* == component: pullquote ==
     One line that carries the page. Used for the mission statement on the
     veteran-facing pages, where the brand documentation names it as the
     approved closing line. */
  .pullquote {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-6);
    align-items: start;
    max-width: 62ch;
  }
  .pullquote__rule { width: 4px; align-self: stretch; border-radius: var(--radius-pill);
                     background: var(--surface-accent); }
  .pullquote__text {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    text-transform: uppercase;
    line-height: var(--lh-heading);
    letter-spacing: var(--ls-display);
  }
  .pullquote__by { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-4); }

  /* == component: diagram ==
     Inline SVG, server-rendered, no chart library. Every diagram here is
     STRUCTURAL: it shows how something is arranged, never how much of it there
     is. Nothing on this site may imply a financial outcome, and a chart with an
     invented axis would do exactly that — so these carry no quantities, no
     scale and no forecast, and each one says so in its caption.

     Colour comes from the surface variables, so one diagram is legible on bone,
     linen, field and ink without a second copy. */
  .diagram {
    margin: 0;
    padding: var(--space-6);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-lg);
    background: var(--surface-tint);
  }
  .diagram__svg { width: 100%; height: auto; display: block; overflow: visible; color: var(--surface-text); }
  /* Every diagram carries two drawings of the same thing. The wide one is 760 units across; scaled
     into a phone column its 15px titles rendered at about 6px. The narrow one is drawn at 340, the
     phone column's real width. display:none also takes the unused copy out of the accessibility
     tree, so a screen reader hears one title and one description. */
  .diagram__svg--narrow { display: none; }
  @media (max-width: 639px) {
    .diagram__svg--wide { display: none; }
    .diagram__svg--narrow { display: block; }
  }
  .diagram__caption {
    display: block;
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--surface-text-muted);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }

  /* Shared SVG vocabulary. Presentation lives here rather than on the elements
     so a diagram partial carries geometry and words only. */
  .dgm-card { fill: var(--surface-card); stroke: var(--surface-hairline-strong); stroke-width: 1; }
  .dgm-card--accent { stroke: var(--surface-accent); }
  .dgm-card--solid { fill: var(--color-flag); stroke: none; }
  .dgm-title { fill: currentColor; font-family: var(--font-body); font-size: 15px; font-weight: 700;
               letter-spacing: -0.01em; }
  .dgm-sub { fill: var(--surface-text-muted); font-family: var(--font-body); font-size: 12px; }
  .dgm-key { fill: var(--surface-accent); font-family: var(--font-body); font-size: 11px;
             font-weight: 600; letter-spacing: var(--ls-label); text-transform: uppercase; }
  .dgm-on-solid { fill: var(--color-white); }
  .dgm-line { fill: none; stroke: var(--surface-hairline-strong); stroke-width: 1.5; }
  .dgm-line--accent { stroke: var(--surface-accent); }
  /* An arrow's shaft and chevron. The shaft stops 1 unit short of the tip, under the chevron;
     with square ends it ran 2 units past the point and poked out beyond it. Round ends and a
     round join close the point cleanly. */
  .dgm-arrow { stroke-linecap: round; stroke-linejoin: round; }

  /* A tile that opens its details. The glyph in the corner is the affordance a touch screen needs,
     since there is no hover there. */
  .dgm-link { cursor: pointer; }
  .dgm-link .dgm-card { transition: stroke var(--dur-fast) var(--ease-out); }
  .dgm-link:hover .dgm-card { stroke: var(--surface-accent); }
  .dgm-more { fill: none; stroke: var(--surface-text-faint); stroke-width: 2;
              stroke-linecap: round; stroke-linejoin: round; transition: stroke var(--dur-fast) var(--ease-out); }
  .dgm-link:hover .dgm-more { stroke: var(--surface-accent); }
  /* The travelling icons pass over the tiles' edges; they must never swallow a click. */
  .dgm-travel { pointer-events: none; }

  /* == component: modal ==
     A native <dialog> opened with showModal(): focus trapping, Escape and the top layer come from
     the browser. A light card, whatever surface the page behind it is. */
  .modal {
    width: min(480px, calc(100vw - var(--container-padding) * 2));
    padding: 0;
    border: none;
    border-radius: var(--radius-lg);
    background: var(--color-bone);
    color: var(--color-ink);
    box-shadow: var(--shadow-lg);
  }
  .modal::backdrop { background: var(--color-ink-60); }
  /* Padding lives here, not on the dialog, so a click in it is not mistaken for the backdrop. */
  .modal__body { padding: var(--space-6); }
  .modal__head { display: flex; align-items: center; gap: var(--space-4); }
  .modal__head .icon-well { border-color: var(--color-hairline); background: var(--color-white); color: var(--color-sand-ink); }
  .modal__title { flex: 1; font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); line-height: var(--lh-snug); }
  .modal__close { display: inline-grid; place-items: center; width: 40px; height: 40px; flex: none;
                  border: var(--border-thin) solid var(--color-hairline); border-radius: var(--radius-pill);
                  background: none; color: var(--color-ink); cursor: pointer; }
  .modal__close:hover { border-color: var(--color-ink-40); }
  .modal__close .icon { width: 18px; height: 18px; }
  .modal__text { margin-top: var(--space-5); font-size: var(--text-md); line-height: var(--lh-body); color: var(--color-ink-60); }
  /* Without JavaScript a tile jumps to its list item; clear the fixed header when it lands. */
  .point[id] { scroll-margin-top: calc(var(--nav-height) + var(--space-5)); }
  .dgm-dot { fill: var(--surface-accent); }
  .dgm-dot--muted { fill: var(--surface-text-faint); }
  .dgm-icon { fill: none; stroke: var(--surface-accent); stroke-width: 1.6;
              stroke-linecap: round; stroke-linejoin: round; }
  /* A sprite symbol reused inside a diagram. The sprite carries geometry only —
     .icon supplies the presentation in normal use — so a diagram has to supply
     its own, and at the smaller size the stroke is dialled back. */
  .dgm-glyph { fill: none; stroke: var(--surface-accent); stroke-width: 2;
               stroke-linecap: round; stroke-linejoin: round; }

  /* == component: diagram-travel ==
     Icons that ride the connector paths, so the motion says what the diagram
     says. SMIL animateMotion follows the real path rather than a second copy
     of it in CSS, which means the curve and the movement cannot drift apart.

     Hidden outright for anyone who has asked for less motion: the diagram is
     complete and readable without it, so there is nothing to degrade to. */
  .dgm-travel > g { opacity: 0; }
  /* Each travelling icon rides on an opaque chip in the card's own colours.
     Without it the connector runs straight through the glyph and the icon
     reads as a faint transparency rather than a thing moving along the line. */
  .dgm-travel__chip { fill: var(--surface-card); stroke: var(--surface-hairline-strong); stroke-width: 1; }
  .dgm-travel__chip--accent { stroke: var(--surface-accent); }
  @media (prefers-reduced-motion: reduce) {
    .dgm-travel { display: none; }
  }

  /* Connectors draw themselves in once the diagram scrolls into view. The
     dash offset only applies under html.js, so with JavaScript off every line
     is simply drawn. */
  .js .diagram .dgm-line { stroke-dasharray: var(--dgm-len, 300); stroke-dashoffset: var(--dgm-len, 300); }
  .js .diagram.is-visible .dgm-line { stroke-dashoffset: 0; transition: stroke-dashoffset 900ms var(--ease-out); }
  @media (prefers-reduced-motion: reduce) {
    .js .diagram .dgm-line { stroke-dasharray: none; stroke-dashoffset: 0; transition: none; }
  }

  /* == component: fdd-map ==
     The reading order for a Franchise Disclosure Document. Markup rather than
     SVG: six labelled items with real sentences that must reflow on a phone and
     be read aloud in order. The item numbers are the FTC Franchise Rule's, not
     ours, so none of them is a claim. */
  .fdd-map { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; counter-reset: fdd; }
  .fdd-map__item {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-5);
    align-items: start;
    padding-block: var(--space-5);
    border-top: var(--border-thin) solid var(--surface-hairline);
  }
  .fdd-map__item:last-child { border-bottom: var(--border-thin) solid var(--surface-hairline); }
  .fdd-map__num {
    display: inline-grid;
    place-items: center;
    width: 46px; height: 46px;
    flex: none;
    border-radius: var(--radius-md);
    border: var(--border-thin) solid var(--surface-hairline-strong);
    background: var(--surface-tint);
    color: var(--surface-accent);
    font-size: var(--text-lg);
    font-weight: 700;
    letter-spacing: var(--ls-tight);
  }
  /* Item 20 is the one that sends a candidate away from us to talk to owners.
     It is marked because it is the most useful item, not the least. */
  .fdd-map__item--call .fdd-map__num { border-color: var(--surface-accent); }
  .fdd-map__title { font-size: var(--text-md); font-weight: 700; letter-spacing: var(--ls-tight); }
  .fdd-map__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-2);
                   max-width: 78ch; }

  /* == component: checklist ==
     Ticked traits and unticked warnings, same row shape. Used where a reader is
     matching themselves against a profile. */
  .checklist { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-3); }
  .checklist__item { display: grid; grid-template-columns: auto 1fr; gap: var(--space-4); align-items: start; }
  .checklist__mark {
    display: inline-grid;
    place-items: center;
    width: 26px; height: 26px;
    flex: none;
    border-radius: 50%;
    border: var(--border-thin) solid var(--surface-hairline-strong);
    color: var(--surface-accent);
    margin-top: 1px;
  }
  .checklist__mark .icon { width: 15px; height: 15px; }
  .checklist__mark--warn { color: var(--color-flag); }
  .checklist__text { font-size: var(--text-md); }
  .checklist__text b { font-weight: 700; }
  .checklist__note { display: block; font-size: var(--text-sm); color: var(--surface-text-muted);
                     margin-top: 2px; max-width: 78ch; }

  /* == component: path-chooser ==
     Doc 04 T7a: operator-education pages answer honestly for independents
     first. Three real options, one of which is not buying a franchise.
     (The prose layer styles the in-article variant; this is the section one.) */
  .paths { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); }
  .path {
    display: flex;
    flex-direction: column;
    padding: var(--space-6);
    border: var(--border-thin) solid var(--surface-hairline);
    border-radius: var(--radius-lg);
    background: var(--surface-card);
  }
  .path--ours { border-color: var(--surface-accent); }
  .path__tag { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-label);
               text-transform: uppercase; color: var(--surface-accent); }
  .path__title { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight);
                 line-height: var(--lh-snug); margin-top: var(--space-3); }
  .path__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-3); }
  .path__best { font-size: var(--text-sm); margin-top: auto; padding-top: var(--space-5); }
  .path__best b { display: block; font-size: var(--text-xs); letter-spacing: var(--ls-label);
                  text-transform: uppercase; color: var(--surface-text-muted); margin-bottom: var(--space-2); }

  /* == component: to-top ==
     Back to top. An anchor, so it works with scripts off; JavaScript only
     decides when it is worth showing, and that hiding is scoped to html.js so
     the control is always present when scripts are not.

     Star over three stripes, in sand on field-dark. No red: section 7 reserves
     flag red for the primary conversion action and this is navigation. */
  .to-top {
    position: fixed;
    right: var(--space-5);
    bottom: var(--space-5);
    z-index: var(--z-nav);
    display: inline-grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: var(--radius-pill);
    border: var(--border-thin) solid var(--color-hairline-dark);
    background: var(--color-field-dark);
    box-shadow: var(--shadow-nav);
    text-decoration: none;
    --focus-ring: var(--focus-ring-dark);
    transition: background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out),
                opacity var(--dur-base) var(--ease-out);
  }
  .to-top:hover { background: var(--color-field); border-color: var(--color-sand); transform: translateY(-2px); }

  .to-top__mark { width: 27px; height: 27px; overflow: visible; }
  .to-top__star { fill: var(--color-sand); }
  .to-top__stripe { fill: none; stroke: var(--color-sand); stroke-width: 2.1; stroke-linecap: round; }
  /* The stripes fade downward, so the mark reads as rising rather than as a stack. */
  .to-top__stripe:nth-of-type(2) { opacity: 0.75; }
  .to-top__stripe:nth-of-type(3) { opacity: 0.5; }
  .to-top__stripe:nth-of-type(4) { opacity: 0.28; }

  /* Only hidden when scripts are running to show it again. */
  .js .to-top { opacity: 0; visibility: hidden; transform: translateY(8px); pointer-events: none; }
  .js .to-top.is-visible { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }

  /* ---------- Responsive ---------- */
  @media (max-width: 991px) {
    .nav__links, .nav__cta { display: none; }
    .nav__toggle { display: inline-flex; }
    .hero { padding-top: calc(var(--nav-height) + var(--space-5)); padding-bottom: var(--space-6); }
    .hero--home { padding-top: calc(var(--nav-height) + var(--space-5)); padding-bottom: var(--space-6); }
    .hero__grid { grid-template-columns: 1fr; gap: var(--space-7); }
    .panels { grid-template-columns: 1fr; }
    .points--grid { grid-template-columns: 1fr; }
    .points--grid .point:nth-last-child(2):nth-child(odd) { border-bottom: var(--border-thin) solid var(--surface-hairline); }
    .proc__steps { grid-template-columns: repeat(2, 1fr); }
    .paths { grid-template-columns: 1fr; }
    /* The rail folds into a strip across the top; the three facts keep their row. */
    .answer { grid-template-columns: 1fr; }
    .answer__label { flex-direction: row; align-items: center; padding: var(--space-3) var(--space-6); }
    .answer__label::before { width: 14px; height: 14px; }
    .answer__text { padding-inline: var(--space-6); }
    .answer__fact { padding: var(--space-5); }
    .split { grid-template-columns: 1fr; }
    .story { grid-template-columns: 1fr; gap: var(--space-7); }
    /* A story whose side column is its HEADLINE (the /territories "Do not see your city?" band)
       stacks as heading-then-text, so it gets heading spacing. The column gap, the lede's own top
       margin and the aside's padding added up to an 80px hole under a two-line headline. */
    .story:has(> .story__aside:first-child > .headline) { gap: var(--space-5); }
    .story:has(> .story__aside:first-child > .headline) .story__aside { padding-top: 0; }
    .story:has(> .story__aside:first-child > .headline) .story__body > .lede:first-child { margin-top: 0; }
    .split__side + .split__side { border-left: none; border-top: var(--border-thin) solid var(--surface-hairline); }
    .proc__steps--list { grid-template-columns: 1fr; }
    .stat-grid { grid-template-columns: repeat(2, 1fr); }
    .footer__grid { grid-template-columns: 1fr 1fr; }
    .final-cta__grid { grid-template-columns: 1fr; gap: var(--space-8); }
    .footer__legal { grid-template-columns: 1fr; }
  }

  @media (max-width: 767px) {
    .button { width: 100%; }
    .button--sm { width: auto; }
    .proc__steps, .stat-grid, .footer__grid, .form__row { grid-template-columns: 1fr; }
    .diagram { padding: var(--space-4); }
    .answer__label { padding-inline: var(--space-5); }
    .answer__text { padding-inline: var(--space-5); }
    .answer__facts { grid-template-columns: 1fr; }
    .answer__fact { padding: var(--space-4) var(--space-5); }
    .answer__fact + .answer__fact { box-shadow: inset 0 var(--border-thin) 0 var(--surface-hairline); }
    .final-cta__buttons { flex-direction: column; }
    .final-cta__grid { gap: var(--space-7); }
    .form { padding: var(--space-5); }
    .panel { padding: var(--space-5); }
    .snapshot { padding: var(--space-5); }
    .icon-well { width: 40px; height: 40px; }
    .to-top { right: var(--space-4); bottom: var(--space-4); width: 46px; height: 46px; }
    .to-top__mark { width: 23px; height: 23px; }
  }
}

/* =====================================================================
   UTILITIES
   ===================================================================== */
@layer utilities {
  /* == component: reveal ==
     Scroll-reveal, the way the customer site moves: content lifts and fades in
     as it arrives.

     The hidden state is scoped to `html.js`, which an inline script in the
     layout sets before first paint. With JavaScript off the class is never
     added, so every element renders visible and the page is complete — the
     animation is additive, never a precondition for reading anything.

     Anyone who has asked their system not to animate gets the finished state
     immediately, not a slower version of the motion. */
  .js .reveal,
  .js .reveal-group > * {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
    will-change: opacity, transform;
  }
  .js .reveal.is-visible,
  .js .reveal-group.is-visible > * {
    opacity: 1;
    transform: none;
    will-change: auto;
  }

  /* A group staggers its own children, so a row of cards arrives in order
     rather than all at once. Past the sixth child the delay stops growing. */
  .js .reveal-group.is-visible > *:nth-child(2) { transition-delay: 70ms; }
  .js .reveal-group.is-visible > *:nth-child(3) { transition-delay: 140ms; }
  .js .reveal-group.is-visible > *:nth-child(4) { transition-delay: 210ms; }
  .js .reveal-group.is-visible > *:nth-child(5) { transition-delay: 280ms; }
  .js .reveal-group.is-visible > *:nth-child(n+6) { transition-delay: 350ms; }

  @media (prefers-reduced-motion: reduce) {
    .js .reveal,
    .js .reveal-group > * { opacity: 1; transform: none; transition: none; }
  }

  .visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .stack > * + * { margin-top: var(--space-5); }
  .grid-two   { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); align-items: start; }
  .grid-three { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); }
  .mt-4 { margin-top: var(--space-4); }
  .mt-5 { margin-top: var(--space-5); }
  .mt-6 { margin-top: var(--space-6); }
  .mt-7 { margin-top: var(--space-7); }
  .mt-8 { margin-top: var(--space-8); }
  body[data-menu-open="true"] { overflow: hidden; }

  @media (max-width: 991px) {
    .grid-two, .grid-three { grid-template-columns: 1fr; }
  }
}

/* =====================================================================
   PROSE
   The rendering surface for authored Markdown. Markdig runs with
   DisableHtml(), so an author cannot introduce a class, a style or an
   element outside this vocabulary — which means styling the vocabulary
   IS styling every article. Design/ProseContractTests enforces the
   other direction: no element outside the allow-list may appear.
   ===================================================================== */
@layer prose {

  /* == component: prose == */
  .post-body {
    font-size: var(--text-md);
    line-height: var(--lh-prose);
    color: var(--color-ink);
  }

  .post-body > * + * { margin-top: var(--space-5); }

  .post-body h2 {
    font-size: var(--text-2xl);
    font-weight: 700;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-heading);
    margin: var(--space-8) 0 var(--space-4);
  }

  .post-body h3 {
    font-size: var(--text-xl);
    font-weight: 700;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug);
    margin: var(--space-7) 0 var(--space-3);
  }

  .post-body h4 {
    font-weight: 700;
    font-size: var(--text-lg);
    line-height: var(--lh-snug);
    margin: var(--space-6) 0 var(--space-3);
  }

  .post-body p { margin-bottom: var(--space-5); }

  .post-body a {
    color: var(--color-sand-ink);
    font-weight: 500;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
  }
  .post-body a:hover { color: var(--color-ink); }

  .post-body ul, .post-body ol { padding-left: var(--space-5); }
  .post-body li + li { margin-top: var(--space-2); }
  .post-body li::marker { color: var(--color-sand-ink); }

  .post-body blockquote {
    margin: var(--space-7) 0;
    padding: var(--space-5) var(--space-6);
    border-left: var(--border-thick) solid var(--color-sand-ink);
    background: var(--color-linen);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    font-size: var(--text-lg);
    line-height: var(--lh-snug);
  }

  .post-body img {
    width: 100%;
    border-radius: var(--radius-lg);
    margin: var(--space-7) 0;
  }

  .post-body figcaption {
    font-size: var(--text-sm);
    color: var(--color-ink-60);
    margin-top: var(--space-3);
  }

  .post-body hr {
    border: none;
    border-top: var(--border-thin) solid var(--color-hairline);
    margin: var(--space-8) 0;
  }

  /* Tables carry the comparison data. Doc 08: a competitor cell with no current
     FDD figure renders "See current FDD" rather than a blank or an estimate. */
  .post-body table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
    line-height: var(--lh-body);
  }
  .post-body th, .post-body td {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-thin) solid var(--color-hairline);
    text-align: left;
    vertical-align: top;
  }
  .post-body th {
    font-weight: 600;
    font-size: var(--text-xs);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--color-ink-60);
  }

  .post-body code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.9em;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    background: var(--color-linen);
  }
  .post-body pre {
    padding: var(--space-5);
    border-radius: var(--radius-md);
    background: var(--color-ink);
    color: var(--color-bone);
    overflow-x: auto;
  }
  .post-body pre code { background: none; padding: 0; color: inherit; }

  .post-body dt { font-weight: 700; margin-top: var(--space-4); }
  .post-body dd { margin-left: 0; color: var(--color-ink-60); }

  .post-body sup { font-size: 0.7em; vertical-align: super; }

  /* Legal and policy pages written in Razor rather than Markdown reuse the
     same heading vocabulary through these two classes. */
  .prose-h2 { font-size: var(--text-2xl); font-weight: 700; letter-spacing: var(--ls-tight);
              line-height: var(--lh-heading); margin-top: var(--space-8); }
  .prose-p { margin-top: var(--space-4); }

  /* == component: post-meta == */
  .post-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    font-size: var(--text-sm);
    color: var(--surface-text-muted);
    margin-top: var(--space-6);
  }
  .post-meta__item { display: flex; align-items: center; gap: var(--space-2); }
  .post-meta__item .icon { width: 15px; height: 15px; color: var(--surface-accent); }
  .post-meta__divider { width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: 0.5; }

  /* == component: toc == */
  .toc { font-size: var(--text-sm); }
  .toc__title {
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--surface-text-muted);
  }
  .toc ol { list-style: none; padding: 0; margin: var(--space-4) 0 0; }
  .toc li + li { margin-top: var(--space-2); }
  .toc li[data-level="3"] { padding-left: var(--space-4); }
  .toc a { text-decoration: none; color: var(--color-ink-60); }
  .toc a:hover { color: var(--color-ink); }

  /* == component: author-card == */
  .author-card {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-5);
    padding: var(--space-6);
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-lg);
    background: var(--color-white);
  }
  .author-card__name { font-weight: 700; }
  .author-card__role { font-size: var(--text-sm); color: var(--color-ink-60); }
  .author-card__bio { font-size: var(--text-sm); margin-top: var(--space-3); }

  /* == component: post-card == */
  .post-card {
    display: flex;
    flex-direction: column;
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-lg);
    background: var(--color-white);
    overflow: hidden;
    text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  }
  .post-card:hover { border-color: var(--color-sand-ink); box-shadow: var(--shadow-md); }
  .post-card__body { display: flex; flex-direction: column; flex: 1; padding: var(--space-5) var(--space-6) var(--space-6); }
  .post-card__category {
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--color-sand-ink);
  }
  .post-card__title {
    font-size: var(--text-lg);
    font-weight: 700;
    letter-spacing: var(--ls-tight);
    line-height: var(--lh-snug);
    margin-top: var(--space-2);
  }
  .post-card__excerpt { font-size: var(--text-sm); color: var(--color-ink-60); margin-top: var(--space-3); }
  .post-card__meta { font-size: var(--text-xs); color: var(--color-ink-60); margin-top: auto; padding-top: var(--space-4); }

  /* == component: inline-cta == */
  .inline-cta {
    margin: var(--space-8) 0;
    padding: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--color-ink);
  }
  .inline-cta__title { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); }
  .inline-cta__text { font-size: var(--text-sm); color: var(--surface-text-muted); margin-top: var(--space-3); }

  /* == component: comparison-table ==
     Template T5 §3 and spec §8e. Built on the prose table styles; scrolls at
     tablet width with a sticky first column; VETS's column carries a sand top
     rule and a linen fill. A missing figure is a link to the FDD lookup block,
     never a blank cell. */
  .comparison-table { margin: var(--space-6) 0 var(--space-8); overflow-x: auto; }
  .comparison-table table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); line-height: var(--lh-body); }
  .comparison-table__caption { caption-side: bottom; text-align: left; font-size: var(--text-xs); color: var(--color-ink-60); padding-top: var(--space-4); }
  .comparison-table th, .comparison-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-thin) solid var(--color-hairline);
    text-align: left; vertical-align: top; min-width: 160px;
  }
  .comparison-table thead th { font-size: var(--text-xs); font-weight: 600; letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--color-ink-60); border-bottom-color: var(--color-ink); }
  .comparison-table tbody th { font-weight: 600; min-width: 200px; }
  .comparison-table tbody th small { display: block; font-size: var(--text-xs); font-weight: 500; color: var(--color-ink-60); }
  .comparison-table tbody th:first-child, .comparison-table thead th:first-child { position: sticky; left: 0; background: var(--color-bone); z-index: 1; }
  .comparison-table__vets { background: var(--color-linen); }
  .comparison-table thead .comparison-table__vets { border-top: var(--border-thick) solid var(--color-sand); }
  .comparison-table__see-fdd { font-size: var(--text-xs); color: var(--color-sand-ink); white-space: nowrap; }
  .comparison-table__sources { font-size: var(--text-xs); color: var(--color-ink-60); margin: var(--space-4) 0 0; padding-left: var(--space-5); }
  .comparison-table__sources li + li { margin-top: var(--space-2); }

  /* == component: fdd-lookup ==
     Doc 08: never re-host or excerpt a competitor FDD. Link to the public state
     databases instead, and say plainly that a brand only appears in one if it
     registered there. */
  .fdd-lookup {
    margin: var(--space-8) 0;
    padding: var(--space-6);
    border: var(--border-thin) solid var(--color-hairline);
    border-radius: var(--radius-lg);
    background: var(--color-linen);
  }
  .fdd-lookup__title { font-size: var(--text-xl); font-weight: 700; letter-spacing: var(--ls-tight); }
  .fdd-lookup__list { list-style: none; padding: 0; margin: var(--space-5) 0 0; }
  .fdd-lookup__list li + li { margin-top: var(--space-4); }
  .fdd-lookup__how { font-size: var(--text-sm); color: var(--color-ink-60); margin-top: var(--space-1); }

  /* == component: path-chooser ==
     Doc 04 T7a: operator-education pages answer honestly for independents first.
     Three real options, one of which is not buying a franchise. */
  .path-chooser { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); margin: var(--space-8) 0; }
  .path-chooser__card { padding: var(--space-6); border-radius: var(--radius-lg); }
  .path-chooser__best { font-size: var(--text-xs); color: var(--color-ink-60); margin-top: var(--space-3); }

  @media (max-width: 991px) {
    .path-chooser { grid-template-columns: 1fr; }
  }

  @media (max-width: 767px) {
    /* A comparison table cannot shrink below readable; let it scroll with the
       first column pinned so the row label stays visible. */
    .post-body table { display: block; overflow-x: auto; white-space: nowrap; }
  }
}
