@charset "utf-8";

/* ==========================================================================
   Be Enabled Advocacy Alliance — beenabled.org
   Target: WCAG 2.2 Level AAA

   Every color pair in the token blocks below is verified by tools/contrast.mjs.
   Do not add a color without adding it to that script's PAIRS table.

   Contents
     1. Fonts
     2. Design tokens + themes
     3. Reset
     4. Base typography          (SC 1.4.8, 1.4.12)
     5. Focus system             (SC 2.4.7, 2.4.11, 2.4.12, 2.4.13)
     6. Skip links               (SC 2.4.1)
     7. Layout primitives
     8. Header + navigation      (SC 2.5.5, 2.4.8)
     9. Breadcrumbs              (SC 2.4.8)
    10. Hero + page intro
    11. Sections, cards, lists
    12. Buttons + calls to action
    13. Forms                    (SC 3.3.1-3.3.6)
    14. Footer
    15. Display settings panel   (SC 1.4.8)
    16. Decoration
    17. Utilities
    18. Motion                   (SC 2.3.3)
    19. Resource hub
    20. Forced colors + print
    21. Blue Envelope directory
    22. On-screen scroll buttons (SC 2.5.5, 2.5.8)
   ========================================================================== */

/* 1. Fonts ---------------------------------------------------------------- */
@import url("assets/fonts/fonts.css");

/* 2. Design tokens + themes ----------------------------------------------- */
:root {
  /* -- Light theme. Ratios are against --surface unless noted. ------------ */
  --surface:          #ffffff;
  --surface-raised:   #f4f8f7;
  --surface-sunken:   #e8f1ef;
  --surface-invert:   #17322f;
  --surface-footer:   #17322f;
  --text-footer:      #f4f8f7;  /* 12.79:1 on --surface-footer */

  --text:             #17322f;  /* 13.69:1 */
  --text-muted:       #2a5556;  /*  8.29:1  | 7.21:1 on sunken */
  --text-invert:      #f4f8f7;  /* 12.79:1 on --surface-invert */

  --brand:            #2f5d5e;  /*  7.37:1 — safe on --surface only */
  --brand-strong:     #234a4b;  /*  9.76:1  | 8.48:1 on sunken */
  --brand-contrast:   #ffffff;  /*  7.37:1 on --brand */

  --link:             #234a4b;  /*  9.76:1 */
  --link-visited:     #4a3d63;  /*  9.15:1 */

  --border:           #5f938c;  /*  3.48:1 — non-text (SC 1.4.11) */
  --border-strong:    #2f5d5e;  /*  7.37:1 */
  --border-subtle:    #cfe0dc;  /* decorative hairlines only */

  --accent:           #f09901;  /* amber — LARGE text or non-text only */
  --accent-text:      #17322f;  /*  6.04:1 on --accent — LARGE TEXT ONLY */
  --accent-ui:        #a86800;  /*  4.52:1 — amber that may carry meaning */
  --accent-warm:      #ef521d;  /* orange — non-text ONLY, never a text bg */
  --accent-coral:     #f9845b;  /* coral — decorative only in light theme */
  --sage:             #96bfba;  /* decorative fills + illustration only */

  --focus-a:          #17322f;  /* 13.69:1 on --surface */
  --focus-b:          #ffffff;  /* 13.69:1 on --focus-a */

  /* -- Presentation controls (SC 1.4.8). Overridden by the settings panel. */
  --ui-scale:   1;
  --lh:         1.6;
  --measure:    68ch;    /* well inside the 80-character ceiling */

  /* -- Spacing scale ----------------------------------------------------- */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.5rem;
  --space-6:  2rem;
  --space-7:  3rem;
  --space-8:  4rem;
  --space-9:  6rem;

  /* Paragraph spacing must be >= 1.5x line spacing (SC 1.4.8) */
  --para-space: calc(var(--lh) * 1.5 * 1em);

  /* -- Type ------------------------------------------------------------- */
  --font-body: "Atkinson Hyperlegible", ui-sans-serif, system-ui, -apple-system,
               "Segoe UI", Roboto, sans-serif;
  --font-head: "Quicksand", var(--font-body);

  --step--1: clamp(0.94rem, 0.92rem + 0.10vw, 1.00rem);
  --step-0:  clamp(1.06rem, 1.02rem + 0.22vw, 1.19rem);
  --step-1:  clamp(1.27rem, 1.19rem + 0.39vw, 1.50rem);
  --step-2:  clamp(1.52rem, 1.38rem + 0.65vw, 1.90rem);
  --step-3:  clamp(1.83rem, 1.61rem + 1.02vw, 2.40rem);
  --step-4:  clamp(2.19rem, 1.86rem + 1.55vw, 3.03rem);
  --step-5:  clamp(2.63rem, 2.14rem + 2.28vw, 3.82rem);

  /* -- Shape ------------------------------------------------------------ */
  --radius:      0.5rem;
  --radius-lg:   1rem;
  --radius-full: 9999px;
  --ring:        0.1875rem;   /* 3px — SC 2.4.13 needs >= 2px */
  --target:      2.75rem;     /* 44px — SC 2.5.5 Target Size (Enhanced) */

  color-scheme: light;
}

