@charset "UTF-8";
/* ==========================================================================
   DNR ENGINEERING AND SURVEYING, LLC — styles.css
   --------------------------------------------------------------------------
   Design thesis: the website is a PLAN SET, not a brochure. Grid field,
   hairlines, station ticks, mono annotation, a title block. No photography.

   HOW TO EDIT THIS FILE (for a non-expert):
     1. Almost everything you'd want to change is a "token" (a --custom-property)
        in the @layer tokens block near the top. Change it there, not in the
        component. Colors, type sizes, and spacing all live there.
     2. The file is organized in @layer blocks, in this order:
          reset      browser normalization
          tokens     colors, type scale, spacing  <-- START HERE
          base       raw HTML elements (h1, p, a, table...)
          layout     page skeleton: .section, .container, grids
          components named blocks: .card, .btn, .hero, .cta ...
          motifs     the engineering-drawing decoration layer
          utilities  small single-purpose helpers
          overrides  motion, forced-colors, print
        Later layers win over earlier ones regardless of selector strength,
        so you can safely override a component from the utilities layer.
     3. NEVER change the five brand hex values (--navy, --orange, --gray,
        --ink, --paper). Everything else is derived from them with color-mix()
        so the palette stays closed.
     4. Survey Orange (#E87722) is a GRAPHICS color only. It is 2.96:1 on white
        and fails WCAG AA for text. For orange *text* use --orange-ink (on
        light grounds) or --orange-lift (on navy). See the tokens block.

   No build step. No framework. No external requests of any kind.
   ========================================================================== */

@layer reset, tokens, base, layout, components, motifs, utilities, overrides;

/* ==========================================================================
   1. RESET
   A small, modern, hand-written reset. No third-party normalize.
   ========================================================================== */
@layer reset {

  *, *::before, *::after { box-sizing: border-box; }

  /* Kill default margins; the .flow utility and base layer put them back
     deliberately, which is what keeps vertical rhythm predictable. */
  html, body, h1, h2, h3, h4, h5, h6, p, figure, blockquote,
  dl, dd, ol, ul, fieldset, legend, table, th, td, pre {
    margin: 0;
    padding: 0;
  }

  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scrollbar-gutter: stable;
    /* Offset in-page anchor targets so the sticky header never covers them. */
    scroll-padding-block-start: calc(var(--header-h) + var(--sp-5));
  }

  body { min-block-size: 100svb; }

  ul[class], ol[class] { list-style: none; }

  img, svg, video, canvas, picture {
    display: block;
    max-inline-size: 100%;
  }
  img, video { block-size: auto; }

  /* MUST come after the rule above. That rule is author-origin, so it beats
     the UA sheet's `[hidden] { display: none }` — without this, the
     <svg hidden aria-hidden="true"> symbol sprite at the top of every <body>
     renders as an empty 300x150 block and shoves the whole page down 150px. */
  [hidden] { display: none !important; }

  /* Form controls do not inherit type by default. Make them. */
  input, button, textarea, select {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
  }
  textarea { resize: vertical; }
  button { background: none; border: 0; cursor: pointer; }

  table { border-collapse: collapse; }

  /* Engineering terms must never be hyphen-broken across lines. */
  :where(p, li, dd, dt, h1, h2, h3, h4, td, th) { hyphens: none; }

  :where(a) { color: inherit; }

  /* Remove the default disclosure marker; .faq__q draws its own. */
  summary::-webkit-details-marker { display: none; }
}


/* ==========================================================================
   2. TOKENS  —  the only place you should be editing colors and sizes
   ========================================================================== */
@layer tokens {

  /* Registered so the service-card accent rule can animate smoothly.
     Purely an enhancement; unsupported browsers just snap. */
  @property --rule-scale {
    syntax: "<number>";
    inherits: false;
    initial-value: 0;
  }

  :root {

    /* ---------------------------------------------------------------
       COLOR SCHEME
       This site ships LIGHT ONLY, on purpose: the design is *paper*.
       A plan sheet is white. `only light` stops the browser from
       force-inverting form controls and scrollbars for dark-mode users.
       Do not add a dark theme — see the design direction, §8.
       --------------------------------------------------------------- */
    color-scheme: only light;

    /* --- LOCKED BRAND HEXES. Do not change these five. --- */
    --paper:   #FFFFFF;   /* White        */
    --gray:    #F2F2F2;   /* Soft Gray    */
    --ink:     #2B2D2F;   /* Charcoal     — body text, 13.8:1 on paper */
    --navy:    #1B365D;   /* Primary Navy — 12.1:1 on paper           */
    --orange:  #E87722;   /* Survey Orange — GRAPHICS ONLY, never text */

    /* --- Derived neutrals (tints/shades of the locked hues only) --- */
    --gray-2:      #FAFAFA;                                        /* faintest wash        */
    --ink-muted:   #5A5F66;                                        /* 6.4:1 on paper       */
    --navy-deep:   color-mix(in oklab, var(--navy) 86%, black);    /* button hover         */
    --navy-tint:   color-mix(in oklab, var(--navy)  7%, white);    /* panel wash           */
    --navy-line:   color-mix(in oklab, var(--navy) 18%, white);    /* decorative hairline  */
    --rule:        color-mix(in oklab, var(--navy) 26%, white);    /* structural hairline  */
    --field-line:  color-mix(in oklab, var(--navy) 62%, white);    /* 3.3:1 — form borders */
    --on-navy:     #FFFFFF;                                        /* 12.1:1 on navy       */
    --on-navy-mut: color-mix(in oklab, white 78%, var(--navy));    /* 7.8:1 on navy        */
    --on-ink-mut:  color-mix(in oklab, white 76%, var(--ink));     /* 7.9:1 on charcoal    */

    /* --- ORANGE: three tokens, NOT interchangeable ------------------
       --orange       #E87722  2.96:1 on white. GRAPHICS ONLY:
                              stroke, fill, border-color, background of a
                              non-text rule. If you ever write
                              `color: var(--orange)` that is a bug.
       --orange-ink   #A64E0B  5.6:1 on white, 5.0:1 on soft gray.
                              The ONLY orange allowed for text on a light
                              ground (eyebrows, small labels, links).
       --orange-lift  #F08A3C  4.9:1 on navy.
                              The ONLY orange allowed for text on navy.
       ---------------------------------------------------------------- */
    --orange-ink:  #A64E0B;
    --orange-lift: #F08A3C;

    /* --- Ground-aware aliases -------------------------------------
       Components read these, never the raw colors, so a single
       [data-ground] attribute reskins any block correctly. --------- */
    --ground:       var(--paper);
    --fg:           var(--ink);
    --fg-muted:     var(--ink-muted);
    --fg-heading:   var(--navy);
    --fg-accent:    var(--orange-ink);
    --hairline:     var(--rule);

    /* --- Focus ring. Orange fails the 3:1 non-text minimum on white,
           so the RING is navy (or white on dark) and orange is only the
           decorative halo. Never make the ring orange. --- */
    --focus:      var(--navy);
    --focus-halo: color-mix(in oklab, var(--orange) 55%, white);

    /* --- TYPE ------------------------------------------------------
       Two system stacks, zero network requests.
       --font-draft is the CAD-annotation face. It is used for roughly
       5% of glyphs and NEVER for prose: sheet numbers, station labels,
       eyebrows, credential lines, table headers, form labels, the title
       block, the footer legal line. Always uppercase + tracked.
       ---------------------------------------------------------------- */
    --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
    --font-draft: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco,
                  Consolas, "Liberation Mono", "Courier New", monospace;

    /* Fluid scale, 360px -> 1280px viewport ramp. */
    --step--2: clamp(0.75rem,   0.726rem + 0.11vw, 0.8125rem);  /* 12->13 legal, title block */
    --step--1: clamp(0.8125rem, 0.788rem + 0.11vw, 0.875rem);   /* 13->14 mono labels        */
    --step-0:  clamp(1rem,      0.951rem + 0.22vw, 1.125rem);   /* 16->18 body               */
    --step-1:  clamp(1.125rem,  1.052rem + 0.33vw, 1.3125rem);  /* 18->21 lede               */
    --step-2:  clamp(1.25rem,   1.152rem + 0.43vw, 1.5rem);     /* 20->24 h3, card title     */
    --step-3:  clamp(1.5rem,    1.255rem + 1.09vw, 2.125rem);   /* 24->34 h2                 */
    --step-4:  clamp(1.875rem,  1.533rem + 1.52vw, 2.75rem);    /* 30->44 h1                 */
    --step-5:  clamp(2.25rem,   1.614rem + 2.83vw, 3.875rem);   /* 36->62 hero display       */

    /* --- SPACE — 4px base. 24px (--sp-5) is the MODULE: the drafting
           grid background is 24px, so anything sized in --sp-5 snaps to
           visible linework. Prefer --sp-5 multiples. --- */
    --sp-1:  0.25rem;   /*   4 */
    --sp-2:  0.5rem;    /*   8 */
    --sp-3:  0.75rem;   /*  12 */
    --sp-4:  1rem;      /*  16 */
    --sp-5:  1.5rem;    /*  24  <- module */
    --sp-6:  2rem;      /*  32 */
    --sp-7:  3rem;      /*  48 */
    --sp-8:  4rem;      /*  64 */
    --sp-9:  6rem;      /*  96 */
    --sp-10: 8rem;      /* 128 */

    --section-y:    clamp(3rem, 7vw, 6.5rem);  /* standard section padding-block */
    --section-y-lg: clamp(4rem, 9vw, 8rem);    /* hero + CTA band                */
    --flow:         var(--sp-5);               /* default vertical rhythm        */

    /* --- STRUCTURE --- */
    --content-max: 72rem;                      /* 1152px                          */
    --gutter: clamp(1.25rem, 5vw, 3rem);
    --measure: 50ch;                           /* ~66 rendered chars. NB: 1ch is the '0' glyph (~11.3px at 18px), about 34% wider than the average character, so 62ch rendered ~83 cpl. */
    --header-h: 3.75rem;                       /* 60px mobile; 72px from 60rem up */

    /* --- SHAPE. Drafting is orthogonal: 2px, globally. No pills.
           No 12px cards. This one number is the cheapest signal that
           the site is not a template. --- */
    --r: 2px;

    /* --- MOTION. Two durations, two easings, nothing else. --- */
    --t-state: 180ms;
    --t-enter: 400ms;
    --ease-state: ease-out;
    --ease-enter: cubic-bezier(.2,.6,.2,1);

    /* Depth budget: exactly two shadows exist on this site.
       Drawings do not have drop shadows. */
    --shadow-panel: 0 12px 24px -12px rgb(27 54 93 / .22);
  }

  /* Ground contexts. Put data-ground on any .section, .cta, .card or
     .rail and every child recolors correctly with no extra classes. */
  [data-ground="gray"] {
    --ground: var(--gray);
    --hairline: color-mix(in oklab, var(--navy) 22%, var(--gray));
  }

  [data-ground="navy"] {
    --ground: var(--navy);
    --fg: var(--on-navy);
    --fg-muted: var(--on-navy-mut);
    --fg-heading: var(--on-navy);
    --fg-accent: var(--orange-lift);
    --hairline: color-mix(in oklab, white 32%, transparent);
    --field-line: color-mix(in oklab, white 55%, transparent);
    --focus: #FFFFFF;
    --focus-halo: var(--orange);
  }

  [data-ground="ink"] {
    --ground: var(--ink);
    --fg: #FFFFFF;
    --fg-muted: var(--on-ink-mut);
    --fg-heading: #FFFFFF;
    --fg-accent: var(--orange-lift);
    --hairline: color-mix(in oklab, white 28%, transparent);
    --focus: #FFFFFF;
    --focus-halo: var(--orange);
  }
}


