/* =========================================================================
   wheelchairdoc.com — the one stylesheet
   Contract: DESIGN.md. Read it before editing this file.

   RULES THIS FILE ENFORCES
   - Raw hex appears in exactly TWO places: the :root token block (§2) and the
     @media print token override (which uses the `black`/`white` keywords).
     Nowhere else. Ever.
   - --oxblood is SEMANTIC: denial risk only. It is used by .risk and by
     nothing else in this file. Do not add a second consumer.
   - No `outline: none`, anywhere, for any reason.
   - Specificity stays FLAT: single class, or a class plus one element/:is().
     No IDs, no chained-class selectors, no !important outside the two blocks
     that need it (reduced-motion and print hiding).
   - PADDING/MARGIN OWNERSHIP (this is the collision DESIGN.md warns about):
       .wrap    owns inline padding + max width   — never block padding
       .section owns block MARGIN                 — never padding at all
       .sheet   owns block + inline PADDING       — never margin
     They are all specificity (0,1,0), so if two of them set the same property
     source order silently decides the winner. Keeping the properties disjoint
     means they can be combined freely and can never cancel.
     DO NOT put .wrap and .sheet on the same element (both own padding-inline).
   ========================================================================= */


/* -------------------------------------------------------------------------
   1. Fonts — self-hosted, zero network requests (DESIGN.md §3)

   Measured from the actual files in assets/fonts/ on 2026-08-16:
     newsreader-var.woff2         variable  wght 200–800, opsz 6–72
     newsreader-var-italic.woff2  variable  opsz 6–72 ONLY — no wght axis
     publicsans-var.woff2         variable  wght 100–900
     publicsans-var-italic.woff2  STATIC    single instance, weight 400
     courierprime-400.woff2       STATIC    weight 400

   The italics therefore get a SINGLE font-weight, not a range. Declaring a
   range a face cannot honour makes the browser skip synthesis and render bold
   italic at regular weight — a silent visual bug. With one declared weight the
   browser synthesises the bold, which is correct and visible.

   Roman faces are clamped to the ranges DESIGN.md §3 specifies rather than the
   full axis range. This matters for Public Sans, whose *default instance is
   wght 100* — an unclamped declaration renders Thin if anything ever fails to
   set the axis.
   ------------------------------------------------------------------------- */