/* -- Dark theme.  Surface is #0b1817 rather than a lighter navy because
      coral only reaches 6.87:1 on #0f1f1e and must clear 7:1. ------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="contrast"]):not([data-theme="warm"]) {
    --surface:        #0b1817;
    --surface-raised: #142a28;
    --surface-sunken: #102220;
    --surface-invert: #e9f3f1;
    --surface-footer: #142a28;
    --text-footer:    #e9f3f1;

    --text:           #e9f3f1;  /* 16.03:1 */
    --text-muted:     #b9d2ce;  /* 11.05:1 */
    --text-invert:    #0b1817;

    --brand:          #96bfba;  /*  9.04:1  | 7.52:1 on raised */
    --brand-strong:   #b3d3ce;  /* 11.05:1 */
    --brand-contrast: #0b1817;  /*  9.04:1 on --brand */

    --link:           #96bfba;
    --link-visited:   #c9b8e6;  /* 10.32:1 */

    --border:         #5f938c;  /*  5.22:1 */
    --border-strong:  #96bfba;
    --border-subtle:  #21403c;

    --accent:         #f09901;  /*  8.00:1 — amber IS readable on dark */
    --accent-text:    #17322f;
    --accent-ui:        #f09901;
    --accent-warm:    #f9845b;  /*  7.33:1 */
    --accent-coral:   #f9845b;

    --focus-a:          #ffffff;
    --focus-b:          #0b1817;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --surface:        #0b1817;
  --surface-raised: #142a28;
  --surface-sunken: #102220;
  --surface-invert: #e9f3f1;
  --surface-footer: #142a28;
  --text-footer:    #e9f3f1;
  --text:           #e9f3f1;
  --text-muted:     #b9d2ce;
  --text-invert:    #0b1817;
  --brand:          #96bfba;
  --brand-strong:   #b3d3ce;
  --brand-contrast: #0b1817;
  --link:           #96bfba;
  --link-visited:   #c9b8e6;
  --border:         #5f938c;
  --border-strong:  #96bfba;
  --border-subtle:  #21403c;
  --accent:         #f09901;
  --accent-text:    #17322f;  /*  6.04:1 on --accent — LARGE TEXT ONLY */
  --accent-ui:        #f09901;
  --accent-warm:    #f9845b;
  --accent-coral:   #f9845b;
  --focus-a:          #ffffff;
  --focus-b:          #0b1817;
  color-scheme: dark;
}

/* -- High contrast. Pure black on white at 21:1. Amber and coral are
      dropped entirely; nothing decorative is allowed to carry meaning. --- */
:root[data-theme="contrast"] {
  --surface:        #ffffff;
  --surface-raised: #ffffff;
  --surface-sunken: #ffffff;
  --surface-invert: #000000;
  --surface-footer: #000000;
  --text-footer:    #ffffff;
  --text:           #000000;  /* 21:1 */
  --text-muted:     #000000;
  --text-invert:    #ffffff;
  --brand:          #000000;
  --brand-strong:   #000000;
  --brand-contrast: #ffffff;
  --link:           #00006e;  /* 15.30:1 */
  --link-visited:   #4b0072;  /* 13.11:1 */
  --border:         #000000;
  --border-strong:  #000000;
  --border-subtle:  #000000;
  --accent:         #000000;
  --accent-text:    #ffffff;  /* 21:1 — amber collapses to black here */
  --accent-ui:        #000000;
  --accent-warm:    #000000;
  --accent-coral:   #000000;
  --sage:           #000000;
  --focus-a:          #000000;
  --focus-b:          #ffffff;
  color-scheme: light;
}

/* -- Warm / low blue light. For light sensitivity and migraine. ---------- */
:root[data-theme="warm"] {
  --surface:        #fbf3e4;
  --surface-raised: #f6ead6;
  --surface-sunken: #f1e2c9;
  --surface-invert: #2b2416;
  --surface-footer: #2b2416;
  --text-footer:    #fbf3e4;
  --text:           #2b2416;  /* 13.31:1 */
  --text-muted:     #4d4128;  /*  8.05:1 */
  --text-invert:    #fbf3e4;
  --brand:          #1f4142;
  --brand-strong:   #1a3839;
  --brand-contrast: #fbf3e4;
  --link:           #234a4b;
  --link-visited:   #4a3d63;
  --border:         #8a7550;
  --border-strong:  #4d4128;
  --border-subtle:  #ded0b4;
  --accent:         #a35d00;
  --accent-text:    #fbf3e4;
  --accent-ui:        #a35d00;
  --accent-warm:    #a33b12;
  --accent-coral:   #a35d00;
  --sage:           #b9c9b4;
  --focus-a:          #2b2416;
  --focus-b:          #fbf3e4;
  color-scheme: light;
}

/* -- Presentation control values (SC 1.4.8) ----------------------------- */
:root[data-text-size="125"] { --ui-scale: 1.25; }
:root[data-text-size="150"] { --ui-scale: 1.5;  }
:root[data-text-size="200"] { --ui-scale: 2;    }

:root[data-line-height="175"] { --lh: 1.75; }
:root[data-line-height="200"] { --lh: 2;    }

/* 3. Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

:where(body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, ul, ol) {
  margin: 0;
}

/* Never remove list semantics from a list that carries meaning; these are the
   navigational lists only, and they keep their role via the surrounding nav. */
:where(ul, ol)[class] { list-style: none; padding: 0; }

img, svg, video { max-width: 100%; height: auto; display: block; }
svg { fill: currentColor; }

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

/* SC 1.4.12 Text Spacing — nothing that holds text may be height-capped or
   clipped, so user spacing overrides can always expand it. */
:where(p, li, dd, dt, h1, h2, h3, h4, blockquote, figcaption, label, td, th) {
  overflow-wrap: break-word;
}

/* 4. Base typography ------------------------------------------------------ */
html {
  /* Percentage, never px, so the browser's own font-size setting is honored. */
  font-size: calc(100% * var(--ui-scale));
  /* SC 2.4.12 — anchor jumps must never park a focused element under anything. */
  scroll-padding-block-start: var(--space-6);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background-color: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--lh);
  /* SC 1.4.8 item 3 — text is never justified. */
  text-align: left;
  hyphens: none;
  -webkit-font-smoothing: antialiased;
}

/* SC 1.4.8 item 2 — every run of prose is capped well inside 80 characters. */
:where(p, li, dd, blockquote, figcaption, .lede) { max-width: var(--measure); }

