/* ============================================================ *
 * GENERATED FILE — DO NOT EDIT.                                 *
 * Mirror of website/src/design-tokens.css                               *
 * copied here by scripts/sync_design_system.py so the FastAPI-   *
 * served dashboard portal can <link> the canonical v4 design     *
 * system. Edit the SOURCE in website/src/, then re-run the sync. *
 * CI (test_design_system_sync.py) fails the build if this copy   *
 * drifts from its source.                                        *
 * ============================================================ */
/* ═══════════════════════════════════════════════════════════════════
   TREASURYFLOW — DESIGN SYSTEM v4 · "LEDGER"
   The single canonical token system. Authored 2026-05-15 by Chief Design Officer.
   Supersedes v3 (Square-quality edition) and the three drifted token blocks
   in portal.html, taskpane styles.css, and the orphaned website/portal.html.

   ── DESIGN PHILOSOPHY · "Excel-spirit" ──────────────────────────────
   TreasuryFlow is Excel-native. The product should feel native to a finance
   professional who lives in spreadsheets. So the system is built like the
   cleanest, calmest spreadsheet a CFO has ever opened:

     · A WHITE canvas. Not a colored dashboard. White is the default. Color
       is the exception, earned by importance.
     · HAIRLINE structure. Borders and gridlines do the structural work;
       shadow is reserved for things that genuinely float (popovers, modals,
       toasts). Linear's principle: "structure should be felt, not seen."
     · INK-BLACK text on a near-monochrome neutral ramp. Numbers in a tabular
       figure style so digits align in columns — a financial typography
       convention, not decoration.
     · ONE accent — deep teal (#0F766E). It appears on the single most
       important number or action per screen. When in doubt, remove color.
     · Semantic cash colors (up / down / neutral / warning) are the ONLY
       other hues, and they encode meaning a CFO is trained to read.

   The bet (validated by the 2026-04-25 color research + 14/14 competitive
   scan): a 40-60 CFO trusts software that looks like QuickBooks/Excel/their
   bank portal — white, quiet, legible — over software that looks "modern."
   Visual restraint is a proxy for operational maturity. A busy, over-colored
   UI signals a team that hasn't made hard editorial decisions — which a CFO
   reads as a team that hasn't made hard security decisions either.

   ── WHAT CHANGED FROM v3 ─────────────────────────────────────────────
   PRESERVED (the audit praised these — do not regress):
     · Every AA contrast value. The 2026-04-25 audit run is intact and
       extended; ratios are annotated per token per background below.
     · Inter / Source Serif 4 / JetBrains Mono. The 1.333 modular scale.
     · The reduced-motion discipline and GPU-only motion approach.
   EVOLVED:
     · Neutral ramp formalized: 0→900 ink scale, white-dominant. This is
       new — v3 had scattered text tokens but no canonical surface ramp.
     · Coral/peach accent RETIRED. Founder directive: ONE accent. Coral was
       "visual accent only, never text" — i.e. it never paid its way. Gone.
     · Cash-semantic colors added: --cash-up / --cash-down / --cash-flat /
       --cash-warn. A treasury product needs first-class up/down language.
     · Gridline + table tokens added — the spreadsheet-grade table is core.
     · "Noir" dark-section tokens RETIRED from the canonical set. White-
       dominant means no full-dark sections. (One ink CTA panel survives as
       a component treatment, not a token family.)
     · Compat-alias block kept LIVE (legacy site still imports this file) but
       quarantined at the bottom and marked for deletion once pages migrate.
     · Density spacing + radius re-grounded on an 8px base (4px micro-step
       retained) so the same tokens serve a marketing page AND a dense
       dashboard grid.
   ═══════════════════════════════════════════════════════════════════ */

