/* =========================================================================
   VitalRecord -- design system: "Clinical Signal"
   White paper, near-black ink, one alarm-red accent reserved for the thing
   that needs attention (CTAs, live states, citations), amber held back for
   the safety-note block alone. Sans (Inter) carries the whole hierarchy;
   mono (JetBrains Mono) marks anything measured -- stat tiles, provenance
   lines, appendix citations. Flat by design: hairline borders instead of
   shadows, square corners on every CTA -- the same "a rule marks the line
   worth noticing" device the old system used, at a colder, more clinical
   register.

   Visual source of truth: docs/superpowers/design/2026-08-25-clinical-
   signal-mockup.html (owner-approved). This file is the shared stylesheet
   every template links (`<link rel="stylesheet" href="/ui/static/app.css">`)
   instead of base.html's old inline <style> block.

   Supersedes: the "warm green" system (cream shell, pine/brass accent).
   Task 3 (2026-08-25) is the foundation only -- it ports the old system's
   full component set forward under the new token names so every template
   Tasks 4-7 haven't reached yet keeps rendering, and lays down the new
   Clinical Signal component grammar (`.microlabel`, `.btn`, `.btn-ghost`,
   `.tile`, `.hairline-grid`, `.prov`, `.safety-note`, `.cite`, `.evidence`,
   `.evidence-neg`, `.appendix`) that those tasks build the rest of the
   site out of.
   ========================================================================= */

/* ---- fonts -------------------------------------------------------------
   Vendored, not CDN-loaded: five static woff2 instances (three Inter
   weights, two JetBrains Mono weights) under this same static route, so
   the page never blocks on a third-party font host. No italic face is
   vendored -- `.source-span`'s `font-style: italic` renders as a browser-
   synthesized oblique, which is an acceptable degradation for a single
   quoted-citation style, not a missing weight anything else depends on. */