/* SC 1.4.8 item 4 — paragraph spacing >= 1.5x the line spacing. */
:where(p, ul, ol, dl, blockquote, figure, table, pre) + :where(p, ul, ol, dl, blockquote, figure, table, pre) {
  margin-block-start: var(--para-space);
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-head);
  font-weight: 700;
  /* Headings are not "blocks of text" under 1.4.8, so tighter leading is fine
     and is easier to scan at large sizes. */
  line-height: 1.15;
  text-wrap: balance;
  color: var(--brand);
  max-width: 24ch;
}

h1 { font-size: var(--step-5); letter-spacing: -0.02em; }
h2 { font-size: var(--step-3); margin-block-start: var(--space-8); }
h3 { font-size: var(--step-2); margin-block-start: var(--space-6); max-width: 34ch; }
h4 { font-size: var(--step-1); margin-block-start: var(--space-5); max-width: 40ch; }

:where(h1, h2, h3, h4) + * { margin-block-start: var(--space-4); }

.lede {
  font-size: var(--step-1);
  color: var(--text-muted);
  max-width: 56ch;
}

strong, b { font-weight: 700; }

blockquote {
  border-inline-start: 0.25rem solid var(--border);
  padding-inline-start: var(--space-5);
  font-size: var(--step-1);
}

/* -- Links ---------------------------------------------------------------
   The underline is not decoration. At AAA both body text and link text must
   clear 7:1, which squeezes them into one narrow luminance band: our link is
   only 1.40:1 against body text, far under the 3:1 that SC 1.4.1 demands when
   color is the sole differentiator. So links are ALWAYS underlined in prose.
   Never write `text-decoration: none` on a prose link. ------------------- */
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
  text-decoration-skip-ink: auto;
}
a:visited { color: var(--link-visited); }
a:hover   { text-decoration-thickness: 0.16em; }

/* 5. Focus system --------------------------------------------------------
   SC 2.4.13 Focus Appearance. Two-tone ring: the inner half always clears 3:1
   against every page surface, and the outer half always clears 3:1 against the
   inner half, so the ring stays visible on whatever it lands on — including on
   top of a brand-filled button. Total perimeter is 6px, well over the 2px
   minimum. Verified by tools/contrast.mjs. --------------------------------- */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--ring) solid var(--focus-a);
  outline-offset: 0;
  box-shadow: 0 0 0 calc(var(--ring) * 2) var(--focus-b);
  border-radius: 2px;
}

/* Older engines without :focus-visible still get a ring. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus {
  outline: var(--ring) solid var(--focus-a);
}
:where(a, button, summary, input, select, textarea, [tabindex]):focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}

/* SC 2.4.12 — a focused element scrolled into view must never sit under
   anything. The header is deliberately NOT sticky, and this is the backstop. */
:where(a, button, summary, input, select, textarea, [tabindex], h1, h2, h3, h4) {
  scroll-margin-block-start: var(--space-6);
}

/* main is focusable as a skip-link target but must not show a ring on click. */
main:focus { outline: none; }
main:focus-visible { outline: var(--ring) solid var(--focus-a); }

/* 6. Skip links ----------------------------------------------------------- */
.skip-links { position: absolute; top: 0; left: 0; z-index: 100; }

.skip-links a {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  /* Moved off-screen rather than display:none, so it stays focusable. */
  transform: translateY(-200%);
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding: var(--space-3) var(--space-5);
  background-color: var(--surface);
  color: var(--link);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius);
  text-decoration: underline;
  white-space: nowrap;
}
.skip-links a:focus { transform: translateY(0); }

/* Visually hidden, but still announced. Never use display:none for this. */
.visually-hidden:not(:focus):not(:active) {
  clip-path: inset(50%);
  height: 1px; width: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
}

/* 7. Layout primitives ---------------------------------------------------- */
.wrap {
  width: min(100% - (2 * var(--space-5)), 72rem);
  margin-inline: auto;
}
.wrap--narrow { width: min(100% - (2 * var(--space-5)), 48rem); }

.stack > * + * { margin-block-start: var(--space-5); }

.section { padding-block: var(--space-8); }
.section--tint { background-color: var(--surface-sunken); }
.section--raised { background-color: var(--surface-raised); }

.section > .wrap > h2:first-child { margin-block-start: 0; }

.grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

/* 8. Header + navigation --------------------------------------------------
   The header is deliberately NOT sticky. SC 2.4.12 (Focus Not Obscured,
   Enhanced) requires that NO part of a focused element is ever covered, and a
   sticky header cannot guarantee that across every engine and zoom level.
   scroll-padding gets you the AA version of this criterion, not the AAA one. */
.site-header {
  border-block-end: 1px solid var(--border-subtle);
  padding-block: var(--space-4);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  color: var(--brand);
  text-decoration: none;
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.1;
}
.brand:visited { color: var(--brand); }
.brand:hover .brand__name { text-decoration: underline; }
.brand__name { font-size: var(--step-0); max-width: 16ch; }
/* Each line is its own element. A bare text node sitting next to a
   display:block sibling is ambiguous markup, and contrast tools sample it
   unreliably. */
.brand__name b { display: block; font-size: var(--step-1); }
.brand__name span { display: block; }

/* -- Primary nav.  SC 2.5.5 caps how dense this can get: at a 44px minimum
      target with real padding, 5-6 items is the honest ceiling. Secondary
      destinations live in the footer, not here. --------------------------- */
.nav__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__link {
  display: inline-flex;
  align-items: center;
  /* SC 2.5.5 Target Size (Enhanced) — 44x44 CSS px, no exceptions here. */
  min-height: var(--target);
  min-width: var(--target);
  padding-inline: var(--space-4);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  font-family: var(--font-head);
  font-weight: 600;
}
.nav__link:visited { color: var(--text); }
.nav__link:hover { background-color: var(--surface-sunken); text-decoration: underline; }

