/* ==========================================================================
   USTR design tokens — the one source of colour, type, spacing, radii, shadow
   and focus for the client portal and the staff console.

   Type: Figtree, one family for everything a person reads (2026-09-18).
   Chosen over Atkinson Hyperlegible Next, Public Sans and Source Sans 3 by
   rendering the same question screen and status screen in each: Atkinson's
   slashed zeros made every dollar figure look like code, Public Sans read as
   a government form, Source Sans ran small and plain. Figtree stays friendly
   at 30px and legible at 14px, and it has true tabular figures for money.
   Anton was the poster face on every heading; all-caps condensed headlines
   were the loudest thing making these screens read as a template, so it is
   gone from the interface (the logo keeps its own lettering).

   Self-hosted, because the CSP is style-src 'self' and font-src 'self'. One
   variable file per subset covers every weight used (400-800); latin-ext
   carries French-Canadian names and addresses ("Québec", "Trois-Rivières").

   The client pages pin data-theme="light", so they are always light — the
   same rule every USTR email follows. The dark tokens below exist for the
   staff console, which people stare at all day.
   ========================================================================== */

/* --- Fonts --------------------------------------------------------------- */

@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/public/fonts/figtree-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/public/fonts/figtree-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Archivo, for headlines on the client pages only (2026-09-19). Ethan chose
   brand direction A, "Winner's Red", after seeing four directions applied to
   the homepage and this portal: the logo's red as the ground, glossy puffed
   objects, and big condensed headlines. The condensed width is what makes it
   read as the brand rather than as the template the 2026-09-18 note above
   warns about — so it is set in sentence case, never shouted in capitals, and
   Figtree still carries every sentence a client actually reads. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 500 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/public/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 500 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/public/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Light tokens (default) ----------------------------------------------- */