@font-face {
  font-family: "Inter";
  src: url("/ui/static/fonts/Inter-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/ui/static/fonts/Inter-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/ui/static/fonts/Inter-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/ui/static/fonts/JetBrainsMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/ui/static/fonts/JetBrainsMono-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;

  /* ---- VitalRecord institutional palette (2026-10-04, Bluebird government register) ---------------------------------------
     Two reds, deliberately not one, after a review finding: 15px/700
     button/link text is WCAG *normal* text (bold only counts as "large"
     from 18.66px), so it needs the 4.5:1 AA-body floor -- and #0787D9 on
     paper is 4.17:1, an AA-large pass but an honest AA-body fail.
     `--color-signal` (#0787D9) is reserved for large-display accents only
     -- >=24px, or >=18.66px bold: the live tile number (`.tile.live .n`,
     30px), and the h1 em / wordmark b treatments when they land in later
     tasks. Every smaller/normal-weight text use (`.btn` fill, `.cite`
     citation markers, `.appendix a`, and everything reached through the
     legacy `--color-accent` alias below: link hover, `.eyebrow`,
     `.intake-reset:hover`, `.btn-primary`) uses `--color-signal-dark`
     (5.53:1, clears AA-body) instead. `--color-signal-darker` is one step
     further for hover/active states built on top of the dark variant. */
  --color-paper: #FFFFFF;
  --color-ink: #0B0F14;
  --color-muted: #5B6572;
  --color-hairline: #E8EAED;
  --color-signal: #0787D9;
  --color-signal-dark: #0468AC;
  --color-signal-darker: #045289;
  --color-safety: #B45309;
  --color-safety-wash: #FBEEDD;

  /* ---- legacy token names ---------------------------------------------
     Every template built against the old "warm green" system -- and every
     template Tasks 4-7 haven't reached yet -- reads these names directly,
     often from its own `extra_style` block. Remapped to the values above
     rather than renamed, so an untouched page inherits the new palette
     instead of breaking outright. Deliberate consequence: the cream
     `--color-shell` is gone -- the shell is white paper now, same as
     every card sitting on it. */
  --color-shell: #FFFFFF;
  --color-surface: #FFFFFF;
  --color-surface-tint: #F3F5F7;
  --color-ink-muted: var(--color-muted);
  --color-border: #8A93A1;
  /* `--color-accent` is every legacy selector's normal/small-text-or-
     border color (links, .eyebrow, .btn-primary, focus/hover borders) --
     none of it is large-display text, so it points at the AA-body-safe
     dark variant, not the lighter `--color-signal` display accent. */
  --color-accent: var(--color-signal-dark);
  --color-accent-dark: var(--color-signal-darker);
  --color-accent-wash: #E3F0FB;
  --color-on-accent: #FFFFFF;
  --color-pending: var(--color-safety);
  --color-pending-wash: var(--color-safety-wash);
  --color-danger: #A02318;
  --color-danger-wash: #FBE9E7;

  /* ---- type -------------------------------------------------------------
     Sans carries the whole hierarchy, including the wordmark and the
     quoted source-citation span the old system rationed to a serif -- the
     approved mockup has no serif anywhere. `--font-display` stays defined
     (aliased to sans) so a page this task doesn't touch keeps resolving it
     to something real instead of the browser's default serif. */
  --font-sans: Inter, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Consolas, monospace;
  --font-body: var(--font-sans);
  --font-display: var(--font-sans);

  --text-xs: 0.8125rem;
  --text-sm: 0.9375rem;
  --text-base: 1.0625rem;
  --text-md: 1.1875rem;
  --text-lg: 1.375rem;
  --text-xl: 1.75rem;
  --text-display: clamp(2rem, 1.5rem + 2.2vw, 2.75rem);
  /* Hero scale, tuned to the mockup's literal endpoints: 38px at the
     640px mobile breakpoint, 56px at the 1020px content width. */
  --text-hero: clamp(2.375rem, 0.5rem + 4.75vw, 3.5rem);

  /* ---- spacing ----------------------------------------------------------
     Unchanged names and values -- every per-template `extra_style` block
     in the repo references these directly. */
  --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;

  --radius-sm: 5px;
  --radius-md: 9px;
  --radius-pill: 999px;

  --shadow-card: 0 1px 3px rgba(11, 15, 20, 0.08), 0 2px 6px rgba(11, 15, 20, 0.05);

  --content-width: 42rem;
  --content-width-wide: 60rem;
}

/* ---- reset ----------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.55;
}
img, svg { max-width: 100%; display: block; }

h1, h2, h3 {
  font-family: var(--font-sans);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--color-ink);
  margin: 0 0 var(--space-4);
}
h1 { font-size: var(--text-display); letter-spacing: -0.02em; overflow-wrap: anywhere; }
h2 { font-size: var(--text-xl); margin-top: 0; }
h3 { font-size: var(--text-lg); margin-top: var(--space-5); font-weight: 700; }

p { margin: 0 0 var(--space-4); }
ol, ul { padding-left: 1.3em; margin: 0 0 var(--space-4); }
li { margin-bottom: var(--space-3); }
li:last-child { margin-bottom: 0; }

a { color: var(--color-accent-dark); text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
a:hover { color: var(--color-accent); }

strong { font-weight: 700; }

:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* visually hidden but screen-reader-readable -- used for the facts
   table's per-cell labels (kept alongside the data-label/::before
   mechanism per the accessibility review: generated content isn't
   guaranteed to be exposed by every screen-reader/browser pairing). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- layout ------------------------------------------------------- */
header.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-4);
  border-bottom: 2px solid var(--color-ink);
  max-width: var(--content-width-wide);
  margin: 0 auto;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-ink);
  text-decoration: none;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.01em;
}
.wordmark:hover { color: var(--color-ink); }
.wordmark svg { flex: none; }
/* Brand-name text is exempt from WCAG's text-contrast requirement (a
   logotype, not running copy), so the ".ai" suffix carries the bright
   large-display accent rather than the AA-body-safe dark variant every
   other small/normal-weight use of the signal red reads instead. */
.wordmark b { color: var(--color-signal); }

/* Signed-in nav. No new tokens: muted ink at rest, and the accent marks
   the current page as a thick underline rather than a filled pill --
   the same "a rule marks the line worth noticing" device the rest of
   the system uses, at its smallest scale. Each link is a 44px target
   even though its text is --text-sm, matching the floor .btn already
   sets. */
.site-nav {
  display: flex;
  /* Centre, not the flex default of stretch: the sign-out control is a
     <form> wrapping a <button> and so has one more box than the plain
     anchors beside it, which left its label sitting a few pixels below
     their baseline. */
  align-items: center;
  gap: var(--space-5);
  font-size: var(--text-sm);
  font-weight: 600;
}
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--color-ink-muted);
  text-decoration: none;
}
.site-nav a:hover { color: var(--color-accent-dark); }

/* Sign out is a <form>, because it changes state and must survive with
   JavaScript off -- but it sits in a row of links, so the button is
   reset to read as one. Two global rules have to be undone for that:
   `form` carries a bottom margin, and `form > button` a top margin.
   No new token: same muted ink, same hover, same 44px target as the
   links beside it. */