:root {

  /* ═══════════════════════════════════════════════════════════════════
     1 · NEUTRAL RAMP — the white-dominant foundation
     A 10-stop ink scale from paper-white to near-black. Every surface,
     border, and text color is drawn from here. "Slate-warm" — a hair of
     warmth so white reads as paper, not as a screen (Linear's 2026 move:
     warm-neutral grey, never cold blue-grey).
     ─────────────────────────────────────────────────────────────────── */
  --ink-0:   #FFFFFF;   /* Paper. The canvas. Cards, page, table cells.        */
  --ink-25:  #FCFCFB;   /* Faintest warm off-white — hover row, inset wells.   */
  --ink-50:  #F7F7F5;   /* Section tint, table header band, zebra stripe.      */
  --ink-100: #F0F0EE;   /* Subtle fill — disabled surface, skeleton base.      */
  --ink-150: #E7E7E4;   /* Hairline gridline (the spreadsheet line).           */
  --ink-200: #D9D9D5;   /* Default border — cards, dividers, inputs at rest.   */
  --ink-300: #BFBFB9;   /* Strong border — input focus-adjacent, separators.  */
  --ink-400: #8C8C85;   /* Quiet text — meta, captions, placeholder.   5.4:1   */
  --ink-500: #5F5F58;   /* Secondary text — body on white.            7.6:1    */
  --ink-700: #36363A;   /* (reserved) deep neutral for ink panels.             */
  --ink-900: #0B1020;   /* Primary text — headlines, body, numbers.  18.9:1    */

  /* ── Semantic surface aliases (consume these in components, not raw ink) ── */
  --surface-page:        var(--ink-0);    /* The white canvas.                */
  --surface-raised:      var(--ink-0);    /* Cards — white, defined by border.*/
  --surface-sunken:      var(--ink-50);   /* Wells, section tints, code.      */
  --surface-hover:       var(--ink-25);   /* Row / cell hover.                */
  --surface-selected:    #ECFBF8;         /* Selected row — faintest teal.    */
  --surface-disabled:    var(--ink-100);  /* Disabled control fill.           */
  --surface-overlay:     rgba(11, 16, 32, 0.48);  /* Modal scrim.             */
  --surface-ink:         var(--ink-900);  /* The one dark panel (final CTA).  */

  /* ═══════════════════════════════════════════════════════════════════
     2 · TEXT — all AA-verified on the surfaces they're used on
     Audit basis: 2026-04-25 run, re-verified 2026-05-15 against the v4
     neutral ramp. Ratios stated below are vs --ink-0 (#FFFFFF) unless noted.
     ─────────────────────────────────────────────────────────────────── */
  --text-primary:    var(--ink-900);   /* 18.93:1 — headlines, body, numbers */
  --text-secondary:  var(--ink-500);   /*  7.58:1 — body, supporting copy    */
  --text-quiet:      var(--ink-400);   /*  5.42:1 — labels, meta, captions   */
  --text-disabled:   #B0B0AA;          /*  2.9:1  — disabled only (non-text-critical) */
  --text-on-accent:  #FFFFFF;          /* On teal/ink fills — 5.9:1+ on teal */
  --text-on-ink:     #F4F4F6;          /* On the ink panel — 16.5:1 on ink-900*/
  --text-on-ink-soft: rgba(244,244,246,0.74); /* Secondary on ink — 9.6:1    */
  --text-link:       #0F766E;          /*  5.47:1 — links on white           */
  --text-link-hover: #0B5E58;          /*  6.95:1 — visible hover state       */

  /* ═══════════════════════════════════════════════════════════════════
     3 · ACCENT — ONE accent. Deep teal. The whole brand.
     Teal = trust + money in fintech, and it is calm enough to sit on a
     white finance canvas without shouting. Used on the single most
     important number/action per screen. Everything else is neutral.
     ─────────────────────────────────────────────────────────────────── */
  --accent:          #0F766E;   /* Deep teal — THE brand color.               */
  --accent-hover:    #0E6B62;   /* Button hover.                              */
  --accent-active:   #0C5C55;   /* Button pressed.                            */
  --accent-strong:   #0A4D47;   /* Deepest teal — text on teal-soft (8.1:1).  */
  --accent-soft:     #ECFDF5;   /* Teal tint — selected wells, icon chips.    */
  --accent-softer:   #F4FBF8;   /* Faintest teal wash — large fills.          */
  --accent-border:   #B6E3DC;   /* Teal hairline — focus rings on soft fills. */
  --accent-contrast: #FFFFFF;   /* Text/icon on a solid teal fill.            */
  --accent-on-ink:   #5EEAD4;   /* Luminous teal — the accent on ink/navy surfaces.
                                   The on-white --accent (#0F766E) is too dark to read
                                   on dark. CSS dark-surface uses ONLY (ink CTA panel,
                                   dark chips). The Liquidity-Mesh <canvas> constant
                                   P_FAST (portal.html:~19365) holds this same value as
                                   a literal by necessity (var() can't reach canvas) —
                                   keep the two in sync deliberately. 9.0:1 on ink-900. */

  /* Canonical brand aliases — the wordmark, the logo mark, the focus ring
     all reference these so "the brand color" has exactly one source. */
  --brand:           var(--accent);
  --brand-ink:       var(--ink-900);   /* Wordmark text — ink, not teal.      */
  --focus-ring:      var(--accent);

  /* ── Gradient WORDMARK — the one canonical gradient-text spec ──────────
     The brand's two anchor colors (teal → navy) as a SINGLE directional
     ramp. Used on the highlighted word(s) inside marketing H1s
     (.hero__title-accent, referral / partner-signup / firm-capacity).
     ONE definition; every usage references this token.

     WHY two stops, not three: the retired spec was
       teal 0% → navy 60% → coral 100%
     but coral was collapsed to teal, so it rendered teal → navy → TEAL —
     a symmetric swing that crossed the murky teal/blue boundary twice and
     dipped through a desaturated blue-grey mid-blend (~#16587C). The word
     read as three colors mid-phrase and looked like a render glitch.
     A monotonic teal→navy ramp reads as ONE word: both endpoints clear
     AA on white (teal #0F766E = 5.47:1, navy #1E3A8A = 10.36:1) and a
     monotonic ramp never dips below the lower endpoint, so EVERY point of
     the gradient clears AA 4.5:1. Navy stays in the brand — now as the
     high-contrast terminal stop, not a muddy midpoint. (Ref: Stripe/Linear
     gradient-text — stay in one adjacent hue band, never swing back.) */
  --gradient-wordmark: linear-gradient(120deg, var(--accent) 0%, var(--accent-secondary) 100%);

  /* ═══════════════════════════════════════════════════════════════════
     4 · SEMANTIC CASH COLORS — the only other hues in the system
     A CFO reads up/down/flat/warning before they read words. These four
     encode cash direction. Each ships a -text grade (AA on white AND on
     its own soft fill) and a -soft fill. Reserve red strictly for genuine
     loss/breach — never decorative (red = danger to a finance buyer).
     ─────────────────────────────────────────────────────────────────── */

  /* CASH UP — inflow, positive delta, healthy. Green. */
  --cash-up:         #16A34A;   /* Icon / large-number / chart green (3.30:1) */
  --cash-up-text:    #15803D;   /* Text-grade — 4.83:1 white, 4.6:1 on soft   */
  --cash-up-soft:    #DCFCE7;   /* Positive-delta pill background.            */
  --cash-up-border:  #A7E8BF;   /* Hairline for positive cards.               */
  --cash-up-text-strong: #14532D; /* green-900 — deep grade for text on --cash-up-soft (≥7:1). */

  /* CASH DOWN — outflow, negative delta, loss. Red — used sparingly. */
  --cash-down:       #DC2626;   /* Icon / large-number red (4.83:1)           */
  --cash-down-text:  #B91C1C;   /* Text-grade — 6.36:1 white, 5.2:1 on soft   */
  --cash-down-soft:  #FEE6E6;   /* Negative-delta pill background.            */
  --cash-down-border:#F3B0B0;   /* Hairline for negative cards.               */
  --cash-down-text-strong: #7F1D1D; /* red-900 — deep grade for text on --cash-down-soft (≥7:1, AAA-leaning). */

  /* CASH FLAT — no movement, neutral, "as expected". Pure neutral, no hue. */
  --cash-flat:       var(--ink-400);   /* Flat-delta dash, neutral arrow.     */
  --cash-flat-text:  var(--ink-500);   /* Flat-delta label — 7.58:1.          */
  --cash-flat-soft:  var(--ink-100);   /* Flat-delta pill background.         */
  --cash-flat-border:var(--ink-200);

  /* WARNING — runway low, variance breach, action-needed. Amber. */
  --warn:            #D97706;   /* Icon / large-number amber (3.19:1)         */
  --warn-text:       #B45309;   /* Text-grade — 4.75:1 white, 4.6:1 on soft   */
  --warn-soft:       #FEF3C7;   /* Warning pill / banner background.          */
  --warn-border:     #F3D98B;   /* Hairline for warning cards.                */
  --warn-text-strong: #92400E;  /* amber-800 — deep grade for text on --warn-soft (≥7:1). */

  /* INFO — neutral-notice SEVERITY. The fourth status alongside up / down /
     warn. A restrained, deep "bank-statement" dusty blue — blue is the
     universal information convention (Material, Polaris, Carbon all use it),
     and it is unmistakably NOT the accent teal, NOT warn amber, NOT danger
     red. Deliberately desaturated and deep (NOT the bright retired-v3
     #0071E3) so it reads considered, in the v4-restraint spirit.

     --info is the SOLID hue — what a solid info fill uses (the info toast,
     an info status dot). --info-text is the text grade for an info label on
     white OR on --info-soft. --info-soft / --info-border are the faint
     pill / banner background + hairline.

     The teal-family --info-text/-soft/-border that lived here before were an
     ALIAS of the accent — fine for a faint inline insight chip, useless for
     a status that must be visually separable from a primary-accent surface.
     A real severity needs its own hue: an info toast sitting next to a teal
     accent toast must not look like the same kind of message.

     AA basis (2026-05-18 CDO audit): --info #2563A8 = 6.12:1 on white (AA
     for the 13px+ bold toast label) and white-on-#2563A8 = 6.12:1 (the
     toast's white text — near AAA). --info-text #1F5491 = 7.68:1 on white
     and 6.62:1 on --info-soft. */
  --info:            #2563A8;   /* Solid info — toast fill, status dot. 6.12:1 */
  --info-text:       #1F5491;   /* Text grade — 7.68:1 white, 6.62:1 on -soft  */
  --info-soft:       #E7EFF8;   /* Info pill / banner background.              */
  --info-border:     #BCD2EA;   /* Hairline for info cards.                    */
  --info-contrast:   #FFFFFF;   /* Text/icon on a solid --info fill — 6.12:1.  */

  /* ═══════════════════════════════════════════════════════════════════
     4b · CATEGORICAL DATA-VIZ PALETTE — for CATEGORY charts only
     ───────────────────────────────────────────────────────────────────
     The four cash-semantic hues above encode DIRECTION (up/down/flat/warn) —
     a CFO reads them as good/bad. This palette is the opposite job: it tells
     two CATEGORIES apart (treasury composition — operating vs restricted vs
     investment; spend by category — payroll vs rent vs software vs …). The
     segments are peers, not a verdict.

     ⚠ HARD RULE — categorical ≠ semantic. Never use a --chart-* token where a
       chart is directional (good/bad, inflow/outflow, healthy/at-risk) — that
       chart keeps --cash-up* / --cash-down* / --warn*. And never let a
       --chart-* token sit next to or override the semantic green/red. A
       category is never a verdict; a verdict is never a category.

     DESIGN (v4 "Ledger" restraint — references: Stripe dashboard charts,
     Mercury analytics, Linear cycle colors):
       · Anchored on the brand teal: --chart-1 = --accent. The largest /
         primary category gets the brand color — same "one accent on the most
         important thing" rule the rest of the system follows.
       · Muted, not saturated. Every hue sits in a narrow saturation band so
         the set reads "considered," never a primary-color rainbow. A
         saturated wheel signals a junior team — the same tell §0 calls out.
       · Color-blind safe by LIGHTNESS, not hue. Each token has a deliberately
         different greyscale L*, so the ordered set stays 6 distinct steps
         even in full greyscale or under deuteranopia/protanopia (~8% of men —
         the CFO demographic). No two adjacent tokens lean on a red-vs-green
         distinction; chart-3 (amber) vs chart-5 (sage) — the closest
         red/green pair — are split by a clear lightness margin.
       · --chart-5 is a desaturated SAGE green chosen specifically so a
         category is never mistaken for the semantic inflow green
         (--cash-up #16A34A). The two greens are intentionally different.
       · 6 hues — covers the busiest categorical chart (a standard B2B finance
         spend breakdown: payroll · rent · software · vendors · taxes · other)
         without over-coloring. Cycle back to --chart-1 past 6.

     USAGE: assign in token order (--chart-1 to the biggest slice, descending).
     Each ships a -soft fill for chips / faint backgrounds. All AA-verified for
     a small swatch + adjacent label on white.
     ─────────────────────────────────────────────────────────────────── */
  --chart-1:       #0F766E;   /* Deep teal — THE brand. Primary/largest slice. */
  --chart-1-soft:  #E3F3F1;   /* Teal chip / faint fill.                       */
  --chart-2:       #3B6FB0;   /* Dusty blue — cool, clearly separable.   4.9:1 */
  --chart-2-soft:  #E6EDF6;   /* Blue chip / faint fill.                       */
  --chart-3:       #B45309;   /* Burnt amber — warm counterpoint (= --warn-text, AA). */
  --chart-3-soft:  #FBEBD6;   /* Amber chip / faint fill.                      */
  --chart-4:       #7E5BB8;   /* Muted violet — distinct hue + greyscale step. 4.8:1 */
  --chart-4-soft:  #EEE9F5;   /* Violet chip / faint fill.                     */
  --chart-5:       #2F8F6B;   /* Sage green — desaturated, NOT the cash-up green. 4.0:1 */
  --chart-5-soft:  #E4F1EB;   /* Sage chip / faint fill.                       */
  --chart-6:       #9A6A2C;   /* Soft bronze — the quiet "other / remainder".  4.6:1 */
  --chart-6-soft:  #F1EADD;   /* Bronze chip / faint fill.                     */

  /* Ordered list — for JS that needs to cycle the palette programmatically.
     A consumer reads this once: getComputedStyle(root).getPropertyValue(...). */
  --chart-series:  #0F766E, #3B6FB0, #B45309, #7E5BB8, #2F8F6B, #9A6A2C;

  /* Chart structural neutrals — gridlines / axes / track inside a chart. */
  --chart-grid:    var(--ink-150);   /* Plot gridlines — the spreadsheet line. */
  --chart-axis:    var(--ink-300);   /* Axis rule, baseline.                   */
  --chart-track:   var(--ink-100);   /* Empty bar/track behind a value.        */

  /* ═══════════════════════════════════════════════════════════════════
     4c · AI ASSISTANT — the one deliberate sub-brand accent
     ───────────────────────────────────────────────────────────────────
     A DELIBERATE, GOVERNED exception to the one-accent rule — and the ONLY
     one. The AI surface (the Ask-AI FAB, the Ask-AI drawer, the trial-
     upgrade chrome, the BYOE AI-assist banner) is a different MODE of
     interaction: generative, conversational, probabilistic — sitting on top
     of the deterministic ledger. Teal means "the most important action on
     this screen" — a teal FAB would read as a primary CTA like "Connect
     bank". A distinct accent makes the assistant read unmistakably as "the
     assistant" at a glance. This is the move Linear (AI = violet), Notion,
     and Raycast all make: the AI affordance is a different kind of thing,
     so it earns a different color.

     This is NOT a violation of "ONE accent". The one-accent rule governs
     which of the white-canvas surfaces earns color by importance. The AI
     accent is functional chrome — it encodes "this is the assistant", the
     same way --cash-up / --cash-down encode direction. A managed fourth
     functional hue, never a decorative gradient.

     WHAT --ai-* GOVERNS. Exactly the AI-mode chrome: the Ask-AI FAB
     (#ask-ai-fab pill + the retired round .ai-fab), the Ask-AI drawer
     (header, send button, user bubble), the trial-upgrade chrome, and the
     BYOE AI-assist banner. Those are the surfaces that consume --ai-accent /
     --ai-soft / --ai-border / --ai-gradient / --ai-glow / --ai-contrast.

     WHY THIS TOKEN FAMILY EXISTS — anti-drift. Before this block the AI-mode
     chrome reached for several uncoordinated raw values (#7C3AED +
     rgba(124,58,237,…) on the Ask-AI FAB / drawer; #2563EB as the gradient
     far-stop; rgba(139,92,246,…) on the BYOE AI-assist banner;
     rgba(59,130,246,…) on the trial banner; rgba(99,102,241,…) on the
     now-retired round .ai-fab) — not a sub-brand, just separate reaches for
     "a purpley-blue". A sub-brand worth keeping is a sub-brand worth
     governing. One hue (--ai-accent, violet-600) is now canonical for AI
     chrome; the blue survives as the far stop of the FAB gradient
     (--ai-accent-2). Any future AI-mode surface consumes these tokens.

     NOT the account-role chip. portal.html's _ROLE_COLORS maps the
     categorical account-role palette — liquid (teal), restricted (amber),
     other (slate), investment (violet ~#A78BFA). That violet is deliberately
     SEPARATE: it is categorical data (telling account roles apart), not AI
     chrome, so it lives in the categorical lane alongside the chart series —
     not here. Do not fold _ROLE_COLORS.investment into --ai-*; an AI banner
     and an Investment account chip are different kinds of thing.

     NOT a chart color. --chart-4 (#7E5BB8) is a categorical violet for
     telling chart SLICES apart — a different job, a different governance
     lane. Never use --ai-accent in a chart or --chart-4 on an AI surface.

     AA basis (2026-05-18 CDO audit): white-on-#7C3AED = 5.70:1 — AA for the
     FAB / button label (13px+ bold) and the white drawer-bubble text.
     ─────────────────────────────────────────────────────────────────── */
  --ai-accent:        #7C3AED;   /* Violet-600 — THE AI sub-brand hue.   5.70:1 */
  --ai-accent-2:      #2563EB;   /* Blue partner — far stop of the AI gradient. */
  --ai-soft:          #F1EBFD;   /* Faint violet wash — AI banner / chip fill.  */
  --ai-border:        #D6C6F5;   /* Violet hairline — AI banner / chip border.  */
  --ai-contrast:      #FFFFFF;   /* Text/icon on a solid --ai-accent fill.      */
  --ai-glow:          rgba(124,58,237,0.32);  /* FAB drop-shadow / focus halo.  */
  /* The signature AI gradient — the FAB, the send button, the user bubble.
     A token so the two-stop violet→blue look has exactly one source — both
     stops reference the hue tokens above, so there is no literal to drift. */
  --ai-gradient:      linear-gradient(135deg, var(--ai-accent), var(--ai-accent-2));

  /* ═══════════════════════════════════════════════════════════════════
     5 · BORDERS & GRIDLINES — hairline-first
     The spreadsheet structure. These do the layout work that shadow does
     in other systems. Three weights + a dedicated gridline token.
     ─────────────────────────────────────────────────────────────────── */
  --border-subtle:   var(--ink-150);   /* Barely-there — internal dividers.  */
  --border-default:  var(--ink-200);   /* Cards, inputs, dividers at rest.   */
  --border-strong:   var(--ink-300);   /* Emphasis dividers, input hover.    */
  --border-focus:    var(--accent);    /* Focus ring color.                  */
  --gridline:        var(--ink-150);   /* THE spreadsheet line — table rules.*/
  --gridline-strong: var(--ink-200);   /* Table header rule, section rule.   */
  --border-width:    1px;              /* Hairline. One width. Always.       */

  /* ═══════════════════════════════════════════════════════════════════
     6 · ELEVATION — shadow used sparingly, only for things that float
     Five steps but the rule is: a card at rest gets NO shadow (border
     defines it). Shadow is earned by lifting off the canvas — hover,
     popover, modal, toast. Shadows are soft, low-spread, neutral-tinted.
     ─────────────────────────────────────────────────────────────────── */
  --shadow-none:     none;
  --shadow-raised:   0 1px 2px rgba(11,16,32,0.04), 0 2px 8px rgba(11,16,32,0.05);   /* hover lift  */
  --shadow-popover:  0 4px 12px rgba(11,16,32,0.08), 0 16px 36px rgba(11,16,32,0.10); /* dropdowns  */
  --shadow-modal:    0 16px 32px rgba(11,16,32,0.14), 0 40px 80px rgba(11,16,32,0.20); /* dialogs   */
  --shadow-toast:    0 6px 16px rgba(11,16,32,0.12), 0 20px 48px rgba(11,16,32,0.16);
  --shadow-focus:    0 0 0 3px rgba(15,118,110,0.18);   /* focus glow (paired w/ outline) */
  --shadow-focus-danger: 0 0 0 3px rgba(220,38,38,0.16);

  /* ═══════════════════════════════════════════════════════════════════
     7 · TYPOGRAPHY
     One sans (Inter — UI + body), one serif (Source Serif 4 — editorial
     accent ONLY, never UI), one mono (JetBrains Mono — every number).
     Strict 1.333 (Major Fourth) modular scale. Numbers always tabular.
     ─────────────────────────────────────────────────────────────────── */
  --font-sans:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-display: 'Outfit', var(--font-sans);
  --font-serif: 'Source Serif 4', 'Crimson Pro', Georgia, serif;
  --font-mono:  'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;

  /* Glassmorphism & Radial Glows (Nume style UI polish) */
  --glass-bg: rgba(255, 255, 255, 0.45);
  --glass-border: 1px solid rgba(255, 255, 255, 0.08);
  --glass-backdrop-filter: blur(12px);
  --radial-glow-1: radial-gradient(circle at 50% 50%, rgba(15, 118, 110, 0.08) 0%, rgba(255, 255, 255, 0) 70%);
  --radial-glow-2: radial-gradient(circle at 100% 0%, rgba(124, 58, 237, 0.06) 0%, rgba(255, 255, 255, 0) 50%);

  /* Modular scale — 1.333 ratio. xs/sm/base are the dashboard's working
     range; the large tiers are marketing display. 13px floor on real
     content (never the 9-11px the audit found in the portal). */
  --text-xs:    12px;   /* Overlines, table meta, dense chrome labels.        */
  --text-sm:    13px;   /* Dashboard body, table cells, secondary UI. FLOOR.  */
  --text-base:  15px;   /* Default body / UI text.                            */
  --text-md:    17px;   /* Emphasized body, card titles.                      */
  --text-lg:    20px;   /* Sub-headings, lead-in copy.                         */
  --text-xl:    26px;   /* H3, large KPI labels.                              */
  --text-2xl:   34px;   /* H2.                                                */
  --text-3xl:   46px;   /* Section display.                                   */
  --text-4xl:   61px;   /* Hero H1.                                           */
  --text-5xl:   82px;   /* Marketing hero display, sparingly.                 */

  /* Numeric display tiers — for KPI hero numbers (mono, tabular). */
  --num-sm:     20px;   /* Inline metric, table total.                        */
  --num-md:     30px;   /* KPI tile value.                                    */
  --num-lg:     44px;   /* Dashboard hero number (total cash position).       */
  --num-xl:     64px;   /* Marketing hero figure.                             */

  /* Weights — 5 only. Inter 300/600/700 + 400/500. No weight 800/900;
     v3 loaded 9 weights, the system uses these 5. */
  --weight-normal:   400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  /* Display weight — light, "understated authority" (the Stripe move).
     Used on the largest marketing display type only. */
  --weight-display:  300;

  /* Line heights */
  --lh-display: 1.04;   /* 60px+ display type.                                */
  --lh-heading: 1.16;   /* H1–H3.                                             */
  --lh-snug:    1.32;   /* Card titles, leads, table cells.                   */
  --lh-body:    1.6;    /* Paragraph body.                                    */
  --lh-loose:   1.75;   /* Legal / long-form.                                 */

  /* Letter spacing */
  --tracking-display: -0.035em;  /* Huge display.                             */
  --tracking-tight:   -0.02em;   /* Headings.                                 */
  --tracking-snug:    -0.01em;   /* Sub-headings, card titles.                */
  --tracking-normal:  0;
  --tracking-wide:    0.04em;    /* Small caps, badges.                       */
  --tracking-widest:  0.14em;    /* Overlines.                                */

  /* Numeric feature flags — apply via .num / --font-mono usage. */
  --numeric-tabular: 'tnum' 1, 'lnum' 1;   /* tabular + lining figures.       */

  /* ═══════════════════════════════════════════════════════════════════
     8 · SPACING — 8px base, 4px micro-step. One scale for marketing
     whitespace AND dense dashboard grids. The "Excel-grid rhythm": the
     dashboard lays out on a 8px sub-grid, sections on the large steps.
     ─────────────────────────────────────────────────────────────────── */
  --space-0:   0;
  --space-1:   2px;    /* Hairline gaps, icon nudges.                         */
  --space-2:   4px;    /* Micro — tight chrome, badge internal.               */
  --space-3:   8px;    /* Base unit — dense grid gap, control padding-y.      */
  --space-4:   12px;   /* Compact — table cell padding, input padding-y.      */
  --space-5:   16px;   /* Default — card internal gap, control padding-x.     */
  --space-6:   24px;   /* Comfortable — card padding, group gap.              */
  --space-7:   32px;   /* Loose — between cards, sub-section gap.             */
  --space-8:   48px;   /* Section internal rhythm.                            */
  --space-9:   64px;   /* Block separation.                                   */
  --space-10:  96px;   /* Section padding (compact).                          */
  --space-11:  128px;  /* Section padding (default).                          */
  --space-12:  160px;  /* Section padding (hero / generous).                  */

  /* Section rhythm — fluid clamps for the marketing site. */
  --section-y:     clamp(72px, 9vw, 128px);
  --section-y-sm:  clamp(48px, 6vw, 80px);
  --section-y-lg:  clamp(96px, 12vw, 160px);

  /* Dashboard layout metrics — the adaptive shell. */
  --dash-gutter:       16px;    /* Gap between dashboard widgets.             */
  --dash-pad:          24px;    /* Dashboard content padding.                 */
  --sidebar-w:         248px;   /* Sidebar expanded.                          */
  --sidebar-w-collapsed: 64px;  /* Sidebar collapsed (icon rail).             */
  --topbar-h:          60px;    /* Dashboard top bar height.                  */
  --row-h:             44px;    /* Data-table row — also the 44px tap floor.  */
  --row-h-compact:     36px;    /* Dense table mode (still > text legibility).*/

  /* ═══════════════════════════════════════════════════════════════════
     9 · RADIUS — opinionated and tight. A spreadsheet has square cells;
     our radius is small so the UI reads precise, not bubbly. One step
     up for cards, pill only for badges/toggles. No 20-28px hero radii
     (v3 had them; white-dominant restraint kills the soft-blob look).
     ─────────────────────────────────────────────────────────────────── */
  --radius-none:  0;       /* Table cells, gridded surfaces — true to Excel.  */
  --radius-xs:    4px;     /* Inputs, small controls, badges-square, chips.   */
  --radius-sm:    6px;     /* Buttons, menu items.                            */
  --radius-md:    8px;     /* Cards, panels, popovers — THE card radius.      */
  --radius-lg:    12px;    /* Large cards, modal, dashboard widgets.          */
  --radius-xl:    16px;    /* Marketing feature cards, hero preview.          */
  --radius-pill:  9999px;  /* Pills, toggles, avatars, status dots.           */

  /* ═══════════════════════════════════════════════════════════════════
     10 · MOTION — functional, fast, reduced-motion-aware
     Motion exists to give closure and confirm causality, never to
     decorate and never to make the user wait (Superhuman's rule).
     Fast durations; the slowest UI transition is 240ms.
     ─────────────────────────────────────────────────────────────────── */
  --ease-standard:  cubic-bezier(0.4, 0, 0.2, 1);    /* Default — most things.*/
  --ease-out:       cubic-bezier(0.16, 1, 0.3, 1);   /* Decelerated — entrances*/
  --ease-in:        cubic-bezier(0.4, 0, 1, 1);      /* Accelerated — exits.   */
  --ease-spring:    cubic-bezier(0.34, 1.4, 0.64, 1);/* Gentle overshoot — taps*/

  --duration-instant: 80ms;    /* Press feedback, tap-down.                   */
  --duration-fast:    140ms;   /* Hover, color, small state changes.          */
  --duration-base:    200ms;   /* Default — most transitions.                 */
  --duration-slow:    280ms;   /* Panel open, drawer, larger reveals.         */
  --duration-slower:  400ms;   /* Marketing scroll reveal (capped here).      */

  /* ═══════════════════════════════════════════════════════════════════
     11 · LAYOUT — containers
     ─────────────────────────────────────────────────────────────────── */
  --container-xs:     560px;   /* Auth, single-column forms.                  */
  --container-narrow: 720px;   /* Legal, long-form reading.                   */
  --container-base:   1080px;  /* Standard marketing content.                 */
  --container-wide:   1280px;  /* Wide marketing, nav.                        */
  --container-xwide:  1440px;  /* Hero, full-bleed sections.                  */
  --container-app:    1600px;  /* Dashboard max content width.                */

  /* ═══════════════════════════════════════════════════════════════════
     12 · Z-INDEX — named layers, no magic numbers
     ─────────────────────────────────────────────────────────────────── */
  --z-base:      0;
  --z-sticky:    20;    /* Sticky table headers, sticky KPI bar.              */
  --z-nav:       50;    /* Top nav / app top bar.                             */
  --z-sidebar:   60;    /* App sidebar (above content, below overlays).       */
  --z-dropdown:  100;   /* Menus, comboboxes, tooltips.                       */
  --z-overlay:   200;   /* Modal scrim.                                       */
  --z-modal:     210;   /* Modal dialog.                                      */
  --z-toast:     300;   /* Toast / undo rack — always on top.                 */
  --z-command:   320;   /* Cmd+K command palette — above toasts.              */

  /* ═══════════════════════════════════════════════════════════════════
     13 · COMPONENT TOKENS — semantic handles components reference so a
     future theme tweak happens in ONE place.
     ─────────────────────────────────────────────────────────────────── */
  --control-h:        36px;    /* Default control height (input, btn).        */
  --control-h-sm:     30px;    /* Compact control.                            */
  --control-h-lg:     44px;    /* Large control — also the tap-target floor.  */
  --tap-min:          44px;    /* WCAG / Apple minimum interactive size.      */
  --table-cell-pad-x: 12px;
  --table-cell-pad-y: 10px;

  /* ═══════════════════════════════════════════════════════════════════
     14 · COMPATIBILITY ALIASES — QUARANTINE ZONE
     The legacy marketing site (index.html, cfo.html, compare-*.html, etc.)
     still imports this file and references v3 token names. These aliases
     keep the live site rendering correctly during migration.

     ⚠ DO NOT reference these in new code. New components use the v4 names
       above. This block is DELETED page-by-page as surfaces migrate, and
       removed entirely once the migration is complete.
     ─────────────────────────────────────────────────────────────────── */
  /* v3 background names */
  --bg-page: var(--surface-page);
  --bg-page-soft: var(--ink-50);          /* legacy "soft page tint" — Matt-quote bars, pricing band */
  --bg-card: var(--surface-raised);
  --bg-tint: var(--ink-50);
  --bg-tint-warm: var(--ink-50);
  --bg-tint-cream: var(--ink-50);
  --bg-tint-peach: var(--ink-25);
  --bg-overlay: var(--surface-overlay);
  --bg-noir: var(--ink-900);
  /* v3 text names */
  --text-tertiary: var(--ink-500);
  --text-tertiary-light: var(--ink-400);
  --text-on-noir: var(--text-on-ink);
  --text-on-noir-soft: var(--text-on-ink-soft);
  /* v3 accent names */
  --accent-primary: var(--accent);
  --accent-primary-hover: var(--accent-hover);
  --accent-primary-active: var(--accent-active);
  --accent-primary-soft: var(--accent-soft);
  --accent-primary-border: var(--accent-border);
  --accent-primary-deep: var(--accent-strong);
  --accent-secondary: #1E3A8A;            /* navy — ACTIVE: terminal stop of --gradient-wordmark (10.36:1 on white) + soft-fill panels below */
  --accent-secondary-hover: #1E40AF;
  --accent-secondary-soft: #EFF6FF;       /* navy soft-fill — pricing/firm-capacity panels */
  --accent-secondary-border: #BFDBFE;
  --accent-warm-coral: var(--accent);     /* coral retired → collapses to teal */
  --accent-warm-coral-text: var(--cash-down-text);
  --accent-warm-peach: var(--accent-border);
  --accent-warm-soft: var(--accent-soft);
  --accent-success: var(--cash-up);
  --accent-success-text: var(--cash-up-text);
  --accent-success-soft: var(--cash-up-soft);
  --accent-warning: var(--warn);
  --accent-warning-text: var(--warn-text);
  --accent-warning-soft: var(--warn-soft);
  --accent-danger: var(--cash-down);
  --accent-danger-text: var(--cash-down-text);
  --accent-danger-soft: var(--cash-down-soft);
  --accent-teal: var(--accent);
  --accent-green: var(--cash-up-text);
  --accent-red: var(--cash-down-text);
  --accent-amber: var(--warn-text);
  --text-muted: var(--ink-400);
  /* v3 border names */
  --border-base: var(--border-default);
  --border-card: var(--border-default);
  --border-soft: var(--border-subtle);    /* legacy "barely-there hairline" — share-link dividers */
  /* v3 shadow names */
  --shadow-card: var(--shadow-raised);
  --shadow-sm: var(--shadow-raised);
  --shadow-md: var(--shadow-raised);
  --shadow-lg: var(--shadow-popover);
  --shadow-hero: var(--shadow-modal);
  --shadow-cta: var(--shadow-raised);
  --shadow-cta-hover: var(--shadow-popover);
  --shadow-warm: var(--shadow-raised);
  /* v3 type scale (1.333 v3 values mapped — kept so legacy clamps resolve) */
  --text-3xl-legacy: 32px;
  /* --text-4xl and --text-5xl are canonical v4 tokens (61px / 82px) defined
     in section 7 above. The v3 values (48px / 72px) are intentionally omitted
     here so the v4 definitions win. Use --text-6xl / --text-7xl for legacy
     references that previously pointed at the old 96px / 128px steps. */
  --text-6xl: 96px;
  --text-7xl: 128px;
  --weight-black: 700;          /* v3 used 800; collapse to bold */
  --weight-extrabold: 700;
  --weight-display-legacy: var(--weight-display);
  --text-display: 72px;
  /* v3 radius names */
  --radius-base: var(--radius-md);
  --radius-2xl: var(--radius-xl);
  --radius-3xl: var(--radius-xl);
  /* v3 motion names */
  --ease-emphasized: var(--ease-out);
  --duration-slowest: 400ms;
  /* v3 line-height/tracking names */
  --lh-tight: var(--lh-snug);
  --tracking-tightest: var(--tracking-display);
  --tracking-wider: 0.1em;
  --section-pad-y: var(--section-y);
  --section-pad-y-sm: var(--section-y-sm);
  --section-pad-y-lg: var(--section-y-lg);
  /* END QUARANTINE ZONE */
}

/* ═══════════════════════════════════════════════════════════════════
   RESET — minimal, system-wide
   ═══════════════════════════════════════════════════════════════════ */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-sans);
  background: var(--surface-page);
  color: var(--text-primary);
  font-size: var(--text-base);
  line-height: var(--lh-body);
  overflow-x: clip; /* clip, not hidden: hidden on the scroll root forces overflow-y:auto and breaks vertical scroll */
  /* Inter stylistic sets — better number alternates for finance UI. */
  font-feature-settings: 'cv11', 'ss01';
}

a {
  color: var(--text-link);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-standard);
}
a:hover { color: var(--text-link-hover); }

img, svg, video, canvas { max-width: 100%; display: block; }

button, input, select, textarea { font-family: inherit; font-size: inherit; }
button { cursor: pointer; }

::selection { background: var(--accent-soft); color: var(--accent-strong); }

/* ── Focus: visible, accent-ringed, never suppressed ── */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}
/* Mouse users don't get the ring; keyboard users always do. */
:focus:not(:focus-visible) { outline: none; }

/* ── Numbers: tabular figures everywhere they're declared ── */
.num, [data-num], .t-mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: var(--numeric-tabular);
  letter-spacing: 0;
}

/* ── Reduced motion: honor it globally. Decoration off; closure kept fast ── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