/* ==========================================================================
   3. BASE — plain HTML elements
   ========================================================================== */
@layer base {

  body {
    font-family: var(--font-ui);
    font-size: var(--step-0);
    line-height: 1.62;
    color: var(--ink);
    background-color: var(--paper);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-wrap: break-word;
  }

  /* --- Headings --- */
  h1, h2, h3, h4, h5, h6 {
    color: var(--fg-heading);
    font-weight: 700;
    text-wrap: balance;
  }
  h1 { font-size: var(--step-4); line-height: 1.08; letter-spacing: -0.02em; }
  h2 { font-size: var(--step-3); line-height: 1.15; letter-spacing: -0.015em; }
  h3 { font-size: var(--step-2); line-height: 1.30; letter-spacing: -0.01em; font-weight: 600; }
  h4 { font-size: var(--step-1); line-height: 1.35; font-weight: 600; }
  h5, h6 { font-size: var(--step-0); font-weight: 600; }

  p { text-wrap: pretty; }          /* Firefox ignores this; harmless. */

  strong, b { font-weight: 600; color: var(--fg-heading); }
  em, i { font-style: italic; }

  small { font-size: var(--step--1); }

  /* --- Links --- */
  a {
    color: var(--navy);
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
    text-decoration-color: color-mix(in oklab, currentColor 45%, transparent);
    transition: text-decoration-color var(--t-state) var(--ease-state),
                color var(--t-state) var(--ease-state);
  }
  a:hover { text-decoration-color: currentColor; }
  [data-ground="navy"] a,
  [data-ground="ink"] a { color: var(--fg); }

  /* --- Focus ring. NON-NEGOTIABLE: every interactive element gets one.
         Navy on paper = 12.1:1. White on navy = 12.1:1. The orange is a
         decorative halo, never the contrast carrier. --- */
  :where(a, button, input, select, textarea, summary, [tabindex], [contenteditable]):focus-visible {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
    box-shadow: 0 0 0 6px var(--focus-halo);
    border-radius: var(--r);
  }
  :where(a, button, input, select, textarea, summary):focus:not(:focus-visible) { outline: none; }

  /* The skip-link target. It carries tabindex="-1" purely so assistive tech
     lands there; it is not an interactive control, so it must not draw the
     focus ring the [tabindex] branch of the rule above would give it. */
  main[tabindex="-1"]:focus,
  main[tabindex="-1"]:focus-visible { outline: none; box-shadow: none; }

  /* --- Lists inside prose --- */
  :where(.prose, .flow) > ul:not([class]),
  :where(.prose, .flow) > ol:not([class]) {
    padding-inline-start: 1.35em;
  }
  :where(.prose, .flow) > ul:not([class]) { list-style: disc; }
  :where(.prose, .flow) > ol:not([class]) { list-style: decimal; }
  :where(.prose, .flow) li + li { margin-block-start: var(--sp-2); }
  li::marker { color: var(--orange-ink); }

  /* --- Rules --- */
  hr {
    border: 0;
    border-block-start: 1px solid var(--hairline);
    margin-block: var(--sp-6);
  }

  /* --- Quotes / code --- */
  blockquote {
    border-inline-start: 3px solid var(--navy);
    padding-inline-start: var(--sp-5);
    color: var(--fg-muted);
  }
  code, kbd, samp {
    font-family: var(--font-draft);
    font-size: 0.92em;
  }

  /* --- Figures --- */
  figure { margin: 0; }
  figcaption {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    line-height: 1.5;
    letter-spacing: 0.06em;
    color: var(--fg-muted);
    margin-block-start: var(--sp-3);
  }

  /* --- Selection --- */
  ::selection { background: color-mix(in oklab, var(--orange) 30%, white); color: var(--ink); }
}


/* ==========================================================================
   4. LAYOUT — the page skeleton
   Every content block on every page is:
       <section class="section"><div class="container"> ... </div></section>
   Change the ground with data-ground="gray|navy|ink" on the .section.
   ========================================================================== */