.site-nav-signout { margin: 0; display: flex; align-items: center; }
/* `.site-nav` is repeated to raise specificity to (0,2,1). The forms
   section below carries `button[type="submit"], form > button {
   margin-top: var(--space-5) }`, which is (0,1,1) -- an exact tie with
   the plain `.site-nav-signout button`, and it comes later in the file,
   so it won on source order and pushed the label 24px below the links
   beside it. Specificity rather than reordering, so this stays correct
   if either block moves. */
.site-nav .site-nav-signout button {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: inherit;
  color: var(--color-ink-muted);
  cursor: pointer;
}
.site-nav .site-nav-signout button:hover { color: var(--color-accent-dark); }

.site-nav a[aria-current="page"] {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.35em;
}

/* Groups the site-nav and the persistent account indicator on the right of
   the header, so the account glyph stays the top-right element on both
   signed-in (nav + account) and signed-out (account only) pages. */
.site-header-end {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

/* The persistent account indicator. Signed out it is a Sign-in link; signed
   in it is a filled signal-coloured glyph plus the account email (truncated,
   never wrapping the header). No new tokens. */
.account {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
}
.account-icon { width: 20px; height: 20px; flex: none; }
.account-icon--on { color: var(--color-signal); }
.account-email {
  color: var(--color-ink-muted);
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.account-signin {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  color: var(--color-ink-muted);
  text-decoration: none;
}
.account-signin:hover { color: var(--color-accent-dark); }

/* Billing-period toggle on /ui/pricing: two links (Monthly / Yearly). The
   active period is filled ink on the surface; the inactive is a plain link.
   No new tokens. */
.billing-toggle {
  display: inline-flex;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin: var(--space-4) 0;
}
.billing-toggle-option {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink-muted);
  text-decoration: none;
}
.billing-toggle-option.is-active {
  background: var(--color-ink);
  color: var(--color-surface);
}

/* Segmented tab control on the sign-in page: one box, two tabs. Same visual
   grammar as .billing-toggle, but for <button> elements (button reset). */
.auth-toggle {
  display: flex;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin: 0 0 var(--space-4);
}
.auth-toggle-option {
  flex: 1 1 0;
  padding: var(--space-2) var(--space-4);
  background: none;
  border: none;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink-muted);
  cursor: pointer;
}
.auth-toggle-option.is-active {
  background: var(--color-ink);
  color: var(--color-surface);
}
.plan-price-period {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink-muted);
}

/* ---- mobile bottom tab bar (signed-in only) ----------------------------
   A fixed bar at the bottom of the viewport, shown only under the 700px
   breakpoint (the media query below). Rendered only on signed-in pages
   (the template guards it on `nav_current`, like the site-nav). At
   700-480px it coexists with the site-nav row above; under 480px the
   header collapses to the wordmark and the bar is the primary nav -- it
   carries Home for that, so the overview stays reachable. Same no-JS rule
   as the site-nav: the sign-out slot is a POST form, never a GET link. No
   new tokens -- surface, hairline and accent tokens only. */
.mobile-tabbar {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  align-items: stretch;
  background: var(--color-surface);
  border-top: 1px solid var(--color-hairline);
  box-shadow: 0 -1px 3px rgba(11, 15, 20, 0.08), 0 -2px 6px rgba(11, 15, 20, 0.05);
  /* notched phones: keep the row clear of the home indicator */
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-tabbar a,
.mobile-tabbar .mobile-tabbar-signout button {
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-ink-muted);
  text-decoration: none;
}
.mobile-tabbar a:hover,
.mobile-tabbar a[aria-current="page"] {
  color: var(--color-accent-dark);
}
.mobile-tabbar a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3em;
}
/* The sign-out slot is a <form> sitting in a row of links; undo the
   global form/button margins and reset the button to read as a link,
   the same reset the site-nav's sign-out form carries. */
.mobile-tabbar-signout { margin: 0; display: flex; }
.mobile-tabbar .mobile-tabbar-signout button {
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  line-height: inherit;
  cursor: pointer;
}
.mobile-tabbar .mobile-tabbar-signout button:hover { color: var(--color-accent-dark); }

/* Plan state on the tab bar (UI/UX review follow-up, 2026-08-27): a
   quiet dot-plus-name slot for an active plan, and the Upgrade link read
   as a CTA. Both render only where a route threads `plan`, mirroring the
   site-nav's own guard. */
.mobile-tabbar-plan {
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-accent-dark);
}
.mobile-tabbar-plan::before {
  content: "";
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  margin-right: 0.35rem;
  border-radius: 50%;
  background: var(--color-accent);
}
.mobile-tabbar a.mobile-tabbar-upgrade { color: var(--color-accent-dark); }

main.page {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-8);
}
main.page-wide { max-width: var(--content-width-wide); }