@font-face {
  font-family: 'Newsreader';
  src: url('fonts/newsreader-var.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Newsreader';
  src: url('fonts/newsreader-var-italic.woff2') format('woff2');
  font-weight: 400;          /* file carries no wght axis — see note above */
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Public Sans';
  src: url('fonts/publicsans-var.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Public Sans';
  src: url('fonts/publicsans-var-italic.woff2') format('woff2');
  font-weight: 400;          /* static instance — see note above */
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Courier Prime';
  src: url('fonts/courierprime-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}


/* -------------------------------------------------------------------------
   2. Tokens (DESIGN.md §2, §3, §4)
   ------------------------------------------------------------------------- */

:root {
  color-scheme: light;   /* one palette, tuned for AAA. No dark variant. */

  /* ground */
  --paper:    #FFFFFF;  /* the sheet — cards, the criterion column */
  --desk:     #E8EDF1;  /* cool pale ground the sheets sit on */
  --seal-tint:#E3EDEB;  /* quiet fill for seal-keyed blocks */

  /* ink */
  --ink:      #121820;  /* primary text */
  --ink-2:    #414D5C;  /* secondary text, captions */

  /* keyed */
  --seal:     #14504B;  /* links, primary action, the site's voice */
  --oxblood:  #7A1F2B;  /* SEMANTIC ONLY: denial risk / audit finding */

  /* lines */
  --edge:     #6B7A8A;  /* control borders — 4.40:1 on paper, 3.73:1 on desk */
  --rule:     #C9D3DC;  /* decorative hairlines ONLY, never a control border */

  /* type families — always a real fallback stack */
  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-body:    'Public Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'Courier Prime', ui-monospace, 'Courier New', monospace;

  /* type scale — fluid, root stays 16px, never px on body text */
  --step--1: clamp(0.875rem, 0.85rem + 0.12vw, 0.9375rem);  /* captions, citations */
  --step-0:  clamp(1.0625rem, 1.03rem + 0.18vw, 1.1875rem); /* body — deliberately large */
  --step-1:  clamp(1.25rem, 1.18rem + 0.35vw, 1.5rem);      /* lead, h3 */
  --step-2:  clamp(1.5rem, 1.36rem + 0.7vw, 2rem);          /* h2 */
  --step-3:  clamp(1.875rem, 1.6rem + 1.4vw, 2.75rem);      /* h1 */
  --step-4:  clamp(2.5rem, 2rem + 2.5vw, 4rem);             /* the criterion letter */

  /* layout */
  --measure: 68ch;
  --rail:    7.5rem;
  --gutter:  clamp(1.25rem, 4vw, 3rem);
  --page:    72rem;      /* outer container cap */

  /* spacing — use ONLY these nine steps */
  --space-025: 0.25rem;
  --space-05:  0.5rem;
  --space-075: 0.75rem;
  --space-1:   1rem;
  --space-15:  1.5rem;
  --space-2:   2rem;
  --space-3:   3rem;
  --space-4:   4rem;
  --space-6:   6rem;

  /* surface */
  --radius: 2px;
  --lift: 0 1px 2px rgb(18 24 32 / 0.06), 0 4px 12px rgb(18 24 32 / 0.04);

  /* motion — colour and outline only */
  --motion: 120ms ease;
}


/* -------------------------------------------------------------------------
   3. Reset
   Root font-size is NEVER set. Browser zoom and user font-size settings must
   work, and this audience uses them.
   ------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-block-start: var(--space-3);
}

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

body {
  /* Column flex so a short page (404, privacy) still puts the footer at the
     bottom of the window rather than halfway up it. */
  display: flex;
  flex-direction: column;
  min-block-size: 100vh;
  background: var(--desk);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.65;
  text-align: start;      /* never justify */
  overflow-wrap: break-word;
}

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

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

button { background: none; border: none; }

table { border-collapse: collapse; }

hr {
  border: 0;
  border-block-start: 1px solid var(--rule);
  margin-block: var(--space-2);
}


/* -------------------------------------------------------------------------
   4. Text
   ------------------------------------------------------------------------- */

:is(h1, h2, h3, h4, h5, h6) {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.15;
  color: var(--ink);
  text-wrap: balance;
  max-inline-size: var(--measure);
}

h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }
h4 { font-size: var(--step-0); }
h5, h6 { font-size: var(--step-0); }

:is(h2, h3, h4) { margin-block-start: var(--space-2); margin-block-end: var(--space-075); }
h1 { margin-block-end: var(--space-1); }

p { max-inline-size: var(--measure); }
p + p { margin-block-start: var(--space-1); }

:is(ul, ol) + p,
p + :is(ul, ol),
:is(h2, h3, h4) + :is(ul, ol) { margin-block-start: var(--space-1); }

/* A plain <ul>/<ol> is already correct — no class required. Markers are not
   stripped globally, because a stripped-by-default list is a trap for the
   next agent. Only the navigation lists opt out, below. */
:is(ul, ol) {
  max-inline-size: var(--measure);
  padding-inline-start: var(--space-15);
}
:is(ul, ol) li + li { margin-block-start: var(--space-05); }
li::marker { color: var(--ink-2); }

/* .list--plain — an unmarked list, for lists that are structural, not prose. */
.list--plain { list-style: none; padding-inline-start: 0; }

strong, b { font-weight: 700; }
em, i { font-style: italic; }

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

abbr[title] { text-decoration: underline dotted; text-underline-offset: 0.2em; }

a {
  color: var(--seal);
  text-decoration: underline;
  text-decoration-thickness: 0.07em;
  text-underline-offset: 0.16em;
  transition: color var(--motion);
}
a:hover { color: var(--ink); }

code, kbd, samp, pre { font-family: var(--font-mono); font-size: 0.95em; }


/* -------------------------------------------------------------------------
   5. Focus (DESIGN.md §5)
   Never removed. Never replaced with a box-shadow. --seal on --paper is
   9.22:1, far past the 3:1 the guideline requires.
   ------------------------------------------------------------------------- */

:focus-visible {
  outline: 3px solid var(--seal);
  outline-offset: 2px;
  border-radius: 2px;
}


/* -------------------------------------------------------------------------
   6. Layout scaffolding
   See the PADDING/MARGIN OWNERSHIP note at the top of this file.
   ------------------------------------------------------------------------- */

/* .wrap — centred container. Owns max width + inline padding only. */
.wrap {
  inline-size: 100%;
  max-inline-size: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* .wrap--narrow — reading-width container for prose-only pages. */
.wrap--narrow { max-inline-size: calc(var(--measure) + 2 * var(--gutter)); }

/* .section — vertical rhythm. Owns block MARGIN only. Never padding. */
.section { margin-block: var(--space-3); }
.section--tight { margin-block: var(--space-15); }
.section--loose { margin-block: var(--space-4); }

/* .stack — uniform vertical spacing between direct children. */
.stack > * + * { margin-block-start: var(--space-15); }
.stack--tight > * + * { margin-block-start: var(--space-075); }

/* .u-visually-hidden — present to assistive tech, absent on screen.
   Used to complete a shortened visible link label (WCAG 2.5.3 is satisfied
   because the visible text is a prefix of the accessible name). */
.u-visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* -------------------------------------------------------------------------
   7. Skip link (DESIGN.md §5) — first focusable element on every page
   ------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  inset-block-start: var(--space-05);
  inset-inline-start: var(--space-05);
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--space-1);
  background: var(--paper);
  color: var(--seal);
  border: 2px solid var(--seal);
  border-radius: var(--radius);
  font-weight: 700;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-1)));
}
.skip-link:focus { transform: translateY(0); }