@layer layout {

  .section {
    background-color: var(--ground);
    color: var(--fg);
    padding-block: var(--section-y);
    position: relative;
    isolation: isolate;   /* keeps decorative ::before layers behind content */
  }
  .section--lg  { padding-block: var(--section-y-lg); }
  .section--tight { padding-block: clamp(1.75rem, 4vw, 3rem); }

  /* A hairline between two sections that share a ground. */
  .section--ruled { border-block-start: 1px solid var(--hairline); }

  .container {
    inline-size: min(100% - (var(--gutter) * 2), var(--content-max));
    margin-inline: auto;
  }
  .container--narrow { --content-max: 46rem; }

  /* Section header: eyebrow + h2 + optional lede. Used at the top of
     nearly every .section. */
  .section-head {
    max-inline-size: 48rem;
    margin-block-end: var(--sp-7);
  }
  .section-head__eyebrow {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
    color: var(--fg-accent);
    margin-block-end: var(--sp-4);
  }
  .section-head__eyebrow::after {
    content: "";
    flex: 1 1 auto;
    block-size: 2px;
    background: var(--orange);
    max-inline-size: 4.5rem;
  }
  .section-head__title { font-size: var(--step-3); }
  .section-head__lede {
    font-size: var(--step-1);
    line-height: 1.5;
    color: var(--fg-muted);
    max-inline-size: 40rem;
    margin-block-start: var(--sp-4);
    text-wrap: pretty;
  }
  /* Two-column feature split. Stacks below 60rem. */
  .split {
    display: grid;
    gap: var(--sp-7);
    align-items: start;
  }
  @media (min-width: 60rem) {
    .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-8); }
    .split--weighted { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
    .split--reverse > .split__media { order: -1; }
  }
  .split__body { min-inline-size: 0; }
  .split__media { min-inline-size: 0; }

  /* Generic auto-fitting grid for tiles that have no component of their own. */
  .grid-auto {
    display: grid;
    gap: var(--sp-5);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  }

  /* Below-the-fold rendering hint. Safe: intrinsic size is only a guess
     for the scrollbar, and content-visibility auto never hides content
     from find-in-page or assistive tech. */
  .section--deferred {
    content-visibility: auto;
    contain-intrinsic-size: auto 40rem;
  }
}


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

  /* ---------------------------------------------------------------------
     5.1 SKIP LINK — first focusable element on every page.
     --------------------------------------------------------------------- */
  .skip-link {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: var(--sp-4);
    z-index: 200;
    transform: translateY(-120%);
    background: var(--navy);
    color: var(--on-navy);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    padding: var(--sp-3) var(--sp-5);
    border-radius: 0 0 var(--r) var(--r);
    transition: transform var(--t-state) var(--ease-state);
  }
  .skip-link:focus-visible { transform: translateY(0); }


  /* ---------------------------------------------------------------------
     5.2 SITE HEADER — sticky, white paper, no logo plate needed.
     Markup must be byte-identical on all five pages except for
     aria-current and the sheet badge value.
     --------------------------------------------------------------------- */
  .header-sentinel { block-size: 1px; margin-block-end: -1px; }

  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 100;
    background: var(--paper);
    border-block-end: 1px solid transparent;
    transition: border-color var(--t-state) var(--ease-state);
  }
  .site-header[data-scrolled] { border-block-end-color: var(--navy-line); }

  .site-header__inner {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    min-block-size: var(--header-h);
  }

  .brand {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    text-decoration: none;
    margin-inline-end: auto;
    padding-block: var(--sp-2);
  }
  .brand__logo {
    inline-size: 132px;
    block-size: auto;
    aspect-ratio: 900 / 497;
  }
  /* The mono micro-line beside the logo. Hidden on small screens. */
  .brand__micro {
    display: none;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-muted);
    padding-inline-start: var(--sp-4);
    border-inline-start: 1px solid var(--navy-line);
    white-space: nowrap;
  }

  .sheet-badge {
    display: none;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.1em;
    font-variant-numeric: tabular-nums;
    color: var(--ink-muted);
    border: 1px solid var(--navy-line);
    border-radius: var(--r);
    padding: 0.3em 0.6em;
  }

  /* --- Nav --- */
  .nav__list {
    display: flex;
    align-items: center;
    gap: clamp(var(--sp-4), 2vw, var(--sp-6));
  }
  .nav__link {
    display: block;
    position: relative;
    font-size: var(--step--1);
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--navy);
    text-decoration: none;
    padding-block: var(--sp-3);
  }
  .nav__link:hover { text-decoration: underline; text-underline-offset: 6px; }

  /* Current page: an orange top-rule PLUS an underline. Color is never
     the only indicator — that is a WCAG requirement, not a preference. */
  .nav__link[aria-current="page"] {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 6px;
  }
  .nav__link[aria-current="page"]::before {
    content: "";
    position: absolute;
    inset-block-start: -1px;
    inset-inline: 0;
    block-size: 3px;
    background: var(--orange);
  }

  /* Contact is the CTA-styled nav item. */
  .nav__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: 44px;
    padding-inline: var(--sp-5);
    background: var(--navy);
    color: var(--on-navy);
    font-size: var(--step--1);
    font-weight: 600;
    text-decoration: none;
    border-radius: var(--r);
    border-block-end: 3px solid var(--orange);
    transition: background-color var(--t-state) var(--ease-state);
  }
  .nav__cta:hover { background: var(--navy-deep); text-decoration: none; }
  .nav__cta[aria-current="page"]::before { content: none; }
  .nav__cta[aria-current="page"] { text-decoration: underline; text-underline-offset: 4px; }

  /* --- Mobile nav toggle --- */
  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    inline-size: 44px;
    block-size: 44px;
    padding-inline: 10px;
    border: 1px solid var(--navy-line);
    border-radius: var(--r);
    color: var(--navy);
  }
  .nav-toggle__bar {
    display: block;
    block-size: 2px;
    inline-size: 100%;
    background: currentColor;
  }
  .nav-toggle__bar:nth-child(2) { background: var(--orange); }

  /* Mobile: nav is a dropdown panel. Desktop rules are further down. */
  @media (max-width: 59.999rem) {
    .nav {
      position: absolute;
      inset-block-start: 100%;
      inset-inline: 0;
      background: var(--paper);
      border-block: 1px solid var(--navy-line);
      box-shadow: var(--shadow-panel);
      display: none;
    }
    .nav[data-open] {
      display: block;
      /* body gets overflow:hidden while this is open, so the panel itself must
         scroll — otherwise at 400% zoom (320x256 CSS px) four of the five nav
         links sit below the fold with no way to reach them. The cap is the
         space actually left under the header, not a flat svh fraction: the
         panel hangs off the bottom of a sticky header, so a plain 70svh
         overhangs the viewport by the header's own height. */
      max-block-size: calc(100svh - var(--header-h) - var(--sp-6));
      overflow-y: auto;
      overscroll-behavior: contain;
    }
    .nav__list {
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      inline-size: min(100% - (var(--gutter) * 2), var(--content-max));
      margin-inline: auto;
      padding-block: var(--sp-3);
    }
    .nav__list > li + li { border-block-start: 1px solid var(--navy-line); }
    .nav__link { padding-block: var(--sp-4); }
    /* On mobile the current-page marker becomes a leading-edge bar. */
    .nav__link[aria-current="page"]::before {
      inset-block: 0;
      inset-inline: calc(var(--gutter) * -1) auto;
      inline-size: 3px;
      block-size: auto;
    }
    .nav__cta { margin-block-start: var(--sp-4); }
  }

  /* Lock the page behind the open mobile panel. */
  @media (max-width: 59.999rem) {
    body:has(.nav[data-open]) { overflow: hidden; }
  }

  @media (min-width: 60rem) {
    :root { --header-h: 4.5rem; }
    .nav-toggle { display: none; }
    .nav { display: block; }
    .brand__logo { inline-size: 168px; }
    .brand__micro { display: block; }
  }
  @media (min-width: 80rem) {
    .sheet-badge { display: block; }
  }


  /* ---------------------------------------------------------------------
     5.3 BUTTONS
     Orange is NEVER a button surface: white-on-orange is 2.96:1 and
     navy-on-orange is 4.09:1. Both are too tight for a button label.
     --------------------------------------------------------------------- */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    min-block-size: 48px;
    padding: var(--sp-3) var(--sp-6);
    font-size: var(--step-0);
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    border-radius: var(--r);
    border: 1.5px solid transparent;
    transition: background-color var(--t-state) var(--ease-state),
                border-color var(--t-state) var(--ease-state),
                color var(--t-state) var(--ease-state);
  }
  .btn:hover { text-decoration: none; }

  /* Primary: navy fill, white label (12.1:1), 3px orange bottom rule. */
  .btn--primary {
    background: var(--navy);
    color: var(--on-navy);
    border-block-end: 3px solid var(--orange);
    padding-block-end: calc(var(--sp-3) - 1.5px);
  }
  .btn--primary:hover { background: var(--navy-deep); }

  /* Secondary: paper fill, navy hairline, navy label. */
  .btn--secondary {
    background: var(--paper);
    color: var(--navy);
    border-color: var(--navy);
  }
  .btn--secondary:hover { background: var(--navy-tint); }

  /* On a navy or charcoal ground: white fill, navy label. */
  .btn--on-dark {
    background: var(--paper);
    color: var(--navy);
    border-block-end: 3px solid var(--orange);
    padding-block-end: calc(var(--sp-3) - 1.5px);
  }
  .btn--on-dark:hover { background: var(--gray); }

  /* Text-only tertiary action. */
  .btn--quiet {
    min-block-size: 44px;
    padding-inline: 0;
    color: var(--navy);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: underline;
    text-underline-offset: 0.35em;
    text-decoration-color: var(--orange);
    text-decoration-thickness: 2px;
  }
  [data-ground="navy"] .btn--quiet,
  [data-ground="ink"]  .btn--quiet { color: var(--fg); }

  .btn-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4) var(--sp-5);
  }


  /* ---------------------------------------------------------------------
     5.4 HERO — paper ground. Every competitor opens on a dark blue or
     photo-scrimmed hero; a white drafting sheet is the differentiator,
     and it means the color logo never lands on navy.
     --------------------------------------------------------------------- */
  .hero {
    padding-block: var(--section-y-lg);
    position: relative;
    isolation: isolate;
    background-color: var(--paper);
    overflow: clip;
  }
  .hero__grid {
    display: grid;
    gap: var(--sp-7);
    align-items: center;
  }
  @media (min-width: 60rem) {
    .hero__grid {
      grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
      gap: var(--sp-8);
    }
  }
  .hero__copy { min-inline-size: 0; }

  /* On a phone the hero stacks, which pushes the starting-price panel below
     the fold. Tighten the block spacing so the panel's first rows show and
     the visitor has a reason to scroll. Desktop is unaffected. */
  @media (max-width: 59.99rem) {
    .hero { padding-block: var(--section-y); }
    .hero__grid { gap: var(--sp-5); }
    .motto {
      margin-block-start: var(--sp-5);
      padding-block-start: var(--sp-4);
    }
  }
  .hero__title {
    font-size: var(--step-5);
    line-height: 1.04;
    letter-spacing: -0.025em;
    color: var(--navy);
    margin-block-start: var(--sp-4);
  }
  .hero__lede {
    font-size: var(--step-1);
    line-height: 1.5;
    color: var(--ink-muted);
    max-inline-size: 34rem;
    margin-block-start: var(--sp-5);
    text-wrap: pretty;
  }
  .hero__actions { margin-block-start: var(--sp-7); }
  .hero__figure { min-inline-size: 0; }
  .hero__figure svg { inline-size: 100%; block-size: auto; }

  /* Motto chips: WE SHOW UP ◦ WE RESPOND ◦ WE GET IT RIGHT */
  .motto {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3) var(--sp-4);
    margin-block-start: var(--sp-6);
    padding-block-start: var(--sp-5);
    border-block-start: 1px solid var(--navy-line);
  }
  .motto__item {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--navy);
    white-space: nowrap;
  }
  .motto__item .ico { color: var(--navy); flex: none; }


  /* ---------------------------------------------------------------------
     5.5 SCOPE BAR — the three facts a public works director wants first,
     above the fold, on a 360px phone. Sits directly under the hero.
     --------------------------------------------------------------------- */
  .scopebar { padding-block: 0; }
  .scopebar__list {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  .scopebar__item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-block-size: 3.25rem;
    padding-block: var(--sp-3);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--navy);
  }
  .scopebar__item + .scopebar__item { border-block-start: 1px solid var(--navy-line); }
  .scopebar__item .ico { flex: none; color: var(--navy); }
  @media (min-width: 60rem) {
    .scopebar__list { flex-direction: row; align-items: stretch; }
    .scopebar__item {
      flex: 1 1 0;
      justify-content: center;
      text-align: center;
    }
    .scopebar__item + .scopebar__item {
      border-block-start: 0;
      border-inline-start: 1px solid var(--orange);
    }
  }


  /* ---------------------------------------------------------------------
     5.6 SERVICE CARD
     Sheet-coded (C-2.1 ...), hairline border, no shadow, 2px radius.
     Cards in a .card-grid use subgrid so titles, bodies and lists align
     across all cards regardless of copy length.
     --------------------------------------------------------------------- */
  .card-grid {
    display: grid;
    gap: var(--sp-5);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  }
  /* From 60rem up, cards sit side by side and share row tracks via subgrid,
     so the title / body / scope-list / link of every card line up no matter
     how much copy each one carries. Each .card MUST have exactly these five
     direct children, in this order:
       .card__head · .card__title · .card__body · .marklist · .card__foot
     `gap: normal` is what makes the subgrid inherit the parent's gutters —
     without it the tracks align but the gaps don't. */
  @media (min-width: 60rem) {
    @supports (grid-template-rows: subgrid) {
      .card-grid { row-gap: var(--sp-4); }
      .card-grid > .card {
        grid-row: span 5;
        display: grid;
        grid-template-rows: subgrid;
        gap: normal;
      }
    }
  }

  /* NOTE: do NOT add `container-type` to .card. Layout containment forces
     `grid-template-rows: subgrid` to compute to `none`, which silently
     breaks the cross-card row alignment above. */
  .card {
    position: relative;
    display: grid;
    align-content: start;
    gap: var(--sp-4);
    background: var(--paper);
    border: 1px solid var(--navy-line);
    border-radius: var(--r);
    padding: var(--sp-6);
    transition: border-color var(--t-state) var(--ease-state);
  }
  /* The 3px orange left rule that scales in on hover / keyboard focus.
     --rule-scale is set ON THE PSEUDO-ELEMENT (it is registered with
     inherits:false, so setting it on .card would not reach ::before). */
  .card::before {
    content: "";
    position: absolute;
    inset-block: -1px;
    inset-inline-start: -1px;
    inline-size: 3px;
    background: var(--orange);
    --rule-scale: 0;
    transform: scaleY(var(--rule-scale));
    transform-origin: top;
    transition: --rule-scale var(--t-state) var(--ease-state);
  }
  .card:hover::before,
  .card:has(a:focus-visible)::before { --rule-scale: 1; }
  .card:hover,
  .card:has(a:focus-visible) { border-color: var(--navy); }

  .card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
  }
  .card__code {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    font-variant-numeric: tabular-nums;
    color: var(--orange-ink);
  }
  .card__head .ico { color: var(--navy); flex: none; }
  .card__title { font-size: var(--step-2); color: var(--navy); }
  .card__body { color: var(--ink); margin: 0; }
  .card__foot { align-self: end; }
  .card__link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    min-block-size: 44px;
    font-weight: 600;
    color: var(--navy);
    text-decoration-color: var(--orange);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.3em;
  }
  @media (min-width: 40rem) {
    .card { padding: var(--sp-7); }
  }


  /* ---------------------------------------------------------------------
     5.7 MARK LIST — replaces every bulleted list in a component.
     Each <li> carries an inline <svg><use href="#cp"></svg> first child.
     --------------------------------------------------------------------- */
  .marklist { display: grid; gap: var(--sp-3); }
  /* Block flow, not grid: an <li> may legitimately hold an inline <a>, a
     <span>, and a bare text node. Under `display:grid` each of those becomes
     a separate grid item and the trailing text drops into the 1.25rem icon
     column, rendering one character per line. Take the icon out of flow
     instead so all inline content stays in a single block. */
  .marklist > li {
    display: block;
    position: relative;
    padding-inline-start: calc(1.25rem + var(--sp-3));
    font-size: var(--step-0);
    line-height: 1.5;
  }
  .marklist > li > .ico {
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: 0.28em;   /* optical baseline alignment */
    inline-size: 1.25rem;
    block-size: 1.25rem;
    color: var(--navy);
  }
  [data-ground="navy"] .marklist > li > .ico,
  [data-ground="ink"]  .marklist > li > .ico { color: var(--on-navy-mut); }
  .marklist--tight > li { font-size: var(--step--1); }


  /* ---------------------------------------------------------------------
     5.8 CREDENTIAL / TRUST STRIP — the highest-value block on the site.
     Full-bleed navy. Four cells, aligned on subgrid so the label / value /
     note rows line up across all four regardless of copy length.
     NOTE: never put a license number in visible text here. Numbers live in
     an HTML comment until they are confirmed.
     --------------------------------------------------------------------- */
  /* Anchors the .rail--top station ticks and buys clearance for them. */
  .credstrip {
    position: relative;
    padding-block-start: calc(var(--section-y) + var(--sp-2));
  }
  .credstrip__grid {
    display: grid;
    gap: var(--sp-6) var(--sp-7);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    margin-block-start: var(--sp-6);
  }
  /* Each .cred MUST have exactly three direct children, in this order:
     .cred__label · .cred__value · .cred__note — so the four cells align. */
  @media (min-width: 60rem) {
    @supports (grid-template-rows: subgrid) {
      .credstrip__grid { row-gap: var(--sp-3); }
      .credstrip__grid > .cred {
        grid-row: span 3;
        display: grid;
        grid-template-rows: subgrid;
        gap: normal;
      }
    }
  }
  .cred {
    display: grid;
    align-content: start;
    gap: var(--sp-3);
    border-block-start: 1px solid var(--hairline);
    padding-block-start: var(--sp-4);
  }
  .cred__label {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fg-accent);
  }
  .cred__value {
    font-size: var(--step-2);
    font-weight: 600;
    line-height: 1.25;
    color: var(--fg-heading);
    text-wrap: balance;
  }
  .cred__note {
    font-size: var(--step--1);
    line-height: 1.55;
    color: var(--fg-muted);
    margin: 0;
  }


  /* ---------------------------------------------------------------------
     5.9 PROCESS — five stations hung off an alignment rail.
     Desktop: horizontal rail across the top, cards below.
     Mobile:  vertical rail on the inline-start edge, cards to its right.
     --------------------------------------------------------------------- */
  .process { display: grid; gap: var(--sp-6); }
  .process__steps {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  }
  /* Three across, not five. The band lives in a plain .container, so its
     inline-size is capped at --content-max (72rem = 1152px) at EVERY viewport
     width. Five columns therefore compute to 211px forever, which is ~20
     characters per line against 18px body type — half the readable minimum.
     Three columns give ~362px. Five steps then read 3 + 2, which is a
     deliberate second rank on the rail rather than a 4 + 1 orphan.
     Do not add a wider breakpoint that restores 5-across: the container cap
     means there is no viewport at which five columns become readable. */
  @media (min-width: 60rem) {
    .process__steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); }
  }
  /* Each .step MUST have exactly four direct children, in this order:
     .step__sta · .step__title · .step__body · .step__deliverable */
  @media (min-width: 60rem) {
    @supports (grid-template-rows: subgrid) {
      .process__steps { row-gap: var(--sp-3); }
      .process__steps > .step {
        grid-row: span 4;
        display: grid;
        grid-template-rows: subgrid;
        gap: normal;
      }
    }
  }
  .step {
    display: grid;
    align-content: start;
    gap: var(--sp-3);
    padding-block-start: var(--sp-4);
    border-block-start: 2px solid var(--navy-line);
  }
  .step__sta {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    font-variant-numeric: tabular-nums;
    color: var(--orange-ink);
  }
  .step__title { font-size: var(--step-1); color: var(--navy); }
  .step__body { font-size: var(--step-0); color: var(--ink); margin: 0; }
  .step__deliverable {
    align-self: end;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    line-height: 1.5;
    letter-spacing: 0.06em;
    color: var(--ink-muted);
    border-block-start: 1px dashed var(--field-line);
    padding-block-start: var(--sp-3);
    margin: 0;
  }
  .step__deliverable b {
    display: block;
    color: var(--navy);
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }


  /* ---------------------------------------------------------------------
     5.10 BIO CARD — title-block plate, NOT a seal.
     Do not build a circular "MISSOURI PROFESSIONAL ENGINEER" ring device.
     That is a facsimile of a regulated seal.
     .bio__cred must NOT exist in the DOM for the unlicensed co-founder.
     --------------------------------------------------------------------- */
  .bio-grid {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  }
  .bio {
    container-type: inline-size;
    display: grid;
    gap: var(--sp-5);
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    border: 1px solid var(--navy-line);
    border-radius: var(--r);
    padding: var(--sp-6);
    background: var(--paper);
  }
  @container (max-width: 26rem) {
    .bio { grid-template-columns: minmax(0, 1fr); }
  }
  .bio__plate {
    position: relative;
    inline-size: 128px;
    block-size: 128px;
    display: grid;
    place-content: center;
    gap: var(--sp-2);
    text-align: center;
    background: var(--navy);
    border-radius: var(--r);
  }
  .bio__plate::before {           /* inner hairline, inset 6px */
    content: "";
    position: absolute;
    inset: 6px;
    border: 1px solid color-mix(in oklab, white 38%, transparent);
  }
  .bio__plate::after {            /* orange corner tick */
    content: "";
    position: absolute;
    inset-block-start: 6px;
    inset-inline-end: 6px;
    inline-size: 14px;
    block-size: 14px;
    border-block-start: 2px solid var(--orange);
    border-inline-end: 2px solid var(--orange);
  }
  .bio__initials {
    font-family: var(--font-draft);
    font-size: var(--step-3);
    font-weight: 500;
    letter-spacing: 0.08em;
    color: var(--on-navy);
  }
  .bio__abbr {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    color: var(--on-navy-mut);
  }
  .bio__body { display: grid; gap: var(--sp-3); min-inline-size: 0; }
  .bio__name { font-size: var(--step-2); color: var(--navy); }
  .bio__role {
    font-size: var(--step-0);
    font-weight: 600;
    color: var(--ink);
    margin: 0;
  }
  /* Credential line. ONLY ever used for the licensed principal. */
  .bio__cred {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--navy);
    border-block: 1px solid var(--navy-line);
    padding-block: var(--sp-2);
    inline-size: fit-content;
    padding-inline-end: var(--sp-5);
  }
  .bio__text { color: var(--ink); margin: 0; }


  /* ---------------------------------------------------------------------
     5.11 NOTES / CALLOUTS — a real drawing legend, with meaning.
       .note--general  45° hatch      = general note
       .note--legal    cross-hatch    = binding / scope / licensure note
       .note--planned  dotted, dashed = PROPOSED FUTURE CONDITION
     The Kansas-expansion note is the ONLY .note--planned on the site and
     it belongs at the very bottom of services.html. The drafting grammar
     itself says "not current," which is exactly what the law requires.
     --------------------------------------------------------------------- */
  .note {
    position: relative;
    border-inline-start: 3px solid var(--navy);
    border-radius: 0 var(--r) var(--r) 0;
    padding: var(--sp-5) var(--sp-6);
    background-color: var(--gray-2);
  }
  .note__label {
    display: block;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--navy);
    margin-block-end: var(--sp-3);
  }
  /* Keep the panel full-bleed but cap the text, or these run 100-130 cpl. */
  .note > p { margin: 0; max-inline-size: var(--measure); }
  .note > p + p { margin-block-start: var(--sp-4); }

  .note--general {
    background-image: repeating-linear-gradient(45deg,
      color-mix(in oklab, var(--navy) 9%, transparent) 0 1px, transparent 1px 8px);
  }
  .note--legal {
    border-inline-start-color: var(--orange);
    background-image:
      repeating-linear-gradient(45deg,
        color-mix(in oklab, var(--navy) 11%, transparent) 0 1px, transparent 1px 8px),
      repeating-linear-gradient(-45deg,
        color-mix(in oklab, var(--navy) 11%, transparent) 0 1px, transparent 1px 8px);
  }
  .note--legal .note__label { color: var(--orange-ink); }
  .note--planned {
    border-inline-start-style: dashed;
    border-inline-start-color: var(--field-line);
    background-image: radial-gradient(
      color-mix(in oklab, var(--navy) 16%, transparent) 1px, transparent 1px);
    background-size: 8px 8px;
  }
  .note--planned .note__label { color: var(--ink-muted); }
  [data-ground="navy"] .note,
  [data-ground="ink"] .note {
    background-color: color-mix(in oklab, white 10%, transparent);
    border-inline-start-color: var(--orange);
  }
  /* --orange-lift is 4.85:1 on undiluted navy, but a .note on a dark ground
     raises its own surface to rgb(50,74,109) with a 10% white wash, which
     drops orange-lift to 3.60:1. This lighter tint measures 5.02:1 on that
     surface and 6.1:1 on undiluted navy. Do not revert to --orange-lift. */
  [data-ground="navy"] .note__label,
  [data-ground="ink"] .note__label { color: #FFB077; }


  /* ---------------------------------------------------------------------
     5.12 FACT TILE — a commitment or a scope fact. NEVER a fabricated
     statistic, a project count, a client count, or "years of experience."
     If the number is not verifiable, do not build a tile for it.
     --------------------------------------------------------------------- */
  .fact-grid {
    display: grid;
    gap: var(--sp-5);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  }
  .fact {
    display: grid;
    align-content: start;
    gap: var(--sp-2);
    border: 1px solid var(--hairline);
    border-radius: var(--r);
    border-block-start-width: 3px;
    border-block-start-color: var(--orange);
    padding: var(--sp-5);
    background: var(--ground);
  }
  .fact__label {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fg-accent);
  }
  .fact__value {
    font-family: var(--font-draft);
    font-size: var(--step-1);
    font-weight: 500;
    line-height: 1.25;
    letter-spacing: 0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--fg-heading);
    text-wrap: balance;
  }
  .fact__note {
    font-size: var(--step--1);
    line-height: 1.5;
    color: var(--fg-muted);
    margin: 0;
  }


  /* ---------------------------------------------------------------------
     5.13 FAQ / DISCLOSURE — native <details>. No JS.
     --------------------------------------------------------------------- */
  .faq { display: grid; gap: 0; border-block-start: 1px solid var(--hairline); }
  .faq__item { border-block-end: 1px solid var(--hairline); }
  .faq__q {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-4);
    padding-block: var(--sp-5);
    font-size: var(--step-1);
    font-weight: 600;
    line-height: 1.35;
    color: var(--fg-heading);
    cursor: pointer;
    list-style: none;
    text-wrap: balance;
  }
  .faq__q::after {              /* +/− indicator, drawn in CSS */
    content: "";
    flex: none;
    inline-size: 14px;
    block-size: 14px;
    margin-block-start: 0.4em;
    margin-inline-start: auto;
    /* --fg-accent, not --orange: raw #E87722 is 2.96:1 on paper and this
       glyph is the only visual indicator of open/closed state (SC 1.4.11). */
    background:
      linear-gradient(var(--fg-accent) 0 0) center / 100% 2px no-repeat,
      linear-gradient(var(--fg-accent) 0 0) center / 2px 100% no-repeat;
  }
  /* Open: the vertical stroke is dropped, leaving a minus. */
  .faq__item[open] > .faq__q::after {
    background: linear-gradient(var(--fg-accent) 0 0) center / 100% 2px no-repeat;
  }
  .faq__q:hover { color: var(--navy); text-decoration: underline; text-underline-offset: 4px; }
  .faq__a {
    padding-block-end: var(--sp-5);
    max-inline-size: var(--measure);
    color: var(--fg);
  }
  .faq__a > * + * { margin-block-start: var(--sp-4); }

  /* Standalone disclosure (e.g. "What to include in an RFQ") */
  .disclosure {
    border: 1px solid var(--hairline);
    border-radius: var(--r);
    padding-inline: var(--sp-5);
  }
  .disclosure > summary {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding-block: var(--sp-4);
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--navy);
    cursor: pointer;
    list-style: none;
  }
  .disclosure > summary::after {
    content: "+";
    margin-inline-start: auto;
    color: var(--orange-ink);
    font-size: var(--step-1);
    line-height: 1;
  }
  .disclosure[open] > summary::after { content: "\2212"; }
  .disclosure__body { padding-block-end: var(--sp-5); max-inline-size: var(--measure); }
  .disclosure__body > * + * { margin-block-start: var(--sp-4); }


  /* ---------------------------------------------------------------------
     5.14 CTA BAND — one per page, maximum.
     --------------------------------------------------------------------- */
  .cta { position: relative; }
  /* Dark variant. The ground itself still comes from data-ground="navy";
     this only buys clearance for the .rail--top station ticks. */
  .cta--navy { padding-block-start: calc(var(--section-y) + var(--sp-2)); }
  .cta__inner {
    display: grid;
    gap: var(--sp-6);
    align-items: center;
  }
  @media (min-width: 60rem) {
    .cta__inner { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--sp-8); }
  }
  .cta__title { font-size: var(--step-3); color: var(--fg-heading); }
  .cta__sub {
    font-size: var(--step-1);
    line-height: 1.5;
    color: var(--fg-muted);
    max-inline-size: 36rem;
    margin-block-start: var(--sp-4);
  }
  .cta__actions { display: grid; gap: var(--sp-4); justify-items: start; }
  @media (min-width: 60rem) {
    .cta__actions { justify-items: end; }
  }
  .cta__mail {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;   /* WCAG 2.2 SC 2.5.8 minimum is 24px; this is a
                               primary conversion control, so give it 44. */
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.08em;
    color: var(--fg);
  }
  /* Paper variant carries a general-note hatch bar on its leading edge. */
  .cta--paper .cta__inner {
    border-inline-start: 3px solid var(--navy);
    padding-inline-start: var(--sp-6);
    background-image: repeating-linear-gradient(45deg,
      color-mix(in oklab, var(--navy) 8%, transparent) 0 1px, transparent 1px 8px);
    background-size: 8rem 100%;
    background-repeat: no-repeat;
  }


  /* ---------------------------------------------------------------------
     5.15 CONTACT — direct links block, then the form.
     The direct block goes ABOVE the form so the page is fully useful
     before any form endpoint is wired up.
     --------------------------------------------------------------------- */
  .direct {
    display: grid;
    gap: var(--sp-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  }
  .direct__link {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    min-block-size: 48px;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--hairline);
    border-radius: var(--r);
    background: var(--paper);
    text-decoration: none;
    transition: border-color var(--t-state) var(--ease-state),
                background-color var(--t-state) var(--ease-state);
  }
  .direct__link:hover { border-color: var(--navy); background: var(--navy-tint); }
  .direct__link .ico { flex: none; color: var(--navy); }
  .direct__meta { display: grid; gap: 2px; min-inline-size: 0; }
  .direct__label {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-muted);
  }
  .direct__value {
    font-size: var(--step-0);
    font-weight: 600;
    color: var(--navy);
    overflow-wrap: anywhere;
  }


  /* ---------------------------------------------------------------------
     5.16 FORM
     Labels are ALWAYS visible above the control. Never use a placeholder
     as a label. Validation styling uses :user-invalid so an error can
     never appear before the visitor has interacted with the field.
     --------------------------------------------------------------------- */
  .form { display: grid; gap: var(--sp-5); max-inline-size: 34rem; }

  .field { display: grid; gap: var(--sp-2); }
  .field__label {
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--navy);
  }
  .field__req { color: var(--orange-ink); font-weight: 700; }
  .field__hint {
    font-size: var(--step--1);
    line-height: 1.4;
    color: var(--ink-muted);
  }

  .field input,
  .field select,
  .field textarea {
    inline-size: 100%;
    min-block-size: 48px;
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--step-0);
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--field-line);
    border-radius: var(--r);
    transition: border-color var(--t-state) var(--ease-state),
                box-shadow var(--t-state) var(--ease-state);
  }
  .field textarea {
    min-block-size: 9rem;
    line-height: 1.6;
    field-sizing: content;      /* Chromium enhancement; degrades to rows= */
  }
  /* Custom chevron: two 8px triangles set 8px apart form a solid caret. */
  .field select {
    appearance: none;
    padding-inline-end: 3rem;
    background-image:
      linear-gradient(45deg,  transparent 50%, var(--navy) 50%),
      linear-gradient(135deg, var(--navy) 50%, transparent 50%);
    background-size: 8px 8px, 8px 8px;
    background-position: right 1.5rem center, right 1rem center;
    background-repeat: no-repeat;
  }
  .field input:hover,
  .field select:hover,
  .field textarea:hover { border-color: var(--navy); }

  /* Only after interaction. :user-invalid, not :invalid. */
  .field:has(:user-invalid) .field__label { color: var(--orange-ink); }
  .field :user-invalid {
    border-color: var(--orange-ink);
    border-inline-start-width: 3px;
  }

  /* Checkbox row */
  .field--check {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: var(--sp-3);
    padding-block: var(--sp-2);
  }
  .field--check input[type="checkbox"] {
    /* 24px is the WCAG 2.2 SC 2.5.8 minimum. Do not shrink this. */
    inline-size: 24px;
    block-size: 24px;
    min-block-size: 0;
    margin-block-start: 0.15em;
    padding: 0;
    accent-color: var(--navy);
  }
  .field--check label {
    font-size: var(--step-0);
    line-height: 1.5;
    color: var(--ink);
  }

  /* Honeypot. Off-screen but NOT display:none, so bots still fill it. */
  .hp {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .form__actions { margin-block-start: var(--sp-2); }
  .form__note {
    font-size: var(--step--1);
    line-height: 1.5;
    color: var(--ink-muted);
  }


  /* ---------------------------------------------------------------------
     5.17 TABLE — always wrapped in .table-wrap so it scrolls on a phone
     instead of blowing out the page width.
     --------------------------------------------------------------------- */
  .table-wrap {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    border: 1px solid var(--hairline);
    border-radius: var(--r);
  }
  .table {
    inline-size: 100%;
    min-inline-size: 32rem;
    font-size: var(--step--1);
    text-align: start;
  }
  .table caption {
    caption-side: top;
    text-align: start;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-muted);
    padding: var(--sp-4) var(--sp-5) var(--sp-3);
  }
  .table th,
  .table td {
    padding: var(--sp-3) var(--sp-5);
    border-block-end: 1px solid var(--hairline);
    vertical-align: top;
    text-align: start;
  }
  .table thead th {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--navy);
    background: var(--gray);
    border-block-end: 2px solid var(--navy-line);
    white-space: nowrap;
  }
  .table tbody tr:last-child > * { border-block-end: 0; }
  .table td { font-variant-numeric: tabular-nums; }

  /* .table--pairs — two-column label/value tables (the fee schedule). These
     fit a 320px phone, so the 32rem floor above would only clip the price
     column. Right-align the value and let the label wrap. */
  .table--pairs { min-inline-size: 0; }
  .table--pairs th,
  .table--pairs td { padding-inline: var(--sp-4); }
  .table--pairs td {
    text-align: end;
    white-space: nowrap;
    font-family: var(--font-draft);
    color: var(--navy);
    font-weight: 600;
  }
  .table--pairs thead th:last-child { text-align: end; }
  .table--pairs tbody th { font-weight: 400; }
  @media (max-width: 26em) {
    .table--pairs td { white-space: normal; }
  }


  /* ---------------------------------------------------------------------
     5.18 BREADCRUMB
     Must be wrapped in <nav aria-label="Breadcrumb">, and the current
     page carries aria-current="page".
     --------------------------------------------------------------------- */
  .crumbs { padding-block: var(--sp-5); }
  .crumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }
  .crumbs__list > li { display: flex; align-items: center; gap: var(--sp-3); }
  .crumbs__list > li + li::before {
    content: "/";
    color: var(--orange-ink);
  }
  .crumbs a {
    display: inline-flex;
    align-items: center;
    min-block-size: 24px;   /* WCAG 2.2 SC 2.5.8 minimum */
    color: var(--ink-muted);
    text-decoration: none;
  }
  .crumbs a:hover { color: var(--navy); text-decoration: underline; text-underline-offset: 4px; }
  .crumbs [aria-current="page"] { color: var(--navy); }


  /* ---------------------------------------------------------------------
     5.19 MAP FIGURE — Missouri is the ONLY filled shape. Kansas is a
     dashed, unfilled hairline with an HQ control point and nothing else.
     The "Missouri only" sentence must be adjacent VISIBLE body text, not
     small print. If the figure ever reads as a two-state service area,
     delete the Kansas shape.
     --------------------------------------------------------------------- */
  .map-figure { display: grid; gap: var(--sp-4); }
  .map-figure svg { inline-size: 100%; block-size: auto; max-inline-size: 34rem; }
  .map-figure__caption {
    font-family: var(--font-ui);
    font-size: var(--step-0);
    letter-spacing: 0;
    text-transform: none;
    color: var(--fg);
    max-inline-size: 34rem;
  }
  .map-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3) var(--sp-5);
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--fg-muted);
  }
  .map-legend > li { display: flex; align-items: center; gap: var(--sp-2); }
  .map-legend .ico { flex: none; color: var(--navy); }


  /* ---------------------------------------------------------------------
     5.20 SITE FOOTER — charcoal ground, one 2px orange hairline at the
     very top edge. That is the last of the orange budget.
     The logo MUST sit on an explicit white plate. This is the brand
     guide's most-violated rule.
     --------------------------------------------------------------------- */
  .site-footer {
    background: var(--ink);
    color: var(--fg);
    border-block-start: 2px solid var(--orange);
    padding-block: var(--sp-8) var(--sp-6);
  }
  .site-footer__grid {
    display: grid;
    gap: var(--sp-7);
  }
  @media (min-width: 40rem) {
    .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (min-width: 60rem) {
    .site-footer__grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr) auto; }
  }

  /* White plate behind the colour logo — required on any dark ground. */
  .footer-plate {
    display: inline-block;
    inline-size: fit-content;
    background: var(--paper);
    border-radius: var(--r);
    padding: var(--sp-3) var(--sp-4);
  }
  .footer-plate img { inline-size: 160px; block-size: auto; aspect-ratio: 900 / 497; }

  .footer-col { display: grid; align-content: start; gap: var(--sp-3); min-inline-size: 0; }
  .footer-head {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--orange-lift);
    padding-block-end: var(--sp-3);
    border-block-end: 1px solid color-mix(in oklab, white 22%, transparent);
  }
  .footer-list { display: grid; gap: var(--sp-1); }
  .footer-list a,
  .footer-contact a {
    display: inline-flex;
    align-items: center;
    min-block-size: 40px;
    color: var(--on-ink-mut);
    font-size: var(--step--1);
    text-decoration-color: color-mix(in oklab, currentColor 40%, transparent);
    overflow-wrap: anywhere;
  }
  .footer-list a:hover,
  .footer-contact a:hover { color: var(--paper); }
  .footer-contact { display: grid; gap: var(--sp-1); font-size: var(--step--1); }
  .footer-contact address {
    font-style: normal;
    color: var(--on-ink-mut);
    line-height: 1.6;
  }
  .footer-contact__label {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--on-ink-mut);
  }
  .footer-blurb {
    font-size: var(--step--1);
    line-height: 1.6;
    color: var(--on-ink-mut);
    max-inline-size: 30rem;
    margin-block-start: var(--sp-4);
  }

  .site-footer__legal {
    margin-block-start: var(--sp-7);
    padding-block-start: var(--sp-5);
    border-block-start: 1px solid color-mix(in oklab, white 18%, transparent);
    font-family: var(--font-draft);
    font-size: var(--step--2);
    line-height: 1.7;
    letter-spacing: 0.06em;
    color: var(--on-ink-mut);
  }


  /* ---------------------------------------------------------------------
     5.21 TITLE BLOCK — the sheet title block, in the footer.
     Real information only. NEVER fake project data, dates, or revisions.
     --------------------------------------------------------------------- */
  .title-block {
    inline-size: fit-content;
    min-inline-size: min(100%, 17rem);
    border: 1px solid color-mix(in oklab, white 30%, transparent);
    border-radius: 0;
    font-family: var(--font-draft);
    font-size: var(--step--2);
    line-height: 1.45;
    letter-spacing: 0.08em;
    font-variant-numeric: tabular-nums;
    color: var(--on-ink-mut);
    text-transform: uppercase;
  }
  .title-block th,
  .title-block td {
    border: 1px solid color-mix(in oklab, white 22%, transparent);
    padding: var(--sp-2) var(--sp-3);
    text-align: start;
    vertical-align: top;
  }
  .title-block th {
    font-weight: 500;
    color: var(--orange-lift);
    white-space: nowrap;
  }
  .title-block td { color: var(--paper); }
  .title-block .title-block__sheet {
    text-align: center;
    vertical-align: middle;
    font-size: var(--step-0);
    letter-spacing: 0.12em;
    color: var(--paper);
    white-space: nowrap;
  }
}