/* Every section reads as a new entry in the briefing: a hairline rule,
   then the flagged heading. First section skips the rule (it follows
   the hero, not another section). */
section { margin-top: var(--space-7); padding-top: var(--space-7); border-top: 1px solid var(--color-hairline); }
section:first-child { margin-top: 0; padding-top: 0; border-top: none; }

.lead {
  font-size: var(--text-md);
  color: var(--color-ink-muted);
}

.eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 var(--space-2);
}

footer.site-footer {
  max-width: var(--content-width-wide);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) var(--space-7);
  border-top: 1px solid var(--color-hairline);
  color: var(--color-ink-muted);
  font-size: var(--text-sm);
}
footer.site-footer a { color: var(--color-ink-muted); }
footer.site-footer a:hover { color: var(--color-accent-dark); }
footer.site-footer .footer-wordmark { color: var(--color-ink); }

/* ---- buttons --------------------------------------------------------
   `.btn` itself carries the signal-dark fill now (mockup calls for
   signal bg, white text, no radius; a review finding moved the fill from
   the lighter `--color-signal` to `--color-signal-dark` -- 15px/700
   button text is WCAG *normal* text, since bold only counts as "large"
   from 18.66px, so it needs the 4.5:1 AA-body floor and only the dark
   variant clears it) rather than a neutral base needing a `-primary`
   modifier -- every current call site already pairs `.btn` with a
   modifier class, so this is additive, not a rename.

   Visual properties (background/border-color/text color, rest and hover)
   are driven entirely through `--btn-*` custom properties rather than set
   directly on `.btn`/`.btn:hover`, after a second review finding:
   `.btn:hover` used to set `border-color` directly at (0,2,0)
   specificity, which beat every modifier's own (0,1,0) border-color and
   nothing in `.btn-secondary:hover`/`.btn-danger:hover`/`.btn-ghost:hover`
   reset it -- so hovering any of them flipped their border signal-red
   regardless of the modifier's own color (`.btn-ghost` ended up
   ink-filled, white-text, red-bordered, never an intended combination).
   Each modifier now sets its own `--btn-border`[`-hover`]; the fallback
   chain `var(--btn-border-hover, var(--btn-border, ...))` means a
   modifier that sets a rest-state border but no hover-specific one simply
   keeps that same border on hover (the correct default for everything
   except the base variant), and the true base `.btn` (no modifier, both
   unset) is the only thing that still falls through to the
   signal-dark/signal-darker hover treatment. `.btn-primary` stays defined
   (now redundant with the base look, harmless) and
   `.btn-secondary`/`.btn-danger` keep overriding as before. `.btn-ghost`
   is new: the mockup's outlined second action. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 13px 26px;
  border-radius: 0;
  border-width: 1px;
  border-style: solid;
  border-color: var(--btn-border, transparent);
  background: var(--btn-bg, var(--color-signal-dark));
  color: var(--btn-fg, #fff);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn:hover {
  background: var(--btn-bg-hover, var(--color-signal-darker));
  border-color: var(--btn-border-hover, var(--btn-border, var(--color-signal-darker)));
  color: var(--btn-fg-hover, var(--btn-fg, #fff));
}
.btn-primary {
  --btn-bg: var(--color-accent);
  --btn-border: var(--color-accent);
  --btn-fg: var(--color-on-accent);
}
.btn-primary:hover {
  --btn-bg-hover: var(--color-accent-dark);
  --btn-border-hover: var(--color-accent-dark);
}
.btn-secondary {
  --btn-bg: transparent;
  --btn-border: var(--color-border);
  --btn-fg: var(--color-ink);
}
.btn-secondary:hover { --btn-bg-hover: var(--color-surface-tint); }
.btn-danger {
  --btn-bg: transparent;
  --btn-border: var(--color-danger);
  --btn-fg: var(--color-danger);
}
.btn-danger:hover { --btn-bg-hover: var(--color-danger-wash); }
.btn-ghost {
  --btn-bg: transparent;
  --btn-border: var(--color-ink);
  --btn-fg: var(--color-ink);
  border-width: 1.5px;
}
.btn-ghost:hover {
  --btn-bg-hover: var(--color-ink);
  --btn-fg-hover: #fff;
}
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}
.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-5); }

/* ---- Clinical Signal component grammar ---------------------------------
   Ported from the approved mockup (docs/superpowers/design/2026-08-25-
   clinical-signal-mockup.html): a small microcopy label, the hairline-
   bordered stat-tile grid, a mono provenance line, an amber safety-note
   block, and the evidence/appendix pattern the report pages cite sources
   through. Every later task (4-7) builds its UI out of this vocabulary
   rather than inventing new classes. */