/* -------------------------------------------------------------------------
   8. Site header + nav + language toggle
   ------------------------------------------------------------------------- */

.site-header {
  background: var(--paper);
  border-block-end: 1px solid var(--rule);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-075) var(--space-15);
  padding-block: var(--space-1);
}

/* min-block-size, not padding: the site name is a standalone navigation
   target and AAA target size (2.5.5) applies to it like any other. */
.site-name {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  line-height: 1.15;
  color: var(--ink);
  text-decoration: none;
  margin-inline-end: auto;
  transition: color var(--motion);
}
.site-name:hover { color: var(--seal); }

/* Two-row header at every width: name + language toggle, then the nav.
   Predictable at 320px and on a 72rem desktop alike, and it never squeezes
   five nav labels against the site name. */
.site-nav { inline-size: 100%; }

/* DESIGN.md §6 floor: targets ≥44×44 and ≥24px APART. The 0.75rem padding
   inside each link is part of the target, not separation between targets, so
   the gap has to carry the whole 24px on its own. */
.site-nav__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-15);
  margin-inline-start: calc(var(--space-075) * -1);
  max-inline-size: none;
  padding-inline-start: 0;
  list-style: none;
}
.site-nav__list li + li { margin-block-start: 0; }

.site-nav__link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--space-075);
  color: var(--seal);
  font-size: var(--step--1);
  font-weight: 600;
  text-decoration: none;
  border-block-end: 3px solid transparent;
  transition: color var(--motion), border-color var(--motion), background-color var(--motion);
}
.site-nav__link:hover { color: var(--ink); background: var(--seal-tint); }
.site-nav__link[aria-current="page"] {
  color: var(--ink);
  border-block-end-color: var(--seal);
}

/* .lang-toggle — links to the EQUIVALENT page in the other language,
   never to the other homepage. */