/* SC 2.4.8 Location — the current page is marked in the markup, and the
   underline means it is not signaled by color alone (SC 1.4.1). */
.nav__link[aria-current="page"] {
  color: var(--brand-strong);
  background-color: var(--surface-sunken);
  text-decoration: underline;
  text-decoration-thickness: 0.19em;
  text-underline-offset: 0.22em;
}

/* -- Mobile disclosure. Built on <details>/<summary> so it opens and closes
      with zero JavaScript; app.js only adds Escape-to-close and the
      resize-cleanup that <details> lacks. ------------------------------- */
.nav-toggle { display: none; }
.nav-toggle > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding-inline: var(--space-4);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-head);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.nav-toggle > summary::-webkit-details-marker { display: none; }
.nav-toggle > summary::marker { content: ""; }
.nav-toggle__icon { width: 1.5rem; height: 1.5rem; flex: none; }
/* Closed shows the hamburger; open shows the X. */
.nav-toggle[open] .nav-toggle__icon--menu,
.nav-toggle:not([open]) .nav-toggle__icon--close { display: none; }

@media (max-width: 56rem) {
  .nav-toggle { display: block; }
  .site-nav { flex-basis: 100%; }
  .nav-toggle:not([open]) + .site-nav .nav__list { display: none; }
  .nav__list { flex-direction: column; align-items: stretch; }
  .nav__link { justify-content: flex-start; }
}

/* 9. Breadcrumbs ----------------------------------------------------------
   SC 2.4.8 Location. Links get a 44px box (SC 2.5.5) and the row gets enough
   leading that those boxes can never overlap when the trail wraps. */
.breadcrumb { padding-block: var(--space-4); }
.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--1);
}
.breadcrumb__list li { display: flex; align-items: center; gap: var(--space-2); }
.breadcrumb__list li + li::before {
  content: "";
  width: 0.5rem; height: 0.5rem;
  border-block-start: 2px solid var(--border);
  border-inline-end: 2px solid var(--border);
  transform: rotate(45deg);
  flex: none;
}
.breadcrumb__list a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-inline: var(--space-2);
}
.breadcrumb__list [aria-current="page"] {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-inline: var(--space-2);
  color: var(--text-muted);
}

/* 10. Hero + page intro --------------------------------------------------- */
.hero {
  padding-block: var(--space-8) var(--space-8);
  background-color: var(--surface-sunken);
  border-block-end: 0.375rem solid var(--brand);
  position: relative;
  overflow: hidden;
}
.hero__inner {
  display: grid;
  gap: var(--space-7);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 60rem) {
  .hero__inner { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
  /* A hero with no second column's worth of content (no decorative art)
     should not leave half its width empty. */
  .hero__inner > .stack:only-child { grid-column: 1 / -1; }
}
.hero h1 { color: var(--brand-strong); max-width: 18ch; }
.hero .lede { font-size: var(--step-2); color: var(--text); max-width: 46ch; }
.hero__art { justify-self: center; width: min(100%, 24rem); }

/* -- "In short" summary. This is the conforming supplemental version that
      SC 3.1.5 permits where accurate content cannot reach lower-secondary
      reading level on its own. Every page carries one. ------------------- */
.in-short {
  border: 2px solid var(--border);
  border-inline-start-width: 0.5rem;
  border-radius: var(--radius);
  padding: var(--space-5);
  background-color: var(--surface-raised);
}
.in-short > h2 {
  margin-block-start: 0;
  font-size: var(--step-0);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.in-short p { font-size: var(--step-1); }
.in-short > * + * { margin-block-start: var(--space-3); }

/* 11. Sections, cards, lists ---------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background-color: var(--surface);
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
}
.section--tint .card { background-color: var(--surface); }
.card > h3 { margin-block-start: 0; color: var(--brand-strong); }
.card p { max-width: none; }
/* The card title is the link. SC 2.4.9 forbids a trailing bare "Learn more",
   and a whole-card link with nested text fails link-purpose too. */
.card__link { text-decoration: underline; }
.card__meta { font-size: var(--step--1); color: var(--text-muted); }

/* Domain cards carry a color band. The band is decoration; the heading text
   and an icon always repeat the meaning, so nothing depends on color alone
   (SC 1.4.1). */
.card--domain { border-block-start-width: 0.5rem; }
.card--housing        { border-block-start-color: var(--brand); }
.card--healthcare     { border-block-start-color: var(--accent); }
.card--education      { border-block-start-color: var(--accent-warm); }
.card--transportation { border-block-start-color: var(--border); }
.card--money          { border-block-start-color: var(--brand-strong); }

.card__icon { width: 2.5rem; height: 2.5rem; color: var(--brand); flex: none; }

/* Definition lists — the correct structure for the domains and the glossary. */
.def-list { display: grid; gap: var(--space-5); }
.def-list dt {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--step-1);
  color: var(--brand-strong);
}
.def-list dd { margin-inline-start: 0; margin-block-start: var(--space-2); }

.tick-list { list-style: none; padding: 0; display: grid; gap: var(--space-4); }
/* The marker is positioned, NOT laid out with grid. A grid container turns
   every element child into its own grid item, which tears an inline <a> out of
   its sentence and drops it into the marker column. Positioning keeps the item
   as ordinary inline flow, so links stay inside the text where they belong. */
.tick-list li {
  position: relative;
  padding-inline-start: 2rem;
  max-width: var(--measure);
}
/* Add .tick-list--nav when the list items are bare links: those are navigation
   targets and need the full 44px box (SC 2.5.5). Plain .tick-list items, where
   a link sits inside a sentence, keep the inline exception and must NOT be
   padded — enlarging inline links makes their hit areas overlap across wrapped
   lines.
   Note: an :only-child selector CANNOT be used here. CSS ignores text nodes
   when deciding :only-child, so <li>text <a>x</a> text</li> would match it. */
.tick-list--nav li > a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
}