.microlabel {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.hairline-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-left: 1px solid var(--color-hairline);
}
@media (max-width: 40rem) {
  .hairline-grid { grid-template-columns: 1fr 1fr; }
}

.tile {
  border-right: 1px solid var(--color-hairline);
  border-bottom: 1px solid var(--color-hairline);
  padding: var(--space-5) var(--space-4);
}
.tile .n {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 30px;
  line-height: 1.1;
  margin-top: var(--space-2);
}
.tile .n small {
  font-size: 13px;
  color: var(--color-muted);
  font-family: var(--font-sans);
  font-weight: 600;
}
.tile.live .n { color: var(--color-signal); }

.prov {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--color-muted);
  margin-top: var(--space-2);
}

.safety-note {
  padding: var(--space-4) var(--space-5);
  margin-top: var(--space-4);
  border-left: 3px solid var(--color-safety);
  background: var(--color-safety-wash);
  color: var(--color-ink);
  font-size: var(--text-sm);
}
.safety-note p { margin: 0; }
.safety-note p + p { margin-top: var(--space-3); }

.cite {
  /* Inline citation marker link (`<sup><a class="cite" href="#src-n">
     [n]</a></sup>`, Task 17): 11px/700 -- normal text by the WCAG
     large-text threshold (18.66px bold), so this is the dark variant, not
     the large-display accent. Named `.cite` (not the mockup's bare
     `sup a`) so it targets the marker regardless of its ancestry. */
  color: var(--color-signal-dark);
  text-decoration: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 11px;
}

.evidence {
  border: 1px solid var(--color-hairline);
  border-left: 3px solid var(--color-ink);
  padding: var(--space-4) var(--space-4);
  margin: var(--space-5) 0;
  font-size: 14.5px;
}
.evidence .prov { margin-top: var(--space-2); }
/* Negative-finding variant -- combined with `.evidence` in markup
   (`class="evidence evidence-neg"`), never standalone. Named as its own
   class (not the mockup's compound `.evidence.neg`) so Task 17 can target
   it directly, consolidated rather than duplicated. */
.evidence-neg {
  border-left-color: var(--color-muted);
  color: var(--color-muted);
}

.appendix {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--color-muted);
  border-top: 2px solid var(--color-ink);
  padding-top: var(--space-3);
  margin-top: var(--space-6);
}
/* 13px mono -- same normal-text case as `.cite` above. */
.appendix a { color: var(--color-signal-dark); text-decoration: none; }
/* Review fix (round 1, Important 1b): the per-source PMID/identifier
   marker inside an appendix entry (report.html renders both
   `<a class="pmid">`, when a derived external link exists, and
   `<span class="pmid">` otherwise) -- deleted with no replacement when
   the page-scoped `.report-doc .appendix .pmid` override was consolidated
   away. Restored here as a named, shared rule: 11px mono, same
   `--color-signal-dark` the rest of the small/normal-weight signal uses
   read (`.cite`, `.appendix a`) -- applied to both the link AND the span
   variant, so an entry with no derivable link doesn't silently lose its
   marker color just because it isn't an `<a>`. */
.pmid {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-signal-dark);
}

/* ---- forms ------------------------------------------------------------ */
form { margin: 0 0 var(--space-5); }
label {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--color-ink);
  margin-top: var(--space-4);
}
label:first-child { margin-top: 0; }
input[type="email"], input[type="password"], input[type="text"], input[type="file"] {
  display: block;
  width: 100%;
  max-width: 24rem;
  margin-top: var(--space-2);
  padding: 0.65rem 0.75rem;
  min-height: 44px;
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
input:focus-visible { border-color: var(--color-accent); }
input:disabled { color: var(--color-ink-muted); background: var(--color-surface-tint); cursor: not-allowed; }
button { font-family: var(--font-body); }
button[type="submit"], form > button {
  margin-top: var(--space-5);
}

/* ---- cards / panels ----------------------------------------------- */
.panel {
  background: var(--color-surface);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: var(--space-5);
}

/* ---- notices, errors, coming-soon ---------------------------------- */
.notice, .error, .coming-soon {
  padding: var(--space-4) var(--space-5);
  margin-top: var(--space-4);
  border-radius: var(--radius-sm);
  border-left: 3px solid;
  font-size: var(--text-sm);
}
.notice p, .error p, .coming-soon p { margin: 0; }
.notice p + p, .coming-soon p + p { margin-top: var(--space-3); }
.notice {
  display: none;
  background: var(--color-accent-wash);
  border-left-color: var(--color-accent);
  color: var(--color-accent-dark);
}
.error {
  display: none;
  background: var(--color-danger-wash);
  border-left-color: var(--color-danger);
  color: var(--color-danger);
}
.coming-soon {
  background: var(--color-pending-wash);
  border-left-color: var(--color-pending);
  color: var(--color-ink);
}

/* ---- inline form status line (early-access waitlist) -----------------
   Unlike `.notice`/`.error` above, this isn't a boxed callout -- it's a
   compact live-region line beside a submit button (`role="status"
   aria-live="polite"`), so it carries no border/background/padding, only
   color. Moved out of landing.html's page-scoped `extra_style` (Task 4
   review): the color states weren't landing-specific, so they belong
   here with the rest of the shared palette decisions. */
.waitlist-status {
  margin: var(--space-4) 0 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--color-ink);
  min-height: 1.5rem;
}
.waitlist-status[data-state="error"] { color: var(--color-danger); }
.waitlist-status:empty { min-height: 0; }