.lang-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 44px;
  min-inline-size: 44px;
  padding-inline: var(--space-075);
  color: var(--seal);
  background: var(--paper);
  border: 2px solid var(--seal);
  border-radius: var(--radius);
  font-size: var(--step--1);
  font-weight: 700;
  text-decoration: none;
  transition: color var(--motion), background-color var(--motion);
}
.lang-toggle:hover { color: var(--seal); background: var(--seal-tint); }


/* -------------------------------------------------------------------------
   9. Main + footer
   ------------------------------------------------------------------------- */

.site-main {
  display: block;
  flex: 1 0 auto;   /* pushes the footer to the bottom on short pages */
  padding-block: var(--space-2) var(--space-4);
}

.site-footer {
  background: var(--paper);
  border-block-start: 1px solid var(--rule);
  color: var(--ink-2);
  font-size: var(--step--1);
}

.site-footer__inner { padding-block: var(--space-2); }

.site-footer__nav { margin-block-end: var(--space-1); }

/* Same ≥24px target separation as the header nav (DESIGN.md §6). */
.site-footer__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-15);
  margin-inline-start: calc(var(--space-075) * -1);
  max-inline-size: none;
  padding-inline-start: 0;
  list-style: none;
}
.site-footer__list li + li { margin-block-start: 0; }

.site-footer__link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--space-075);
  color: var(--seal);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--motion), background-color var(--motion);
}
.site-footer__link:hover { color: var(--ink); background: var(--seal-tint); }


/* -------------------------------------------------------------------------
   10. .sheet — white card on the desk ground (DESIGN.md §5)
   Owns PADDING only. Never margin — use .section or .stack for spacing.
   ------------------------------------------------------------------------- */

.sheet {
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--lift);
  padding-block: var(--space-2);
  padding-inline: var(--gutter);
}

/* The sheet's own padding is the top spacing. A heading must not add to it. */
.sheet > :first-child { margin-block-start: 0; }

/* .sheet--part — one printed part of the appointment sheet ("For me",
   "For my doctor's office"). On screen it is an ordinary .sheet; in print
   each part starts on a fresh page. See the print block, §18. */


/* -------------------------------------------------------------------------
   11. .criterion — the annotated column (DESIGN.md §4)

   REQUIRED MARKUP. Other agents must emit exactly this shape:

     <div class="criterion">
       <div class="criterion__key">
         <p class="criterion__letter">C</p>
         <p class="cite">L33789 §(C)</p>
       </div>
       <div class="criterion__body">
         <h3>…</h3>
         <p>…</p>
         <div class="risk">…</div>
       </div>
     </div>

   Desktop: --rail margin column carrying the letter and citation, plus a
   --measure reading column.
   Below 900px (56.25em, so a user font-size bump collapses it too): one
   column, and .criterion__key becomes an inline label ABOVE the requirement.
   It must never become a cramped side-by-side.
   ------------------------------------------------------------------------- */

.criterion {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, var(--measure));
  column-gap: var(--gutter);
  row-gap: var(--space-1);
  align-items: start;
}

.criterion + .criterion {
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-2);
  border-block-start: 1px solid var(--rule);
}

.criterion__key { min-inline-size: 0; }

.criterion__body { min-inline-size: 0; }
.criterion__body > :is(h2, h3, h4):first-child { margin-block-start: 0; }

/* The signature element. Letters run A–O, but the LCD also keys sections as
   IV(B), II(1)/(2) and (a)–(b) — hence --long below. */
.criterion__letter {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-weight: 600;
  line-height: 1;
  color: var(--ink-2);
  max-inline-size: none;
  overflow-wrap: break-word;
  hyphens: none;
}

/* .criterion__letter--long — for multi-character section keys such as
   "IV(B)" or "II(1)/(2)", which overflow the rail at --step-4. */
.criterion__letter--long { font-size: var(--step-2); line-height: 1.1; }

/* .cite — the LCD citation, e.g. L33789 §(C) */
.cite {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.4;
  color: var(--ink-2);
  max-inline-size: none;
  overflow-wrap: anywhere;
}