.tick-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.32em;
  width: 1.25rem; height: 1.25rem;
  border-radius: var(--radius-full);
  border: 0.3125rem solid var(--brand);
}

/* 12. Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  /* SC 2.5.5 — 44px floor, before padding. */
  min-height: var(--target);
  min-width: var(--target);
  padding: var(--space-3) var(--space-6);
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--step-0);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.btn:visited { color: inherit; }
.btn:hover { text-decoration: underline; text-underline-offset: 0.2em; }

.btn--primary {
  background-color: var(--brand);
  color: var(--brand-contrast);
  border-color: var(--brand);
}
.btn--primary:visited { color: var(--brand-contrast); }

.btn--secondary {
  background-color: transparent;
  color: var(--link);
  border-color: var(--border-strong);
}
.btn--secondary:visited { color: var(--link); }
.btn--secondary:hover { background-color: var(--surface-sunken); }

/* Amber only reaches 6.04:1 with its darkest legal label, which clears the
   4.5:1 large-text bar but NOT the 7:1 body-text bar. So this variant is
   locked to large text and must never be used at body size. (SC 1.4.6) */
.btn--accent {
  background-color: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
  font-size: var(--step-1);   /* >= 24px effective — required, not stylistic */
  font-weight: 700;
}
.btn--accent:visited { color: var(--accent-text); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-4); }

/* 13. Forms ---------------------------------------------------------------- */
.field { display: grid; gap: var(--space-2); max-width: 36rem; }
.field + .field { margin-block-start: var(--space-6); }

.field > label {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--step-0);
}
.field__req { color: var(--text-muted); font-weight: 400; }

/* SC 3.3.5 Help — hint text is always visible and never a placeholder, because
   placeholder text disappears the moment a user starts typing and is invisible
   to anyone who needs it most. */
.field__hint { font-size: var(--step--1); color: var(--text-muted); max-width: none; }

.field input, .field textarea, .field select {
  min-height: var(--target);
  padding: var(--space-3) var(--space-4);
  background-color: var(--surface);
  color: var(--text);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius);
  width: 100%;
}
.field textarea { min-height: 9rem; resize: vertical; }

.field--invalid input, .field--invalid textarea, .field--invalid select {
  border-color: var(--accent-warm);
  border-width: 0.1875rem;
}
/* The error is announced in text and marked with an icon; the red border is
   reinforcement, never the sole signal. (SC 1.4.1, 3.3.1) */
.field__error {
  display: flex;
  gap: var(--space-2);
  font-weight: 700;
  color: var(--link);
  font-size: var(--step--1);
}
.field__error:empty { display: none; }

.form-status { margin-block-start: var(--space-5); }
.form-status:empty { display: none; }

fieldset { border: 2px solid var(--border); border-radius: var(--radius); padding: var(--space-5); }
legend { font-family: var(--font-head); font-weight: 700; padding-inline: var(--space-2); }

.radio-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.radio-row label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding: var(--space-2) var(--space-4);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.radio-row input { width: 1.25rem; height: 1.25rem; min-height: 0; accent-color: var(--brand); }
.radio-row label:has(input:checked) {
  border-color: var(--brand-strong);
  border-width: 0.1875rem;
  background-color: var(--surface-sunken);
}

/* 14. Footer ---------------------------------------------------------------
   Footers get tall at AAA: every link needs a 44px row (SC 2.5.5). That is a
   deliberate trade, not an oversight. */
.site-footer {
  margin-block-start: var(--space-9);
  background-color: var(--surface-footer);
  color: var(--text-footer);
  padding-block: var(--space-8) var(--space-6);
  border-block-start: 1px solid var(--border);
}
.site-footer a { color: var(--text-footer); }
.site-footer a:visited { color: var(--text-footer); }
.site-footer h2, .site-footer h3 { color: var(--text-footer); }

.footer__grid {
  display: grid;
  gap: var(--space-7);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}
.footer__grid h3 {
  margin-block-start: 0;
  font-size: var(--step-0);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.footer__list { list-style: none; padding: 0; margin-block-start: var(--space-3); }
.footer__list a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-block: var(--space-1);
}
.footer__legal {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border);
  font-size: var(--step--1);
}

/* 15. Display settings panel ----------------------------------------------
   This is the mechanism for SC 1.4.8 item 1 (user-selectable foreground and
   background colors). Built from <details> + radio inputs so it needs no
   JavaScript to open, and no dragging (SC 2.5.7 — never an <input type=range>).
   With JS off the panel is hidden and a <noscript> note points to the
   equivalent browser and OS settings, which satisfy the same criterion by
   technique G156. */
.settings { margin-inline-start: auto; }
.settings > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding-inline: var(--space-4);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius);
  font-family: var(--font-head);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.settings > summary::-webkit-details-marker { display: none; }
.settings > summary::marker { content: ""; }
.settings__icon { width: 1.5rem; height: 1.5rem; flex: none; }

.settings__panel {
  margin-block-start: var(--space-4);
  padding: var(--space-5);
  background-color: var(--surface-raised);
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  display: grid;
  gap: var(--space-6);
}
@media (min-width: 48rem) {
  .settings__panel { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.settings__panel fieldset { border: 0; padding: 0; margin: 0; }
.settings__panel legend {
  padding: 0;
  font-size: var(--step-0);
  margin-block-end: var(--space-3);
}

/* 16. Decoration ------------------------------------------------------------ */
.rule {
  border: 0;
  block-size: 0.25rem;
  background-color: var(--border);
  margin-block: var(--space-7);
  max-width: 6rem;
}

/* 17. Utilities ------------------------------------------------------------ */
.text-muted { color: var(--text-muted); }
.center { text-align: left; }  /* guard: never introduce justify */
.flow > * + * { margin-block-start: var(--space-4); }
.no-bullet { list-style: none; padding: 0; }

/* External links are marked in text, not by an icon alone, and never open a
   new window — SC 3.2.5 forbids unrequested context changes. */
.ext__icon { width: 0.85em; height: 0.85em; display: inline; vertical-align: baseline; }

/* 18. Motion ---------------------------------------------------------------
   SC 2.3.3 Animation from Interactions. There is no motion in the default
   build. This is the standing guard for anything added later: it must clear
   BOTH the OS preference and the in-page override. */
@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;
  }
}
:root[data-motion="reduce"] *,
:root[data-motion="reduce"] *::before,
:root[data-motion="reduce"] *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  scroll-behavior: auto !important;
}