/* ---- badges --------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.7rem;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: capitalize;
  white-space: nowrap;
}
.badge-extracted, .badge-accepted {
  background: var(--color-accent-wash);
  color: var(--color-accent-dark);
}
.badge-rejected, .badge-failed {
  background: var(--color-danger-wash);
  color: var(--color-danger);
}
.badge-queued, .badge-extracting {
  background: var(--color-pending-wash);
  color: var(--color-pending);
}

/* ---- source citations (facts table + the landing sample) -------------
   A quoted, verbatim source line gets the same accent rule as every
   section flag -- the citation *is* the evidence, so it gets the brand's
   one strong color, with conviction, same as a CTA. */
.source-span {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-md);
  color: var(--color-ink);
  line-height: 1.5;
  border-left: 3px solid var(--color-accent);
  padding: var(--space-1) 0 var(--space-1) var(--space-4);
}
.fact-row td {
  border-bottom: none;
  padding-bottom: var(--space-1);
}
.fact-row:not(:first-child) td { padding-top: var(--space-5); }
.fact-span-row td {
  padding-top: 0;
  padding-bottom: var(--space-4);
}

/* ---- tables ----------------------------------------------------------- */
table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--text-sm);
}
th, td {
  text-align: left;
  padding: var(--space-3) var(--space-3);
  border-bottom: 1px solid var(--color-hairline);
  vertical-align: top;
  font-variant-numeric: tabular-nums;
}
th {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-ink-muted);
  font-weight: 700;
}
.table-scroll { overflow-x: auto; margin-top: var(--space-4); }

/* ---- meta / small text ------------------------------------------------ */
.meta { color: var(--color-ink-muted); font-size: var(--text-sm); }

/* ---- hero (landing + login) -------------------------------------------
   One layout, two scales: landing's h1 carries `.hero-heading` (the
   larger --text-hero size); login's h1 stays at the ordinary h1 size
   but reuses the same `.hero` composition (heading beside the mark)
   with `.hero-mark--compact` for a smaller vignette. */
.hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-top: var(--space-2);
}
.hero-body { min-width: 0; }
.hero-heading {
  font-size: var(--text-hero);
  line-height: 1.05;
  letter-spacing: -0.03em;
  max-width: 16ch;
}
/* The mockup's identity-defining moment: "Say it all." in signal red.
   Display-size text (--text-hero, >=38px) clears the AA-large / large-
   display threshold outright, so the bright --color-signal is correct
   here -- unlike every small/normal-weight signal use elsewhere in the
   system, which reads the AA-body-safe --color-signal-dark instead.
   Scoped to the landing hero's own h1, not every <em> on the site. */
.hero-heading em {
  font-style: normal;
  color: var(--color-signal);
}
.hero-lead { max-width: 40ch; }
.hero-mark {
  flex: none;
  width: min(12rem, 40vw);
  margin: 0 auto;
}
.hero-mark--compact { width: min(8rem, 36vw); }
.hero-mark-svg { width: 100%; height: auto; display: block; }
.hero-mark-page-back { fill: var(--color-surface-tint); stroke: var(--color-hairline); stroke-width: 1.25; }
.hero-mark-page-front { fill: var(--color-surface); stroke: var(--color-border); stroke-width: 1.25; }
.hero-mark-title { fill: var(--color-hairline); }
.hero-mark-line { stroke: var(--color-hairline); stroke-width: 2.5; stroke-linecap: round; }
.hero-mark-quote-bar { fill: var(--color-accent); }
.hero-mark-quote-line { stroke: var(--color-ink-muted); stroke-width: 2.5; stroke-linecap: round; opacity: 0.8; }
.hero-mark-quote-line--1 { opacity: 1; stroke: var(--color-ink); }
.hero-mark-dot { fill: var(--color-accent); }
.hero-mark-rule { stroke: var(--color-accent); stroke-width: 1.5; }