/* A link that IS its own paragraph. Same reasoning as .cite a: it sits on its own
   line, so WCAG 2.5.5's inline-in-a-sentence exception does not cover it, and at
   22px it failed even 2.5.8 AA's 24px floor. Measured by the ada_audits battery,
   which sees standalone links that axe does not report at all.

   This needs a class rather than a selector: `p > a:only-child` would also match
   an inline link, because :only-child counts ELEMENTS and the surrounding prose
   is text nodes. */
.link-block a {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
}

/* A citation link sits on its own line, so WCAG 2.5.5's "inline in a sentence"
   exception does NOT apply to it. Measured at 16-36px tall before this rule --
   failing even 2.5.8 AA (24px), let alone the 44px this site targets.
   inline-flex gives the anchor real height without padding arithmetic. */
.cite a {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  color: var(--seal);
}

.criterion__letter + .cite { margin-block-start: var(--space-05); }


/* -------------------------------------------------------------------------
   12. .risk — the denial-risk callout (DESIGN.md §5)
   The ONLY consumer of --oxblood. Colour never carries the meaning alone:
   .risk__label prints the words "If this is missing".
   ------------------------------------------------------------------------- */

.risk {
  border-inline-start: 3px solid var(--oxblood);
  padding-inline-start: var(--space-1);
  padding-block: var(--space-025);
  margin-block-start: var(--space-15);
  max-inline-size: var(--measure);
}

.risk__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--oxblood);
  margin-block-end: var(--space-025);
  max-inline-size: var(--measure);
}

.risk :is(h2, h3, h4, h5, h6) { color: var(--oxblood); margin-block-start: 0; }

.risk p { color: var(--ink); }


/* -------------------------------------------------------------------------
   13. .lede — sits under an h1 (DESIGN.md §5)
   ------------------------------------------------------------------------- */

.lede {
  font-size: var(--step-1);
  line-height: 1.45;
  color: var(--ink-2);
  text-wrap: pretty;
  max-inline-size: var(--measure);
  margin-block-end: var(--space-15);
}


/* -------------------------------------------------------------------------
   14. Buttons (DESIGN.md §5) — min 44×44, ≥24px apart
   ------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-05);
  min-block-size: 44px;
  min-inline-size: 44px;
  padding-block: var(--space-05);
  padding-inline: var(--space-15);
  background: var(--seal);
  color: var(--paper);
  border: 2px solid var(--seal);
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--motion), border-color var(--motion), color var(--motion);
}
.btn:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.btn--ghost {
  background: var(--paper);
  color: var(--seal);
  border-color: var(--seal);
}
.btn--ghost:hover { background: var(--seal-tint); color: var(--seal); border-color: var(--seal); }

.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* .btn-row — buttons kept ≥24px apart, wrapping at 320px. */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-15);
  margin-block-start: var(--space-15);
}


/* -------------------------------------------------------------------------
   15. .disclaimer — the provenance block (DESIGN.md §7)
   Load-bearing, not fine print. Text is fixed; the revision date is rendered
   from SOURCE_VERSION in criteria.js and is never hardcoded in markup.
   ------------------------------------------------------------------------- */

.disclaimer {
  background: var(--seal-tint);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  padding-block: var(--space-1);
  padding-inline: var(--space-15);
  color: var(--ink);
  font-size: var(--step--1);
  line-height: 1.55;
  max-inline-size: var(--measure);
}

.disclaimer p { max-inline-size: none; }
.disclaimer :is(h2, h3, h4) {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  margin-block-start: 0;
  margin-block-end: var(--space-025);
}
.disclaimer a { color: var(--seal); }


/* -------------------------------------------------------------------------
   15b. The wizard (DESIGN.md §5, §6)

   prep.js builds a .wizard / .field / .option namespace that nothing in this
   file defined, so every one of the 50 answer controls rendered as a bare
   20px-tall label. Measured at 320/360/390px before this block existed:
   50 targets under 44px on /prep/. For an audience that includes people with
   tremor and limited dexterity, a 20px target is the difference between the
   tool working and not.

   Targets are >= 44px (DESIGN.md §6) and the WHOLE row is the target, not the
   13px input inside it.
   ------------------------------------------------------------------------- */