/* 19. Resource hub ---------------------------------------------------------
   Filters, topic chips, the List/Day/Month toggle, and listing cards for
   /resources/ and /resources/submit/. Everything below the palette block
   reuses the token names other components already read (--text, --brand,
   --surface, etc.), so overriding the tokens once re-themes every existing
   component — cards, chips, buttons, focus rings — with no changes to their
   own CSS. Same technique as .blue-envelope (§21).

   Gold is the focal color here — headings, the active view-toggle state,
   the card accent border — on warm cream surfaces, rather than the site's
   teal-tinted ones. Teal stays for body text and links: it's still the
   site's identity, just not what this page leads with. Scoped to .hub and
   only in the base light theme; switching to dark, high contrast, or warm
   falls back to the site's normal tokens, same as every other page. Every
   pairing below is registered in tools/contrast.mjs's themes list and
   checked at the ratio AAA requires for its role — see the numbers in the
   comment on each line.

   "Base light theme" has two spellings in the markup: Light chosen in the
   panel (data-theme="light"), or nothing chosen (no data-theme) on a device
   that is not asking for dark. The second block below handles the third
   case — nothing chosen on a device that IS dark — by handing every token
   back to the site's dark theme. Without it, this palette would paint
   white cards under the dark theme's near-white text. */
:root:not([data-theme]) .hub,
:root[data-theme="light"] .hub {
  --brand:          #7D4B00;  /*  7.30:1 on white, and white reaches 7.30:1 on it */
  --brand-strong:   #5C3700;  /* 10.49:1 on white */
  --brand-contrast: #ffffff;
  --surface:        #ffffff;
  --surface-raised: #FBF3E4;
  --surface-sunken: #F8ECD6;
  --border:         #8A6633;  /*  5.21:1 on white — non-text, needs 3:1 */
  --border-strong:  #7D4B00;  /* same as --brand */
  --border-subtle:  #E4CFA0;  /* decorative hairlines only, like the site default */
  --accent-ui:      #7D4B00;  /* amber that may carry meaning — same as --brand here */
  --accent-warm:    #A33B12;  /*  6.58:1 on white — non-text ornament ONLY, never a text background */
  /* --text, --text-muted, --link, --link-visited, --focus-a/b: deliberately
     NOT overridden — this page keeps the site's teal for those, verified
     against the new cream --surface-sunken above (was too dark against the
     site's --text-muted at the first cream picked; lightened until it
     cleared 7:1 rather than darkening the teal to fit). */
}
/* "Match my device" on a dark device: every token the block above sets goes
   back to the site's dark theme. `inherit` re-reads each one from the
   ancestor, so no color is repeated here — this list only has to name the
   same tokens. Chosen Dark, High contrast, and Warm never reach the light
   block at all, because they set data-theme. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .hub {
    --brand:          inherit;
    --brand-strong:   inherit;
    --brand-contrast: inherit;
    --surface:        inherit;
    --surface-raised: inherit;
    --surface-sunken: inherit;
    --border:         inherit;
    --border-strong:  inherit;
    --border-subtle:  inherit;
    --accent-ui:      inherit;
    --accent-warm:    inherit;
  }
}

.hub-filters {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.chip-group, .view-toggle { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.chip, .view-toggle button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--target);
  min-width: var(--target);
  padding-inline: var(--space-5);
  border: 2px solid var(--border-strong);
  border-radius: var(--radius-full);
  background-color: var(--surface);
  color: var(--text);
  font-family: var(--font-head);
  font-weight: 700;
  cursor: pointer;
}
.view-toggle button { border-radius: var(--radius); }

.chip[aria-pressed="true"], .view-toggle button[aria-pressed="true"] {
  background-color: var(--brand);
  color: var(--brand-contrast);
  border-color: var(--brand);
}

.day-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.day-nav h4 { margin: 0; }

.listing-list { display: grid; gap: var(--space-5); }

.listing-card {
  padding: var(--space-5);
  background-color: var(--surface);
  border: 2px solid var(--border);
  border-inline-start-width: 0.5rem;
  /* --accent-ui rather than --brand: an amber accent here reads as the
     calendar's own color, distinct from the teal used for body text and
     links everywhere else on the site. Already a verified 3:1 non-text
     pairing (see tools/contrast.mjs's PAIRS table) — nothing new to check. */
  border-inline-start-color: var(--accent-ui);
  border-radius: var(--radius-lg);
}
.listing-card > * + * { margin-block-start: var(--space-3); }
.listing-card > h3 { margin-block-start: 0; color: var(--brand-strong); }