@media (min-width: 40rem) {
  .hero {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-6);
  }
  .hero-mark { margin: 0; }
}

/* ---- trust row (landing) ----------------------------------------------
   Three principles-page commitments, restated short and linked back to
   the full statement -- a scan-able trust signal, not a duplicate of
   the "Where we stand" panel's prose. */
.trust-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-5);
}
.trust-item {
  display: block;
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-md);
  line-height: 1.35;
  text-decoration: none;
}
.trust-item:hover, .trust-item:focus-visible {
  border-color: var(--color-accent);
  background: var(--color-accent-wash);
  color: var(--color-ink);
}

/* ---- "what's in a report" list (landing) -------------------------------
   Same visual language as principles.html's commitments list (accent
   left-rule, bold lead-in) -- one shared list pattern reused for two
   different lists of short, flat, unordered statements, rather than a
   new component invented for each. */
.info-list { list-style: none; padding-left: 0; margin-top: var(--space-5); }
.info-list li {
  padding: var(--space-4) 0 var(--space-4) var(--space-5);
  border-left: 3px solid var(--color-accent);
  border-bottom: 1px solid var(--color-hairline);
  margin-bottom: 0;
  font-size: var(--text-md);
}
.info-list li:last-child { border-bottom: none; }

/* ---- plans (landing teaser + pricing.html) ------------------------------
   Flat hairline-bordered tiles, not the shadowed/rounded `.panel` card --
   Clinical Signal's own rule ("hairline borders instead of shadows, square
   corners on every CTA") applied to the one card shape both pages share.
   `.plan-card` used to ride on a `.panel` class alongside it for its
   border/shadow/radius; that pairing is gone from both templates now that
   this rule is everything a plan card needs. */
.plans-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-5);
  align-items: stretch;
}
.plan-card {
  display: flex;
  flex-direction: column;
  padding: var(--space-5);
  border: 1px solid var(--color-hairline);
  background: var(--color-surface);
}
.plan-card--featured {
  border-color: var(--color-accent);
  border-width: 2px;
  background: var(--color-accent-wash);
}
.plan-title { color: var(--color-ink); }
/* pricing.html only: the plan's price on its own line, in the mono face
   every other measured/priced number on the site uses (`.tile .n`). */
.plan-price {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-lg);
  color: var(--color-ink);
  margin: 0 0 var(--space-3);
}
.plans-note { margin-top: var(--space-4); }

/* ---- numbered steps list ("How it works", landing) ---------------------
   A generic ordered-explanation pattern (accent-filled numeral circle +
   text), not landing-specific in principle. Moved out of landing.html's
   page-scoped `extra_style` (Task 4 review): the badge's fill/text color
   is exactly the kind of per-page color override the shared stylesheet
   exists to prevent. */
.steps {
  list-style: none;
  padding-left: 0;
  counter-reset: step;
  margin-top: var(--space-5);
}
.steps li {
  counter-increment: step;
  display: flex;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.steps li::before {
  content: counter(step);
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--color-on-accent);
  background: var(--color-accent);
  border-radius: 50%;
}
.steps li > span { padding-top: 0.3rem; }
.steps-note { margin-top: var(--space-5); }

/* ---- intake conversation stub (landing) ---------------------------------
   Native fieldset/legend/radio semantics throughout -- arrow keys move
   within a step, Tab moves between controls, nothing here needs custom
   ARIA widget roles. Progressive: with JS disabled only step 1 renders
   (inert, not broken -- see the noscript notice). */
.intake-panel { padding: var(--space-6) var(--space-5); }
.intake-progress {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-5);
}
.intake-step { border: none; padding: 0; margin: 0 0 var(--space-6); }
.intake-step:last-of-type { margin-bottom: 0; }
.intake-step legend {
  padding: 0;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--text-md);
  color: var(--color-ink);
  margin-bottom: var(--space-4);
  width: 100%;
}
.intake-step legend:focus {
  outline: 3px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}
.intake-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--space-3);
}
.intake-option {
  position: relative;
  display: block;
  cursor: pointer;
}
.intake-option-input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.intake-option-card {
  display: block;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink);
}
/* Sibling combinator, not :has() -- works on every browser this product
   supports, not only the ones current when this was written. */
