/* ==========================================================================
   DESIGN TOKENS
   Single source of truth for color, spacing, type, radius, shadow.

   THEMING
   -------
   Light is the base, declared on :root. Dark overrides ONLY the colour
   tokens, at the bottom of this file, under :root[data-theme="dark"].

   There is exactly one dark block, not one per media query, because the
   theme is always resolved to an explicit data-theme attribute by
   assets/js/theme.js before first paint — including the "follow the
   operating system" case, which JS resolves and re-resolves if the OS
   setting changes while the app is open. That keeps this file DRY: a
   duplicated @media (prefers-color-scheme) block would be a second copy of
   every value to keep in step.

   Nothing outside this file should name a colour. If a component needs one
   that does not exist here, add a semantic token here rather than a hex
   value there — that is what makes a theme switch a token change instead of
   a sweep through twenty components.
   ========================================================================== */
:root {
  /* What the browser should assume for form controls, scrollbars and the
     like. Overridden in the dark block. */
  color-scheme: light;

  /* Brand — blue and white, anchored on the logo's own blue. Hierarchy comes
     from tonal weight within this one hue (a deep shade for primary buttons
     and headline surfaces, the base shade for structural/nav elements, pale
     tints for backgrounds and badge fills) rather than a second color family
     doing the "important vs. secondary" job blue alone can already do. */
  --color-primary: #2f5fed;
  --color-primary-dark: #2447c2;
  --color-primary-light: #e3e9ff;
  --color-primary-50: #f2f5ff;
  /* The strongest filled primary surface — the hero stat chip. Separate from
     --color-primary-dark because that token also means "primary hover" and
     "primary accent text", and in dark mode those want to get LIGHTER while
     a filled chip carrying white text has to stay dark. */
  --color-primary-emphasis: #2447c2;

  /* Reserved, not used on any primary surface — kept only as the documented
     escape hatch for a chart that someday needs a genuine second series.
     Buttons, hero cards, nav and badges must stay on the blue scale above. */
  --color-accent: #d97a1f;
  --color-accent-dark: #a85a0d;
  --color-accent-light: #fbe4cc;
  --color-accent-50: #fef6ec;

  /* Neutrals — clean, light, low-contrast surfaces */
  --color-bg: #f7f8fa;
  --color-surface: #ffffff;
  /* A surface that sits ABOVE another surface: modal sheets, dropdown menus,
     hover fills. In light mode it is the page tint (a card's hover reads as a
     faint grey); in dark mode it is LIGHTER than the card, because on dark
     backgrounds elevation reads as light, not shadow. */
  --color-surface-raised: #f7f8fa;
  /* Floating panels that sit OVER the page: modal sheets, combobox dropdowns,
     the date picker. Light mode wants plain white here (same as a card) while
     dark mode wants a lifted grey, so this cannot just be --color-surface. */
  --color-surface-overlay: #ffffff;
  --color-border: #e7e9ee;
  --color-border-strong: #d3d7e0;
  --color-text: #14161f;
  --color-text-muted: #63697b;
  --color-text-faint: #6b7184; /* ~4.9:1 on white — passes WCAG AA for normal text */

  /* Text/icons drawn ON a filled primary surface (buttons, the brand mark,
     the active bottom-nav chip). Named rather than hardcoded to #fff so the
     dark theme can change it if its primary ever gets light enough to need
     dark text on top. */
  --color-on-primary: #ffffff;

  /* Body links. Separate from --color-primary because primary doubles as a
     button background: a background wants to be dark enough for white text,
     while a link on the page background wants to be light enough to read.
     One value cannot do both once the page goes dark. */
  --color-link: #2f5fed;

  /* Scrim behind modals and the mobile drawer. */
  --color-scrim: rgba(16, 24, 40, 0.5);

  /* The animated highlight that sweeps a loading skeleton. */
  --color-skeleton-sheen: #eef1f5;

  /* Caret for a native <select>. A data URI cannot interpolate a CSS
     variable, so the whole image is the token and each theme supplies its
     own stroke colour. */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235b6472' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'></polyline></svg>");

  /* Status — deliberately its own family, never pulled from brand blue, so
     Completed/Draft/Error states stay readable and unambiguous against a
     blue-and-white UI. */
  --color-success: #15803d;
  --color-success-bg: #eafbf1;
  /* Danger TEXT. Darkened from #d92d20 to clear WCAG AA on the badge tint
     below: #d92d20 on #fdecec measured 4.23:1, under the 4.5:1 needed for
     13px text, which a "Suspended" badge is. #c9291d measures 4.82:1 there —
     a deliberate margin, since a value that only just scrapes 4.50 is one
     rounding away from failing again.
     Every other use of this token sits on a lighter background and only
     improves: on white 4.83 -> 5.50, on the page tint 4.55 -> 5.18. */
  --color-danger: #c9291d;
  --color-danger-bg: #fdecec;
  /* The FILLED danger surface (destructive buttons), as opposed to
     --color-danger which is the text/icon colour. Left at the original
     #d92d20: it carries WHITE text at 4.83:1, which already passes, and
     changing it would darken every Delete button for no accessibility gain.
     This is exactly the split the two tokens exist for. */
  --color-danger-solid: #d92d20;
  --color-danger-hover: #b7281b;
  --color-warning: #b45309;
  --color-warning-bg: #fef3e2;
  --color-info: #2f5fed;
  --color-info-bg: #eef2ff;

  /* Toasts are deliberately a dark, high-contrast surface in BOTH themes —
     they are transient overlays, and keeping them constant means a success
     message looks the same wherever it appears. */
  --color-toast-bg: #14161f;
  --color-toast-success: #0e5c33;
  --color-toast-error: #8f2419;
  --color-toast-info: #0b4a86;
  --color-toast-text: #ffffff;

  /* Sidebar — light, airy surface (not a dark enterprise panel) */
  --color-nav-bg: #ffffff;
  --color-nav-bg-active: var(--color-primary-50);
  --color-nav-text: var(--color-text-muted);
  --color-nav-text-active: var(--color-primary-dark);
  --color-nav-border: var(--color-border);

  /* Typography — mobile-first scale.
     These values are sized for a phone held at arm's length, then left alone
     on desktop: a 16px body is as readable on a laptop as it is on a 360px
     screen, and one scale across all widths is what keeps the app feeling
     like one product. The previous scale started at 15px with 12px meta
     labels, which read as cramped on a phone. */
  --font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --fs-xs: 0.8125rem;   /* 13px — smallest text in the system; meta labels only */
  --fs-sm: 0.875rem;    /* 14px — secondary text, table cells */
  --fs-base: 1rem;      /* 16px — body. Also the minimum for inputs: anything
                           smaller makes iOS Safari zoom on focus. */
  --fs-md: 1.125rem;    /* 18px — card and section titles */
  --fs-lg: 1.375rem;    /* 22px — page titles */
  --fs-xl: 1.625rem;    /* 26px — stat values */
  --fs-2xl: 2rem;       /* 32px — hero stat value */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --tracking-tight: -0.011em;

  /* Line heights — named so vertical rhythm is a decision, not an accident */
  --lh-tight: 1.2;      /* headings, stat values */
  --lh-snug: 1.35;      /* card titles, list rows */
  --lh-base: 1.5;       /* body copy */

  /* Spacing scale */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;
  --sp-9: 48px;

  /* Radius — crisp, not pill-shaped */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 999px;

  /* Shadow — used sparingly, never heavy */
  --shadow-sm: 0 1px 2px rgba(20, 22, 31, 0.04);
  --shadow-md: 0 6px 16px -4px rgba(20, 22, 31, 0.10);
  --shadow-lg: 0 16px 40px -8px rgba(20, 22, 31, 0.18);

  /* Layout */
  --header-h: 56px;
  --sidebar-w: 248px;
  --content-max: 1180px;

  /* Touch targets.
     --touch-target is the FLOOR: nothing interactive may be smaller, on any
     screen. --tap-comfortable is what primary controls get on a phone, where
     the finger is the pointer and the hand is often the one holding it.
     A "small" button is still 44px on mobile - small means less padding and
     smaller text, never a smaller hit area. */
  --touch-target: 44px;
  --tap-comfortable: 52px;

  /* Bottom navigation. Height excludes the safe-area inset, which is added
     separately so the bar clears the home indicator on modern phones. */
  --bottomnav-h: 60px;

  /* Breakpoints, for reference — CSS cannot use variables in media queries,
     so these are documentation for the three widths this app uses. Any new
     rule should pick one of them rather than inventing a fourth.
       sm  640px  phone -> large phone / small tablet
       md  900px  tablet: tables may replace cards
       lg 1024px  sidebar replaces drawer + bottom nav
     Below sm is the design target: 360 / 375 / 390 / 412 / 430. */

  /* Motion (kept minimal/functional only) */
  --transition-fast: 120ms ease;
  --transition-base: 180ms ease;
}