/* ==========================================================================
   6. MOTIFS — the engineering-drawing decoration layer
   All of these are decorative. Every instance in the HTML must carry
   aria-hidden="true" (and focusable="false" on inline SVG). The ONLY
   exception is the Missouri map, which is exposed to assistive tech with
   role="img" + <title> + <desc>.
   ========================================================================== */
@layer motifs {

  /* --- M1 GRID FIELD (drafting vellum) -------------------------------
     Applied as an absolutely-positioned decorative layer, never directly
     on an element that holds text. The mask is what keeps it from
     fighting the copy — it must fade out before it reaches a paragraph.
     Usage: <div class="field-grid" aria-hidden="true"></div> as the first
     child of a position:relative section.
     -------------------------------------------------------------------- */
  .field-grid {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    --g: 24px;    /* minor line — matches --sp-5 */
    --G: 120px;   /* major line — every 5th      */
    --ink-min: color-mix(in oklab, var(--navy) 10%, transparent);
    --ink-maj: color-mix(in oklab, var(--navy) 20%, transparent);
    background-image:
      linear-gradient(to right,  var(--ink-maj) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--ink-maj) 0 1px, transparent 1px),
      linear-gradient(to right,  var(--ink-min) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--ink-min) 0 1px, transparent 1px);
    background-size:
      var(--G) var(--G), var(--G) var(--G),
      var(--g) var(--g), var(--g) var(--g);
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  }
  /* On a phone the hero is very tall, so the same 55% stop would carry the
     grid all the way through the headline. Fade it out sooner. */
  @media (max-width: 59.999rem) {
    .field-grid {
      -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 14%, transparent 52%);
              mask-image: linear-gradient(to bottom, #000 0%, #000 14%, transparent 52%);
    }
  }
  .field-grid--up {
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 45%, transparent 100%);
            mask-image: linear-gradient(to top, #000 0%, #000 45%, transparent 100%);
  }
  [data-ground="navy"] .field-grid,
  [data-ground="ink"]  .field-grid {
    --ink-min: color-mix(in oklab, white 8%, transparent);
    --ink-maj: color-mix(in oklab, white 14%, transparent);
  }

  /* --- M2 CONTOURS ---------------------------------------------------
     Full-width topographic band pinned to the bottom of a section.
     -------------------------------------------------------------------- */
  .contours {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: -1;
    pointer-events: none;
    inline-size: 100%;
    block-size: clamp(180px, 34vw, 420px);
    color: var(--navy);
  }
  .contours svg { inline-size: 100%; block-size: 100%; }
  [data-ground="navy"] .contours,
  [data-ground="ink"]  .contours { color: #FFFFFF; opacity: .5; }

  /* --- M3 SURVEY MARKS ------------------------------------------------
     The icon set. <svg class="ico"><use href="#cp"></use></svg>
     Size is set here so page authors never need inline width/height.
     -------------------------------------------------------------------- */
  .ico {
    inline-size: 1.25rem;
    block-size: 1.25rem;
    fill: none;
    color: currentColor;
  }
  .ico--sm { inline-size: 1rem;   block-size: 1rem; }

  /* --- M4 STATION RAIL (the signature element) ------------------------
     A chainage rail. Ticks every 24px; a heavier orange tick every 120px.
     Built with gradients, NOT a stretched SVG — preserveAspectRatio="none"
     would distort the strokes.
     Usage: <div class="rail" aria-hidden="true"></div>
     Chainage labels go in a sibling <ul class="rail-stops"> which spaces
     them evenly with flexbox — no absolute positioning, no inline styles.
     -------------------------------------------------------------------- */
  .rail {
    position: relative;
    block-size: 13px;
    inline-size: 100%;
    border-block-start: 1px solid color-mix(in oklab, var(--navy) 40%, transparent);
    background-image:
      repeating-linear-gradient(to right,
        color-mix(in oklab, var(--navy) 32%, transparent) 0 1px, transparent 1px 24px),
      repeating-linear-gradient(to right,
        var(--orange) 0 1.5px, transparent 1.5px 120px);
    background-size: 100% 7px, 100% 13px;
    background-repeat: no-repeat;
    background-position: 0 0, 0 0;
  }
  [data-ground="navy"] .rail,
  [data-ground="ink"]  .rail {
    border-block-start-color: color-mix(in oklab, white 45%, transparent);
    background-image:
      repeating-linear-gradient(to right,
        color-mix(in oklab, white 34%, transparent) 0 1px, transparent 1px 24px),
      repeating-linear-gradient(to right,
        var(--orange) 0 1.5px, transparent 1.5px 120px);
  }
  /* Rail pinned to the top edge of a full-bleed band. */
  .rail--top {
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    border-block-start: 0;
  }
  /* Chainage labels, evenly distributed. No absolute positioning needed. */
  .rail-stops {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-block-start: var(--sp-2);
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.1em;
    font-variant-numeric: tabular-nums;
    color: var(--fg-muted);
  }
  /* --- M5 hatching lives on .note (see components 5.11) ---------------- */

  /* --- M6 NORTH ARROW -------------------------------------------------- */
  .north {
    display: inline-grid;
    justify-items: center;
    gap: 2px;
    color: var(--navy);
  }
  .north__label {
    font-family: var(--font-draft);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    color: currentColor;
  }
  .north svg { inline-size: 18px; block-size: auto; }

  /* --- M7 PLAN-AND-PROFILE FIGURE (hero) ------------------------------- */
  .figure-plan { inline-size: 100%; }
  .figure-plan svg { inline-size: 100%; block-size: auto; }
  .figure-plan .fp-label {
    font-family: var(--font-draft);
    font-size: 11px;
    letter-spacing: 1.2px;
    fill: var(--navy);
    fill-opacity: .72;
  }
  /* Below 40rem the plan register is dropped; profile only. */
  @media (max-width: 39.999rem) {
    .figure-plan .fp-plan { display: none; }
  }

  /* --- M8 title block lives on .title-block (see components 5.21) ------ */

  /* The one signature motion on the site: the hero alignment draws itself
     once, as if being drafted. 900ms, on load, never repeated. */
  .draw {
    stroke-dasharray: var(--draw-len, 1200);
    stroke-dashoffset: var(--draw-len, 1200);
  }
  @media (prefers-reduced-motion: no-preference) {
    .draw { animation: dnr-draw 900ms var(--ease-enter) 120ms forwards; }
  }
  @keyframes dnr-draw { to { stroke-dashoffset: 0; } }
}