.intake-option-input:checked ~ .intake-option-card {
  border-color: var(--color-accent);
  border-width: 2px;
  background: var(--color-accent-wash);
  color: var(--color-accent-dark);
  padding: calc(var(--space-3) - 1px) calc(var(--space-4) - 1px);
}
.intake-option-input:focus-visible ~ .intake-option-card {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}
.intake-result { padding: var(--space-6) var(--space-5); }
.intake-result:focus { outline: none; }
.intake-result-text {
  font-size: var(--text-md);
  color: var(--color-ink);
}
.intake-reset {
  display: inline-block;
  margin-top: var(--space-4);
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--color-accent-dark);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  cursor: pointer;
}
.intake-reset:hover { color: var(--color-accent); }

/* ---- invite / coming-soon as first-class moments (login) --------------- */
.invite-reveal {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  margin-top: var(--space-3);
  padding: 0.55rem 1rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}
.invite-reveal:hover, .invite-reveal:focus-visible {
  background: var(--color-accent-wash);
  color: var(--color-ink);
}
.coming-soon-icon {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--color-pending);
}
.coming-soon-heading {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: var(--text-md);
  color: var(--color-ink);
  margin: 0 0 var(--space-2);
}
.coming-soon-heading::before { content: none; }

/* ---- details / disclosure (extracted pages) --------------------------- */
details {
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-sm);
  margin-top: var(--space-3);
  background: var(--color-surface);
}
details + details { margin-top: var(--space-3); }
summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
summary::-webkit-details-marker { display: none; }
summary .chevron {
  flex: none;
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
details[open] summary .chevron { transform: rotate(45deg); }
details pre {
  margin: 0;
  padding: var(--space-4);
  border-top: 1px solid var(--color-hairline);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--color-surface-tint);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

@media (max-width: 30rem) {
  /* Wordmark plus two nav links overflows a 320px viewport, so the nav
     wraps onto its own line rather than the brand shrinking. */
  header.site-header { padding: var(--space-4) var(--space-4); flex-wrap: wrap; row-gap: var(--space-3); }
  .site-nav { gap: var(--space-4); }
  main.page { padding: var(--space-5) var(--space-4) var(--space-7); }

  /* Facts table -> stacked cards. The real per-fact provenance table
     (document.html) and the landing sample reuse this identical rule:
     one CSS pattern for "a fact + its quoted source", table on wide
     screens, card on narrow ones. thead is visually hidden and each
     cell grows a visible label from data-label via ::before; an
     .sr-only label is also present in the markup itself (see
     document.html / landing.html) so the label survives even where
     generated content isn't exposed to a screen reader. */
  .facts-table thead { display: none; }
  .facts-table, .facts-table tbody, .facts-table tr, .facts-table td { display: block; width: 100%; }
  .facts-table tr.fact-row td { padding-top: 0; padding-bottom: var(--space-1); border-bottom: none; }
  .facts-table tr.fact-row {
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-hairline);
  }
  .facts-table tr.fact-row:first-child { margin-top: 0; padding-top: 0; border-top: none; }
  .facts-table tr.fact-span-row td { padding: var(--space-2) 0 var(--space-4); }
  .facts-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-ink-muted);
    font-weight: 700;
    margin-bottom: 2px;
  }

  .hero-mark { width: min(11rem, 48vw); }
  .trust-item { font-size: var(--text-base); }
}

/* ---- mobile tab bar breakpoint (700px) -----------------------------------
   The base file's own narrow-screen handling lives at 30rem; the bottom
   tab bar's breakpoint is 700px (43.75rem) per the reports-dashboard
   design -- wide phones and small tablets get the tab bar, desktops get
   the site-nav. main.page's bottom padding is bumped here so the fixed
   bar never covers the last card; this block sits after the 30rem block,
   so at <=30rem this bottom padding wins over that block's --space-7. */
@media (max-width: 43.75rem) {
  .mobile-tabbar { display: flex; }
  main.page { padding-bottom: var(--space-8); }
  /* The fixed tab bar also covers the footer's lower edge on phones --
     main's padding only clears content, so the footer gets its own
     clearance plus the device safe area (UI/UX review, 2026-08-27). */
  footer.site-footer {
    padding-bottom: calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
  }
}

/* ---- print ------------------------------------------------------------ */
@media print {
  body { background: #fff; color: #000; font-size: 12pt; }
  header.site-header, footer.site-footer, .no-print, form, button,
  #upload-form, #delete-btn, .hero-mark, .mobile-tabbar { display: none !important; }
  main.page, main.page-wide { max-width: 100%; padding: 0; margin: 0; }
  a { color: #000; text-decoration: underline; }
  section { border-top-color: #999; }
  .panel { box-shadow: none; }
  .badge { border: 1px solid #000; background: none !important; color: #000 !important; }
  .fact-row, .fact-span-row { break-inside: avoid; }
  details { border: none; }
  details pre { background: none; border-top: 1px solid #999; }
}