.listing-card__tags { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.tag {
  display: inline-flex;
  align-items: center;
  font-size: var(--step--1);
  font-weight: 700;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background-color: var(--surface-sunken);
  color: var(--text);
}
.listing-card__meta { color: var(--text-muted); font-size: var(--step--1); }

.hub-empty {
  padding: var(--space-5);
  background-color: var(--surface-raised);
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
}

/* 20. Forced colors + print ----------------------------------------------- */
@media (forced-colors: active) {
  .btn, .card, .field input, .field textarea, .field select, .in-short {
    border: 2px solid ButtonBorder;
  }
  .nav__link[aria-current="page"] { forced-color-adjust: none; }
  :where(a, button, summary, input, [tabindex]):focus-visible {
    outline: 3px solid Highlight;
    box-shadow: none;
  }
  .status-badge, .state-card { border: 2px solid ButtonBorder; }
  .scroll-nav__btn { border: 2px solid ButtonBorder; }
}

@media print {
  .site-header, .site-footer, .settings, .skip-links, .nav-toggle, .scroll-nav { display: none; }
  body { background: #fff; color: #000; font-size: 12pt; }
  a { color: #000; }
  /* Link destinations are lost on paper, so print them. */
  main a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; }
  .card, .in-short, .state-card, .callout { border: 1pt solid #000; }
  h2, h3 { break-after: avoid; }
  p, li { orphans: 3; widows: 3; }
}

/* 21. Blue Envelope directory ----------------------------------------------
   Components for /blue-envelope/. Everything below the palette block reuses
   the token names other components already read (--text, --brand, --surface,
   etc.), so overriding the tokens once re-themes every existing component —
   cards, badges, buttons, focus rings — with no changes to their own CSS.

   Deliberately its own identity: blue, sky, white, and ochre, with a serif
   display face, rather than the site's teal/amber brand. Scoped to
   .blue-envelope and only in the base light theme — switching to dark, high
   contrast, or warm falls back to the site's normal tokens, same as every
   other page. Every pairing below is verified at the ratio AAA requires for
   its role; see the numbers in the comment on each line.

   Same two-part scoping as .hub (§19): the block below is the base light
   theme — Light chosen, or nothing chosen on a light device — and the
   @media block after it hands "nothing chosen on a dark device" back to the
   site's dark theme. */
:root:not([data-theme]) .blue-envelope,
:root[data-theme="light"] .blue-envelope {
  --text:           #0C2038;  /* 16.41:1 on white */
  --text-muted:     #2A3E58;  /* 10.89:1 on white · 8.70:1 on --surface-sunken · 9.84:1 on --surface-raised */
  --link:           #123D6E;  /* 10.95:1 on white */
  --link-visited:   #4B3562;  /* 10.58:1 on white · 8.46:1 on --surface-sunken */
  --brand:          #1D4E89;  /*  8.39:1 on white, and white reaches 8.39:1 on it */
  --brand-strong:   #123D6E;  /* same as --link: 10.95:1 on white */
  --brand-contrast: #ffffff;
  --surface:        #ffffff;
  --surface-raised: #EEF4FB;
  --surface-sunken: #DBE7F7;
  --surface-invert: #0C2038;
  --text-invert:    #ffffff;  /* 16.41:1 on --surface-invert */
  --border:         #4A6A94;  /*  5.55:1 on white — non-text, needs 3:1 */
  --border-strong:  #1D4E89;  /* same as --brand */
  --border-subtle:  #B7CBE6;  /* decorative hairlines only, like the site default */
  --accent-warm:    #D0812F;  /*  3.06:1 on white — non-text ornament ONLY, never a text background */
  --focus-a:        #0C2038;
  --focus-b:        #ffffff;
  --font-head: "Newsreader", Georgia, "Times New Roman", serif;
  color: var(--text);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .blue-envelope {
    --text:           inherit;
    --text-muted:     inherit;
    --link:           inherit;
    --link-visited:   inherit;
    --brand:          inherit;
    --brand-strong:   inherit;
    --brand-contrast: inherit;
    --surface:        inherit;
    --surface-raised: inherit;
    --surface-sunken: inherit;
    --surface-invert: inherit;
    --text-invert:    inherit;
    --border:         inherit;
    --border-strong:  inherit;
    --border-subtle:  inherit;
    --accent-warm:    inherit;
    --focus-a:        inherit;
    --focus-b:        inherit;
    --font-head:      inherit;
  }
}

.blue-envelope .kicker {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--step--1);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  border-inline-start: 0.375rem solid var(--accent-warm);
  padding-inline-start: var(--space-3);
}
.blue-envelope h2.accent-line::after {
  content: "";
  display: block;
  width: 3.5rem;
  height: 0.375rem;
  border-radius: var(--radius-full);
  background-color: var(--accent-warm);
  margin-block-start: var(--space-3);
}

/* -- Numbered steps ("How it works") ------------------------------------ */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.steps li {
  display: grid;
  grid-template-columns: 3rem 1fr;
  gap: var(--space-4);
  align-items: start;
  background-color: var(--surface);
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.steps li > div > strong { display: block; font-family: var(--font-head); font-size: var(--step-0); margin-block-end: var(--space-1); }
.steps li > div > p { margin: 0; max-width: none; color: var(--text-muted); }
.steps__num {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background-color: var(--brand);
  color: var(--brand-contrast);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--step-1);
  box-shadow: 0 0 0 4px var(--surface), 0 0 0 7px var(--accent-warm);
}

/* -- Hero cover graphic. Purely decorative (aria-hidden, see .hero__art
      elsewhere) and redundant with the real <h1> and lede next to it, so the
      text inside it is real DOM text — never baked into the image (SC 1.4.9)
      — just hidden from assistive tech rather than announced twice. ------ */
.cover {
  width: min(22rem, 100%);
  aspect-ratio: 3 / 4;
  background-color: var(--brand);
  color: var(--brand-contrast);
  border-radius: 0.375rem 0.875rem 0.875rem 0.375rem;
  position: relative;
  box-shadow: -2px 0 0 rgba(12, 32, 56, 0.35) inset, 14px 22px 0 rgba(12, 32, 56, 0.16);
  transform: rotate(2.5deg);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--space-6) var(--space-6) var(--space-6) var(--space-7);
}
/* The spine is drawn with a border rather than a background on purpose. A
   pseudo-element that carries a background stops axe from resolving the
   background behind .cover__title, and the site's own AAA scan then fails
   the cover text as "undeterminable". A border draws the same 2px line and
   is not a background. */
.cover::before {
  content: "";
  position: absolute;
  inset-inline-start: 0.875rem;
  inset-block: 0;
  width: 0;
  border-inline-start: 2px solid rgba(255, 255, 255, 0.18);
}
.cover__title {
  font-family: var(--font-head);
  font-size: var(--step-3);
  line-height: 1.05;
  font-weight: 600;
  margin: 0;
  max-width: none;
}
.cover__sub { font-size: var(--step-0); margin: var(--space-2) 0 0; max-width: none; }
.cover__art { width: 100%; height: auto; display: block; }
.cover__art-paper       { fill: var(--surface); }
.cover__art-lines       { fill: none; stroke: var(--surface-sunken); }
.cover__art-envelope    { fill: var(--surface-sunken); }
.cover__art-flap        { stroke: var(--brand); }
.cover__art-seal        { fill: var(--accent-warm); }
.cover__art-seal-hole   { fill: var(--surface-sunken); }
.cover__brand {
  font-size: var(--step--1);
  letter-spacing: 0.2em;
  font-weight: 700;
  margin: 0;
  max-width: none;
}

@media (max-width: 959px) {
  .cover { order: -1; width: min(16rem, 70%); margin-block-end: var(--space-4); }
}

.callout {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  border: 2px solid var(--accent-warm);
  border-inline-start-width: 0.5rem;
  border-radius: var(--radius);
  padding: var(--space-5);
  background-color: var(--surface-raised);
  margin-block-start: var(--space-6);
}
.callout__icon { width: 1.75rem; height: 1.75rem; color: var(--accent-warm); flex: none; }
.callout p { max-width: none; }
.callout > p, .callout > div { margin: 0; }

/* -- Jump list. Styled like nav links, not underlined prose links, because
      this is a navigation aid rather than a sentence (same exception the
      site already relies on for .nav__link and .footer__list a). --------- */
.state-index {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-block-start: var(--space-5);
  padding: 0;
  list-style: none;
}
.state-index a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-inline: var(--space-4);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  font-size: var(--step--1);
}
.state-index a:visited { color: var(--text); }
.state-index a:hover { background-color: var(--surface-sunken); text-decoration: underline; }