/* ==========================================================================
   7. UTILITIES — small, single-purpose. Later layer, so they win.
   ========================================================================== */
@layer utilities {

  /* Vertical rhythm. Put .flow on any wrapper and its direct children
     get consistent spacing without per-element margins. */
  .flow > * + * { margin-block-start: var(--flow); }
  .flow--tight  { --flow: var(--sp-4); }

  /* Readable prose block. */
  .prose { max-inline-size: var(--measure); }
  .prose > * + * { margin-block-start: var(--sp-5); }
  .prose h2, .prose h3 { margin-block-start: var(--sp-7); }
  .prose h2:first-child, .prose h3:first-child { margin-block-start: 0; }

  .lede {
    font-size: var(--step-1);
    line-height: 1.5;
    color: var(--fg-muted);
    max-inline-size: 34rem;
    text-wrap: pretty;
  }

  /* Eyebrow / kicker above a heading. */
  .eyebrow {
    display: block;
    font-family: var(--font-draft);
    font-size: var(--step--1);
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fg-accent);
  }

  .visually-hidden {
    position: absolute !important;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .measure { max-inline-size: var(--measure); }
  .measure--narrow { max-inline-size: 34rem; }
  .nowrap { white-space: nowrap; }
  .mt-5 { margin-block-start: var(--sp-5); }
  .mt-6 { margin-block-start: var(--sp-6); }
  .mt-7 { margin-block-start: var(--sp-7); }

  /* Scroll-reveal hook.
     CRITICAL: the DEFAULT state is fully visible. The hidden state is
     applied ONLY under html.js, which script.js sets on its first line.
     No-JS visitors and slow-JS visitors must never see a blank page. */
  .js .reveal {
    opacity: 0;
    transform: translateY(12px);
  }
  @media (prefers-reduced-motion: no-preference) {
    .js .reveal {
      transition: opacity var(--t-enter) var(--ease-enter),
                  transform var(--t-enter) var(--ease-enter);
      transition-delay: var(--reveal-delay, 0ms);
    }
  }
  .js .reveal.is-visible { opacity: 1; transform: none; }
  /* Stagger helpers — put on siblings. */
  .reveal-2 { --reveal-delay: 60ms; }
  .reveal-3 { --reveal-delay: 120ms; }
}