.wizard { margin-block: var(--space-2); }

.wizard__progress {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-2);
  margin-block-end: var(--space-075);
}

/* Live requirement count, sitting under the progress line. This is how a
   visitor sees that answering a question buys them something — the sheet is
   already printable, and each answer removes requirements that do not apply.
   Without it the questions look like a toll gate. */
.wizard__count {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--seal);
  margin-block-end: var(--space-1);
}

.wizard__step { margin-block-end: var(--space-15); }

/* The cane/walker interstitial. Deliberately NOT --oxblood: that token is
   reserved for denial risk (DESIGN.md §2), and this block is not a rejection.
   It is the criterion most claims turn on, stated honestly. */
[data-cane-note] {
  margin-block-start: var(--space-15);
}

[data-cane-note] h4 {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.25;
  margin-block-end: var(--space-05);
}

[data-cane-note] p + p { margin-block-start: var(--space-075); }

/* Focus lands here on every advance, so it must show a ring even though it is
   not natively focusable (prep.js sets tabindex="-1"). */
.wizard__step-title:focus-visible {
  outline: 3px solid var(--seal);
  outline-offset: 4px;
}

.wizard__step-intro,
.wizard__note {
  color: var(--ink-2);
  max-inline-size: var(--measure);
}

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

/* The element also carries .btn-row, which owns the ≥24px gap DESIGN.md §6
   requires. Never restate `gap` here: this is the one place on the site where a
   tremor or switch user hits adjacent controls repeatedly, and source order
   would silently win. */
.wizard__nav {
  margin-block-start: var(--space-15);
  padding-block-start: var(--space-1);
  border-block-start: 1px solid var(--rule);
}

.field { border: 0; margin: 0; padding: 0; min-inline-size: 0; }

.field__legend {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.25;
  color: var(--ink);
  padding: 0;
  margin-block-end: var(--space-05);
  max-inline-size: var(--measure);
}

.field__help {
  color: var(--ink-2);
  font-size: var(--step--1);
  margin-block-end: var(--space-1);
  max-inline-size: var(--measure);
}

/* Empty until prep.js fills it, so it must not reserve space or announce itself. */
.field__error:empty { display: none; }

.field__error {
  color: var(--oxblood);
  font-weight: 600;
  margin-block-end: var(--space-1);
  max-inline-size: var(--measure);
}

/* Fifty answer rows across the wizard, hit repeatedly by tremor and switch
   users. ≥24px apart, per DESIGN.md §6 — the borders are inside the target. */
.options {
  display: grid;
  gap: var(--space-15);
  /* Three separate things are needed to stop these rows overflowing at 320px
     with 200% text zoom, and the first two alone are NOT enough:
       1. min() on the cap — 68ch resolves far wider than the viewport at 2x root
       2. min-inline-size:0 on .option__text — a flex item will not shrink below
          its min-content width unless told to
       3. minmax(0, 1fr) here — a GRID ITEM's default min-width is `auto`, not 0,
          so the li refuses to shrink and pushes the row out regardless of 1 and 2
     Measured on /es/preparacion/ (Spanish labels are longer, so it surfaced
     there first): 20px of horizontal scroll until (3) was added. */
  grid-template-columns: minmax(0, 1fr);
  max-inline-size: min(var(--measure), 100%);
  list-style: none;
  margin: 0;
  padding: 0;
}

.option {
  display: flex;
  align-items: flex-start;
  gap: var(--space-075);
  min-block-size: 44px;
  padding: var(--space-075) var(--space-1);
  background: var(--paper);
  border: 2px solid var(--edge);
  border-radius: var(--radius);
  cursor: pointer;
}

.option:hover { border-color: var(--seal); }

.option__input {
  inline-size: 1.375rem;
  block-size: 1.375rem;
  flex: none;
  /* optical alignment with the first line of label text */
  margin-block-start: 0.15em;
  accent-color: var(--seal);
}