/* ==========================================================================
   DARK THEME

   Colour tokens only. Spacing, type, radius and layout are deliberately NOT
   redefined here — the two themes are the same product, and anything that
   changes shape between them is a bug, not a feature.

   Design notes:
   - The darkest surface is #0f1218, not #000. Pure black makes every border
     and shadow disappear and turns scrolling into a strobe on OLED screens.
   - Surfaces get LIGHTER as they rise: bg -> surface -> surface-raised. On a
     dark UI, elevation reads as light, not as shadow, so a modal over a card
     over the page is three steps up rather than three drop-shadows.
   - Body text is #e6e9f0, not #fff. Pure white on near-black is the classic
     cause of halation - the text appears to vibrate for anyone with even
     mild astigmatism.
   - The blue splits in two. --color-primary stays dark enough that white
     button text clears 4.5:1, while --color-link and --color-primary-dark
     (used for accent text and hover) are lightened so they read against a
     dark background. One blue cannot do both jobs.
   ========================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Brand. --color-primary is a BUTTON BACKGROUND first: white on #2f6ae8
     is ~4.6:1, so primary buttons keep white labels and stay legible.
     --color-primary-dark is the hover/accent-text value and is LIGHTER,
     because on dark surfaces "more prominent" means brighter. */
  --color-primary: #2f6ae8;
  --color-primary-dark: #7ba7ff;
  --color-primary-light: #24304b;   /* avatar + badge fills, focus rings */
  --color-primary-50: #1a2133;      /* faint tint: nav active, stat icons */
  /* Stays dark, unlike --color-primary-dark, because it carries white text. */
  --color-primary-emphasis: #2f6ae8;

  --color-accent: #e08a33;
  --color-accent-dark: #f0a75c;
  --color-accent-light: #3a2a17;
  --color-accent-50: #261c10;

  /* Neutrals. Three steps of elevation, each a real step you can see. */
  --color-bg: #0f1218;
  --color-surface: #171b23;
  --color-surface-raised: #1f2530;
  --color-surface-overlay: #1f2530;
  --color-border: #272d38;
  --color-border-strong: #3a4250;
  --color-text: #e6e9f0;
  --color-text-muted: #a4acbb;   /* ~7.5:1 on --color-surface */
  --color-text-faint: #8d95a5;   /* ~5.4:1 on --color-surface — still AA */

  --color-on-primary: #ffffff;
  --color-link: #7ba7ff;         /* ~6.9:1 on --color-bg */

  /* A heavier scrim: the layer beneath is already dark, so it needs more
     cover to read as "behind" the modal. */
  --color-scrim: rgba(3, 5, 9, 0.72);

  --color-skeleton-sheen: #2b3240;

  /* Same caret, lighter stroke. */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238d95a5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'></polyline></svg>");

  /* Status. Foregrounds lifted for contrast; the -bg tints are deep, low
     saturation fills rather than the pale washes light mode uses — a pastel
     badge on a dark card looks like a bug. */
  --color-success: #5ec27f;
  --color-success-bg: #14291d;
  --color-danger: #ff7a70;          /* danger TEXT on a dark surface */
  --color-danger-bg: #331a18;
  /* Deep enough for white button text (~5:1). The lighter --color-danger
     above would put white on salmon at about 2.3:1 — unreadable, and far too
     loud for a destructive action that should look serious, not neon. */
  --color-danger-solid: #b8392e;
  --color-danger-hover: #d0483c;
  --color-warning: #e0a136;
  --color-warning-bg: #302512;
  --color-info: #7ba7ff;
  --color-info-bg: #1c2740;

  /* Toasts stay a constant dark overlay in both themes; in dark mode they
     are lifted slightly so they separate from the page behind them. */
  --color-toast-bg: #262c38;
  --color-toast-success: #14512f;
  --color-toast-error: #7a2a22;
  --color-toast-info: #143f6b;
  --color-toast-text: #f2f4f8;

  /* Sidebar: a shade below the card surface, so the content area reads as
     the foreground even though both are dark. */
  --color-nav-bg: #12161d;
  --color-nav-bg-active: var(--color-primary-50);
  --color-nav-text: var(--color-text-muted);
  --color-nav-text-active: var(--color-primary-dark);
  --color-nav-border: var(--color-border);

  /* Shadows go nearly opaque black. A 4%-alpha shadow that reads as a soft
     edge on white is completely invisible on #171b23; the borders above do
     most of the separation work in this theme. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
  --shadow-md: 0 6px 16px -4px rgba(0, 0, 0, 0.55);
  --shadow-lg: 0 16px 40px -8px rgba(0, 0, 0, 0.68);
}