:root {
  color-scheme: light;

  /* Type */
  --font-body: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: var(--font-body);
  /* The client pages' headline face (direction A). Always used with
     font-stretch: var(--brand-stretch); without it Archivo is a normal-width
     grotesk and the headlines lose the one thing that makes them the brand. */
  --font-brand: "Archivo", "Arial Narrow", var(--font-body);
  --brand-stretch: 64%;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Ink, from black through the neutral ramp to the page background. One
     ramp, one hue (a warm, near-neutral grey — not blue-grey), so the whole
     app reads as one material rather than components in different greys. */
  --ink: #161314;
  --body: #2e2a2b;
  --muted: #5f5a5b;
  --faint: #8e8889;
  --line: #e6e2e2;
  --line-strong: #cbc5c5;
  --surface: #ffffff;
  --surface-sunken: #f6f4f4;
  /* Nudged from a warm beige (#f2ede4) toward a grayish-beige (2026-08-31 —
     Ethan pointed at this exact territory during the walkthrough). Still the
     same warm-neutral ramp, just less yellow: R-B spread drops from 14 to 4.
     One token, both surfaces read from it (the console via public/staff.css,
     the client portal via app/globals.css), so this is the one place to
     change it. Contrast against every ink/body/muted/brand text colour that
     was already ≥4.5:1 on the old value stays ≥4.5:1 (in fact marginally
     higher, since the new value is fractionally lighter) — checked by hand,
     not by a test, because this token has no automated contrast check yet. */
  --bg: #f3f1f1;

  /* Brand — the approved USTaxRecovery values, and nowhere else in the file.
     #A70102 on white is 8.2:1, comfortably AA/AAA for text and for the
     white-on-red button label. */
  --brand: #a70102;
  --brand-dark: #7d0102;
  --brand-tint: #fbeeee;
  --brand-ink: #ffffff;
  /* Direction A's two supporting colours: the warm cream of the puffed
     cheque, used for type on the red panel, and the chip gold, used for a
     thin rule and nothing larger. */
  --cream: #f4ede2;
  --gold: #c9a24b;
  --panel-red-glow: #b20a09;
  --panel-red: #9a0303;
  --panel-red-deep: #6f0101;
  /* Some components carry a permanently dark surface regardless of the page's
     own theme — the assistant panel's header is the one in this codebase.
     --brand text there needs the same ~6.1:1 dark-surface value dark mode
     gets, even while the rest of a light page is using --brand-dark for that
     same role. Defined here too (identical value) so a component author can
     reach for --brand-on-dark unconditionally instead of writing its own
     light/dark branch. (A component whose own surface flips polarity with
     the theme — the client-identity band on case status is --ink, which is
     near-black in light mode and near-white in dark mode — is a different
     case: it needs --brand-on-dark only in light mode and --brand-dark once
     the page itself is dark, exactly the way ordinary page text does.) */
  --brand-on-dark: #ff5a56;

  /* Semantic state — deliberately not brand red for good/warn/info, so a
     "your package is ready" note and a "call this client" button don't fight
     for the same colour. Critical keeps brand red on purpose (see the design
     direction doc: money-at-risk flagged in the money company's own colour
     is coherent) but is only ever used on badges/borders/text, never on a
     clickable primary action — that rule is what keeps it from being
     confused with the brand CTA. */
  --good: #146c56;
  --good-tint: #e9f5f0;
  --warn: #8a5a00;
  --warn-tint: #fbf1de;
  --info: #2a5788;
  --info-tint: #eaf1f9;
  --critical: var(--brand);
  --critical-tint: var(--brand-tint);

  /* The line of each state, which the system never had.
     ------------------------------------------------------------------
     Every state already carried an ink and a tint, and no border — so a
     bordered status pill had nowhere to go and four different borders were
     typed by hand in staff.css: #bfdccd, #dba7a9, #f0cdcf, #fdf6f5. Each is
     somebody eyeballing the same idea a fifth time. A line is a third of a
     state, not a one-off, and it belongs here beside the other two. */
  --good-line: #bfdccd;
  --warn-line: #e7d3a8;
  --info-line: #b9cde4;
  --critical-line: #dba7a9;
  /* A row that has waited too long. Not an error — nothing is broken — so it
     is the faintest possible brand ground rather than the critical tint. */
  --stale-wash: #fdf6f5;
  --stale-ink: #7c1610;

  /* Focus — one ring, used everywhere, brand-tinted so it never reads as a
     browser default. 3px solid-alpha, not a thin 1px line an older user on
     a phone in sunlight will not see. */
  --focus-ring: 0 0 0 3px rgba(167, 1, 2, 0.7);
  --focus-ring-offset: 2px;

  /* Radii — one language: small controls, cards, nothing else. The previous
     stylesheets used eleven values between 6px and 20px with no logic to
     which surface got which; consolidated to three. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 20px;

  /* Shadow — two only. Money/legal work does not get a glossy elevation
     system; a card either sits on the page (sm) or is genuinely floating
     above it, like the assistant panel or a modal (lifted). */
  --shadow-sm: 0 1px 2px rgba(23, 20, 18, 0.06), 0 1px 1px rgba(23, 20, 18, 0.04);
  --shadow-lifted: 0 12px 32px -12px rgba(23, 20, 18, 0.32), 0 2px 8px rgba(23, 20, 18, 0.08);

  /* Spacing — 4px base. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 56px;
  --space-10: 72px;

  /* Type scale. Body sizes never drop below 14px anywhere a client reads —
     NN/g's senior-usability research (see evidence doc §7) sets 12pt/16px as
     the floor for this audience, and the portal's default body text sits
     above that floor rather than at it. */
  --text-display-xl: 700 2.25rem/1.12 var(--font-display);   /* 36px — page-level heading */
  --text-display-lg: 700 1.875rem/1.15 var(--font-display);  /* 30px — step/section heading */
  --text-display-md: 700 1.375rem/1.2 var(--font-display);   /* 22px — card heading */
  --text-body-lg: 400 1.0625rem/1.6 var(--font-body);         /* 17px — primary reading size */
  --text-body-md: 400 1rem/1.55 var(--font-body);             /* 16px — default */
  --text-body-sm: 400 0.875rem/1.5 var(--font-body);          /* 14px — captions, hints, meta */
  --text-label: 700 0.8125rem/1.3 var(--font-body);           /* 13px — field labels, eyebrows */
  --text-mono: 400 0.875rem/1.4 var(--font-mono);              /* case refs, figures */

  /* Layout measure — the client surfaces are a single reading column; the
     staff console is a working width. Two tokens, not a grid system. */
  --measure-form: 40rem;   /* 640px — sign-in, one onboarding question */
  --measure-case: 46rem;   /* 736px — case status, has more to show at once */
  --measure-console: 74rem; /* 1184px — staff console working width */

  /* Minimum tap target, per the hard constraint and NN/g's touch research. */
  --tap-min: 44px;
}