.option__text {
  color: var(--ink);
  /* A flex item will not shrink below its min-content width unless told to, so
     a long unbroken label pushes the row past the viewport. */
  min-inline-size: 0;
  overflow-wrap: break-word;
}

/* :has() keeps the state on the row rather than the 13px input, so the whole
   row reads as selected. Colour is never the only signal -- the native control
   still shows its own checked state. */
.option:has(.option__input:checked) {
  border-color: var(--seal);
  background: var(--seal-tint);
}

.option:has(.option__input:focus-visible) {
  outline: 3px solid var(--seal);
  outline-offset: 2px;
}

.sheet__title {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.15;
  margin-block: var(--space-2) var(--space-075);
}

/* Ruled space to write in. Decorative, so it is hidden from assistive tech in
   the markup; here it only needs to look like a line you can write on.

   The box holds one <hr> per line and GROWS with them — it carries no height of
   its own. A fixed height here clipped the lines and overlapped the block
   underneath, on screen and on the printed sheet, which is the deliverable.
   Each rule takes its writing room ABOVE itself, because that is where the pen
   goes; the generic `hr` margins do not apply inside this box. */
.write-lines {
  display: block;
  margin-block-end: var(--space-15);
}

.write-lines hr {
  margin-block: var(--space-2) 0;
  border-block-start: 1px solid var(--rule);
}


/* -------------------------------------------------------------------------
   16. Responsive — the rail collapses (DESIGN.md §4)
   900px expressed in em so a raised default font size collapses it too.
   ------------------------------------------------------------------------- */

@media (max-width: 56.25em) {

  .criterion {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-075);
  }

  /* The key becomes an INLINE LABEL sitting ABOVE the requirement. */
  .criterion__key {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-05) var(--space-075);
    padding-block-end: var(--space-05);
    border-block-end: 1px solid var(--rule);
  }

  .criterion__letter { font-size: var(--step-2); line-height: 1.1; }
  .criterion__letter--long { font-size: var(--step-1); }
  .criterion__letter + .cite { margin-block-start: 0; }
}

@media (max-width: 30em) {
  .site-header__inner { gap: var(--space-075); }
  .site-name { margin-inline-end: 0; }
  .sheet { padding-inline: var(--space-1); }
  .btn { inline-size: 100%; }
}


/* -------------------------------------------------------------------------
   17. Motion (DESIGN.md §5)
   Effectively none. Nothing moves on load, nothing reveals on scroll.
   ------------------------------------------------------------------------- */

@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;
  }
}


/* -------------------------------------------------------------------------
   18. Print — the sheet is the deliverable and most people hand over paper.

   The palette is redefined at :root rather than patched per-component, so
   every rule in this file turns black-on-white in one place and no component
   can be forgotten. `black` and `white` are keywords, not hex — the token
   discipline holds.
   ------------------------------------------------------------------------- */