/* ==========================================================================
   8. OVERRIDES — motion, high contrast, print
   ========================================================================== */
@layer overrides {

  /* --- Cross-document view transitions: see the top-level @view-transition
         rule at the very end of this file. Pure enhancement — Chromium and
         Safari animate the header/footer across page loads, Firefox just
         navigates instantly. --- */
  @media (prefers-reduced-motion: no-preference) {
    .site-header { view-transition-name: dnr-header; }
    .site-footer { view-transition-name: dnr-footer; }
    html { scroll-behavior: smooth; }
  }

  /* --- Reduced motion. The last three rules matter: a blanket duration
         kill without them would leave .reveal elements stuck at opacity 0
         and the hero alignment permanently undrawn. --- */
  @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;
    }
    .js .reveal { opacity: 1 !important; transform: none !important; }
    .draw { stroke-dashoffset: 0 !important; animation: none !important; }
    .card::before { transform: scaleY(1); }
  }

  /* --- Windows High Contrast Mode. Genuinely used in municipal and
         accessibility-audited environments — unlike dark mode. Strip the
         decorative layers and let system colors through. --- */
  @media (forced-colors: active) {
    .field-grid,
    .contours,
    .rail,
    .cta--paper .cta__inner { background-image: none; }
    .note { background-image: none; border-inline-start: 3px solid CanvasText; }
    .card,
    .bio,
    .fact,
    .direct__link,
    .title-block,
    .table-wrap,
    .disclosure { border: 1px solid CanvasText; }
    .btn { border: 1px solid ButtonText; forced-color-adjust: none; }
    .nav__link[aria-current="page"]::before { background: Highlight; }
    :focus-visible { outline: 3px solid Highlight; box-shadow: none; }
    .bio__plate { border: 1px solid CanvasText; }
    svg [fill="#E87722"], svg [stroke="#E87722"] { forced-color-adjust: none; }
  }

  /* --- PRINT --------------------------------------------------------
     A city administrator WILL print the services page and the contact
     page. Black text on white, no decoration, link URLs exposed, and
     no element allowed to split awkwardly across a page break.
     ------------------------------------------------------------------ */
  @media print {
    @page { margin: 16mm 14mm; }

    :root {
      --ground: #FFFFFF;
      --fg: #000000;
      --fg-muted: #333333;
      --fg-heading: #000000;
      --fg-accent: #000000;
      --hairline: #999999;
    }

    html, body {
      background: #FFFFFF !important;
      color: #000000 !important;
      font-size: 11pt;
      line-height: 1.45;
    }

    /* Hide navigation, decoration and calls to action. */
    .skip-link,
    .site-header,
    .nav,
    .nav-toggle,
    .sheet-badge,
    .field-grid,
    .contours,
    .rail,
    .rail-stops,
    .figure-plan,
    .hero__figure,
    .north,
    .cta,
    .btn,
    .btn-row,
    .header-sentinel,
    .footer-list,
    .crumbs { display: none !important; }

    .section,
    .hero,
    .site-footer,
    .card,
    .bio,
    .fact,
    .note,
    .cred,
    .credstrip,
    [data-ground] {
      background: #FFFFFF !important;
      color: #000000 !important;
      padding-block: 0.5rem !important;
      box-shadow: none !important;
    }

    h1, h2, h3, h4, .card__title, .cred__value, .fact__value,
    .bio__name, .section-head__title { color: #000000 !important; }

    .card, .bio, .fact, .note, .direct__link, .title-block, .table-wrap {
      border: 1px solid #999999 !important;
      background-image: none !important;
      break-inside: avoid;
    }

    .site-footer {
      border-block-start: 1px solid #000000 !important;
      padding-block-start: 0.75rem !important;
    }
    .footer-plate { padding: 0 !important; }
    .footer-plate img { inline-size: 120px; }
    .title-block th, .title-block td { border-color: #666666 !important; color: #000 !important; }

    /* Expose destinations. Skip in-page anchors and javascript: links. */
    a { text-decoration: underline; color: #000000 !important; }
    a[href^="http"]::after,
    a[href^="mailto:"]::after,
    a[href^="tel:"]::after {
      content: " (" attr(href) ")";
      font-family: var(--font-draft);
      font-size: 9pt;
      word-break: break-all;
    }
    a[href^="#"]::after { content: ""; }

    /* Open every disclosure so nothing is printed hidden. */
    details { display: block !important; }
    .faq__a, .disclosure__body { display: block !important; max-inline-size: none; }
    .faq__q::after, .disclosure > summary::after { display: none !important; }

    h1, h2, h3, h4 { break-after: avoid; }
    p, li, tr, img, figure { break-inside: avoid; }
    .prose, .measure, .lede, .faq__a { max-inline-size: none !important; }
  }
}

/* ==========================================================================
   9. CROSS-DOCUMENT VIEW TRANSITIONS
   Top level on purpose: @view-transition is only honoured at the top level
   of a stylesheet or inside a conditional group rule — not inside @layer.
   Chromium and Safari cross-fade between the five pages; Firefox ignores
   this entirely and navigates instantly. Nothing depends on it.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