/* --- Dark tokens ------------------------------------------------------------
   Repaints the same names. Brand red needs two different values depending on
   role: #A70102 keeps working as a *fill* (button backgrounds, badges) because
   white text on it is still 8.2:1 regardless of page background — but as
   *text/link colour on the dark page itself* it only hits ~2.3:1 against a
   near-black surface, which fails. --brand-on-dark (#ff5a56, ~6.1:1) is the
   text/link/icon value; --brand stays the fill value your components already
   use. Component authors should default to --brand and only reach for
   --brand-on-dark when applying colour to text or an outline. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --ink: #f3f0ea;
    --body: #d8d2c6;
    --muted: #a49c8d;
    --faint: #756e61;
    --line: #3a352c;
    --line-strong: #4c4636;
    --surface: #211d19;
    --surface-sunken: #191613;
    --bg: #141210;

    --brand: #c81f1c;       /* fill — ~3.2:1 vs bg, white text on it ~5.8:1 */
    --brand-dark: #931613;
    --brand-tint: #2c1614;
    --brand-ink: #ffffff;
    --brand-on-dark: #ff5a56; /* text/link/icon use, ~6.1:1 vs bg */

    --good: #4bbf98;
    --good-tint: #142822;
    --warn: #d9a441;
    --warn-tint: #2a2210;
    --info: #7aa8de;
    --info-tint: #17222f;
    --critical: var(--brand-on-dark);
    --critical-tint: var(--brand-tint);
    --good-line: #2f4c40;
    --warn-line: #4a3c18;
    --info-line: #2f4460;
    --critical-line: #5c2b28;
    --stale-wash: #241b1a;
    --stale-ink: #ffb4ad;

    --focus-ring: 0 0 0 3px rgba(255, 90, 86, 0.4);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.3);
    --shadow-lifted: 0 12px 32px -12px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.4);
  }
}

/* Manual override hook — unused until a toggle exists, harmless until then. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --ink: #f3f0ea; --body: #d8d2c6; --muted: #a49c8d; --faint: #756e61;
  --line: #3a352c; --line-strong: #4c4636;
  --surface: #211d19; --surface-sunken: #191613; --bg: #141210;
  --brand: #c81f1c; --brand-dark: #931613; --brand-tint: #2c1614; --brand-ink: #ffffff;
  --brand-on-dark: #ff5a56;
  --good: #4bbf98; --good-tint: #142822;
  --warn: #d9a441; --warn-tint: #2a2210;
  --info: #7aa8de; --info-tint: #17222f;
  --critical: var(--brand-on-dark); --critical-tint: var(--brand-tint);
  --good-line: #2f4c40; --warn-line: #4a3c18; --info-line: #2f4460;
  --critical-line: #5c2b28; --stale-wash: #241b1a; --stale-ink: #ffb4ad;
  --focus-ring: 0 0 0 3px rgba(255, 90, 86, 0.4);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.3);
  --shadow-lifted: 0 12px 32px -12px rgba(0, 0, 0, 0.6), 0 2px 8px rgba(0, 0, 0, 0.4);
}
:root[data-theme="light"] { color-scheme: light; }

/* --- Base reset ------------------------------------------------------------
   Deliberately small. Component styling belongs in the pages that consume
   this file, not here — this is tokens plus the handful of rules that have
   to apply globally to be trustworthy (focus visibility, tap targets,
   [hidden] winning). */

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

html {
  background: var(--bg);
  color-scheme: light dark;
}

body {
  margin: 0;
  color: var(--body);
  background: var(--bg);
  font: var(--text-body-md);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { color: var(--ink); margin: 0; }
p { margin: 0; }
a { color: var(--brand); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) a{ color: var(--brand-on-dark); } }

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

/* One focus treatment, everywhere, including for custom controls that use
   role="button" — a screen-reader/keyboard user on this audience is not a
   hypothetical. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Real tap targets. Anything that can be pressed gets the floor, even if its
   visible content is smaller — padding, not just touch-action, closes the
   gap between a 32px icon and a 44px legal minimum. */
button, a, input[type="checkbox"], input[type="radio"], select {
  min-height: var(--tap-min);
}
input[type="checkbox"], input[type="radio"] { min-width: var(--tap-min); }

/* An author [hidden] rule beats any component class that also sets display.
   Written once, globally, rather than re-litigated per stylesheet — see the
   existing comment to this effect in app/globals.css and public/staff.css,
   consolidated here so there is one place it can be wrong. */
[hidden] { display: none !important; }

/* Respect a user's OS-level motion preference. Nothing in this system
   depends on motion to convey information, so turning it off costs nothing. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