@media print {

  :root {
    --paper:     white;
    --desk:      white;
    --seal-tint: white;
    --ink:       black;
    --ink-2:     black;
    --seal:      black;
    --oxblood:   black;
    --edge:      black;
    --rule:      black;
    --lift:      none;
    /* Keep a real gutter: it is the column-gap between the rail and the
       reading column, not just page padding. .wrap zeroes its own padding. */
    --gutter:    1rem;
  }

  @page { margin: 1.5cm; }

  html, body { background: white; color: black; }

  body { font-size: 11pt; line-height: 1.45; }

  /* Chrome/Safari drop backgrounds and borders by default. */
  .disclaimer, .risk, .sheet, .site-header, .site-footer {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Screen chrome and controls carry nothing to paper. */
  .skip-link,
  .site-header,
  .site-nav,
  .site-footer,
  .lang-toggle,
  .btn,
  .btn-row,
  /* The nav container has its own rule line, so hiding only its buttons would
     print an empty bordered strip. Progress ("Question 4 of 11") is meaningless
     on paper. */
  .wizard__nav,
  .wizard__progress,
  button,
  [data-print="hide"] { display: none !important; }

  .site-main { padding-block: 0; }

  .wrap { max-inline-size: none; padding-inline: 0; }

  .sheet {
    box-shadow: none;
    border: 1px solid black;
    padding-block: var(--space-1);
    padding-inline: var(--space-1);
  }

  /* Both parts of the appointment sheet start on a fresh page. */
  .sheet--part { break-before: page; page-break-before: always; }

  /* A criterion or a denial-risk callout must never straddle a page fold. */
  .criterion,
  .risk,
  .disclaimer { break-inside: avoid; page-break-inside: avoid; }

  :is(h1, h2, h3, h4) { break-after: avoid; page-break-after: avoid; }

  /* Keep the rail on paper — it is the vocabulary the office uses. */
  .criterion { grid-template-columns: var(--rail) minmax(0, 1fr); }

  /* The 44px tap target is a touch affordance; on paper it is just wasted
     space between every citation and the text under it. */
  .cite a { display: inline; min-block-size: 0; }

  /* Ruled lines are the point of Part 1 -- they must survive the ink drop. */
  .write-lines hr {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    border-block-start: 1px solid black;
  }

  /* A ruled block must not be split across a page break mid-answer. */
  .write-lines { break-inside: avoid; }

  /* A printed link is dead unless the URL is on the page. */
  a[href]:not([href^="#"])::after {
    content: " <" attr(href) ">";
    font-family: var(--font-mono);
    font-size: 0.85em;
    font-weight: 400;
    overflow-wrap: anywhere;
  }

  a { color: black; text-decoration: underline; }

  img, svg { max-inline-size: 100%; }
}


/* ── Quoted policy ─────────────────────────────────────────────────────────
   A blockquote quoting policy text had no treatment at all: it rendered
   identically to the surrounding explanation. On a site whose entire purpose
   is separating what the determination SAYS from what we think it means, that
   is the one distinction that has to survive.

   Border only, in --rule, which §2 reserves for decorative hairlines — it
   carries no meaning on its own, so nothing here depends on seeing it. The
   quotation is still a <blockquote> with a cite attribute, which is what a
   screen reader and a parser actually read. Contrast is untouched: no text or
   background colour changes.
   ────────────────────────────────────────────────────────────────────────── */
blockquote {
  border-inline-start: 2px solid var(--rule);
  padding-inline-start: var(--space-1);
  margin-block: var(--space-1);
}

blockquote ol,
blockquote ul {
  padding-inline-start: var(--space-2);
  margin-block-start: var(--space-05);
}

blockquote li + li {
  margin-block-start: var(--space-05);
}


/* ── Inline-flex links must be allowed to wrap ──────────────────────────────
   Several components use display:inline-flex purely to make min-block-size:44px
   apply, since block-size does nothing on an inline element. That is a sound
   trick, but it has a side effect: the anchor becomes a flex CONTAINER, so an
   inline <span> and the words around it are split into separate flex items.
   Flex items do not reflow around one another, and without flex-wrap the row
   cannot break at all — the anchor simply grows past the viewport.

   It surfaced on the Spanish home page only, at 200% text zoom: "Lea la L33789
   en la <span lang=en>CMS Medicare Coverage Database</span>" measured 26px past
   a 320px viewport. The English string fits on one line, so the English page
   was clean and the bug looked like it did not exist.

   That is the trap worth remembering on a bilingual site: Spanish runs roughly
   20% longer, so any fixed-width assumption that holds in English gets tested
   here first. A scan of every page found 14 containers with this shape, one
   overflowing and the rest close — .site-nav__link is at 264px of 320 in
   Spanish already.

   Wrapping only engages when the content would not otherwise fit, so nothing
   moves at normal sizes. Do not "tidy" this away.
   ────────────────────────────────────────────────────────────────────────── */
.link-block a,
.cite a,
.btn,
.site-nav__link,
.site-footer__link,
.lang-toggle,
.site-name,
.skip-link,
.option {
  flex-wrap: wrap;
}