.state-list { display: grid; gap: var(--space-4); margin-block-start: var(--space-6); }
.state-list[hidden] { display: none; }

.state-card {
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
}
.state-card[hidden] { display: none; }
.state-card > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding: var(--space-4) var(--space-5);
  cursor: pointer;
  list-style: none;
}
.state-card > summary::-webkit-details-marker { display: none; }
.state-card > summary::marker { content: ""; }
.state-card__name { font-family: var(--font-head); font-weight: 700; font-size: var(--step-0); }
.state-card__abbr { color: var(--text-muted); font-weight: 400; font-size: var(--step--1); }
.state-card .chevron { margin-inline-start: auto; color: var(--text-muted); flex: none; transition: transform 0.15s; }
.state-card[open] .chevron { transform: rotate(180deg); }
.state-card__body {
  padding: var(--space-4) var(--space-5) var(--space-5);
  border-block-start: 1px solid var(--border-subtle);
}
.state-card__body > p:first-child, .state-card__body > dl:first-child { margin-block-start: 0; }

.chapter-group {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: 1px dashed var(--border-subtle);
}
.chapter-item { padding-block: var(--space-4); border-block-start: 1px solid var(--border-subtle); }
.chapter-item:first-of-type { border-block-start: 0; padding-block-start: 0; }

.status-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--step--1);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  border: 2px solid transparent;
  max-width: 100%;
}
/* Color is never the only signal here — the label text always names the
   status too (SC 1.4.1) — but each kind also gets a distinct fill/border
   treatment so the difference does not rely on reading the words either. */
.status-badge--law      { background-color: var(--brand);          color: var(--brand-contrast); }
.status-badge--agency   { background-color: var(--surface-invert); color: var(--text-invert); }
.status-badge--local    { background-color: var(--surface-sunken); color: var(--text); border-color: var(--border-strong); }
.status-badge--proposed { background-color: var(--surface-raised); color: var(--text-muted); border-style: dashed; border-color: var(--border); }
.status-badge--none     { background-color: var(--surface);        color: var(--text-muted); border-style: dashed; border-color: var(--border-subtle); }

@media (max-width: 480px) {
  .state-card > summary { flex-direction: column; align-items: flex-start; min-width: 0; }
  .state-card .chevron { position: absolute; inset-inline-end: var(--space-5); }
  .state-card > summary { position: relative; }
}

/* 22. On-screen scroll buttons (SC 2.5.5, 2.5.8) ---------------------------
   Opt-in from Display settings (§15). Created by app.js only while the
   setting is on, so nothing extra sits in the page for anyone who leaves
   it off — which is everyone until they turn it on. No scroll animation:
   see the "deliberately absent" note in app.js's file header. */
.scroll-nav {
  position: fixed;
  right: max(var(--space-4), env(safe-area-inset-right, 0px) + var(--space-2));
  bottom: max(var(--space-4), env(safe-area-inset-bottom, 0px) + var(--space-2));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: 40;
}
.scroll-nav__btn {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  border: 2px solid var(--border-strong);
  background-color: var(--surface-raised);
  color: var(--brand-strong);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  cursor: pointer;
}
.scroll-nav__btn:hover { background-color: var(--surface); }
.scroll-nav__btn svg { width: 22px; height: 22px; }
/* The buttons are position:fixed, which is exactly what SC 2.4.12 (Focus Not
   Obscured, Enhanced) warns about. While they are shown, anything scrolled
   into view by focus stops short of the strip they occupy. app.js sets the
   attribute together with the buttons. */
:root[data-scroll-buttons="on"] { scroll-padding-block-end: 9rem; }
