/* Aktib web design tokens — one source for every web surface.
 *
 * Derived from the machine-readable spec in landing/brand-guidelines.html
 * (<script id="aktib-brand-guidelines">). `npm run brand:check` fails if the
 * raw scale below drifts from that spec, so this file cannot quietly diverge.
 *
 * Why this file exists: the landing pages, the business dashboard, and the
 * admin console each grew their own :root block, and all three defined --ink
 * as a different step of the same forest scale — #061F16, #082418, and
 * #06432F. Every one of them clears WCAG AAA on our paper grounds (9.4:1 at
 * the lightest), so this was never a legibility bug; it just meant body text
 * was a visibly different green depending on which Aktib surface you were on.
 *
 * The reconciliation: --ink is forest-900.
 *   - forest-950 is the deepest step, kept for high-emphasis display type.
 *   - forest-900 is body ink. The dashboard already used it, so the largest
 *     surface does not move.
 *   - forest-800 is the brand green for buttons, links, and accents. Admin was
 *     using it as body text, which is what made admin read lighter and greener
 *     than the dashboard sitting next to it.
 *
 * Usage: link this before a surface's own <style> block, then alias only what
 * that surface actually needs. Do not redeclare a raw scale value downstream —
 * alias it, so a brand change lands in one place.
 */

:root {
  color-scheme: light;

  /* ---- Raw scale. Mirrors brand-guidelines.html; do not edit in isolation. ---- */
  --forest-950: #061f16;
  --forest-900: #082418;
  --forest-800: #06432f;
  --forest-700: #075f42;
  --forest-600: #0f7b62;
  --lime-400: #d7f46d;
  --paper-50: #fffdf7;
  --paper-100: #fff7ec;
  --paper-200: #f5f1e8;
  --paper-300: #eee4d4;
  --clay-500: #b96642;
  --gold-400: #e8c26a;
  --aqua-200: #b8ecf3;
  --rose-200: #f1a18f;

  /* ---- Semantic aliases. Surfaces consume these, never the raw scale. ---- */
  --ink: var(--forest-900);
  --ink-display: var(--forest-950);
  /* 0.70 is the floor that keeps secondary text at 5.6:1 on our darkest ground
     (#eee9df, the dashboard body). At 0.66 it measured 4.97:1 — still AA, but
     with no headroom left for a slightly darker surface. */
  --ink-soft: rgba(8, 36, 24, 0.7);
  /* Decorative/disabled only. Deliberately below AA — never put reading text on it. */
  --ink-mute: rgba(8, 36, 24, 0.44);
  --muted: var(--ink-soft);

  --paper: var(--paper-50);
  --soft: var(--paper-200);
  --sunk: var(--paper-300);

  --green: var(--forest-700);
  --green-2: var(--forest-600);
  --lime: var(--lime-400);

  --line: rgba(8, 36, 24, 0.12);
  --line-soft: rgba(8, 36, 24, 0.07);

  /* Status colors carry meaning and are deliberately outside the brand scale —
   * a warning that reads as brand green is a warning nobody sees. */
  --success: #1f7a4d;
  /* Measured, not chosen: the previous #b6802b scored 2.89:1 on --tint-amber,
     below even AA-large, so every warning chip built from it would have been
     unreadable. #8a5d18 clears AA on all four grounds (4.74–5.64) and is the
     iOS app's `honeyInk`, so a pending state now reads the same on both
     products. The brighter amber survives as --gold-400 / --tint-amber for
     non-text use. */
  --warn: #8a5d18;
  --danger: #9b2c2c;

  /* Pale surface tints for chips, rails, and state washes. These are one step
   * paler than anything in the brand scale on purpose: they sit *behind* ink
   * and must never compete with it. Named by role so a new tint cannot be
   * invented inline. */
  --tint-mint: #e7f5d8;
  --tint-blue: #dff0ff;
  --tint-amber: #ffe9bd;
  --tint-rose: #ffe1db;

  --shadow-sm: 0 1px 2px rgba(8, 36, 24, 0.05);
  --shadow: 0 12px 34px rgba(8, 36, 24, 0.08);
  --shadow-lg: 0 20px 70px rgba(8, 36, 24, 0.12);

  --r: 14px;

  /* ==== Scales ====
   * Added 2026-08-25. Three surfaces had grown 25 font sizes, 18 radii, 20
   * shadows and 27 spacing atoms between them with no system; these are the
   * steps everything snaps to. Values rhyme with the iOS app's tokens
   * (aktib-mobile/src/theme/tokens.js) so the two products feel related:
   * its 6-step type scale and 12/18/24/pill radii are the seed here. */

  /* Spacing. Proven on landing/index.html, which was the only web surface
     with a real scale; promoted here so every surface can use it. */
  --space-0: 4px;
  --space-1: 8px;
  --space-2: 12px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 32px;
  --space-6: 48px;
  --space-7: 72px;
  --space-8: 104px;

  /* Type. Dense operational UI lives in xs–base; lg and up are page chrome.
     2xs is the micro-label step: uppercase stat labels and table headers. It
     exists because 23 declarations sat below xs, six of them at 9px — too
     small to read, and rounding them up to 11px would have reflowed every
     stat tile. Reading text never uses it. */
  --text-2xs: 10px;
  --text-xs: 11px;
  --text-sm: 12px;
  --text-md: 13px;
  --text-base: 14px;
  --text-lg: 16px;
  --text-xl: 18px;
  --text-2xl: 22px;
  --text-3xl: 28px;
  --text-display: 36px;

  /* Weights. The dashboard had nine (700/720/740/760/800/820/850/900/950);
     the differences below 100 apart are invisible at these sizes. */
  --w-regular: 400;
  --w-medium: 500;
  --w-semibold: 600;
  --w-bold: 700;
  --w-heavy: 800;
  /* The dashboard's display type shipped at 850–950 and the scale stopped at
     800, so 43 of its 70 weight declarations had nowhere to land. Black keeps
     that hierarchy instead of flattening it. */
  --w-black: 900;

  /* Radius. `--r` stays as the legacy card radius so existing rules do not
     move; new work picks a step. */
  --r-xs: 6px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 24px;
  --r-pill: 999px;

  /* Fills the gap between --shadow-sm and --shadow, which is where most of
     the dashboard's 16 bespoke shadows were improvising. */
  --shadow-md: 0 8px 24px rgba(8, 36, 24, 0.06);

  /* Stacking. Eleven ad-hoc z-indexes (1..1000) collapse to six roles. */
  --z-raised: 2;
  --z-sticky: 10;
  --z-nav: 30;
  --z-popover: 60;
  --z-modal: 80;
  --z-toast: 100;

  --dur-fast: 120ms;
  --dur-med: 200ms;
  --dur-slow: 320ms;
  --ease-out: cubic-bezier(0.2, 0.7, 0.3, 1);

  /* Focus. The dashboard ringed focus in --lime, which measures ~1.4:1 on a
     paper card — a focus indicator nobody can see fails WCAG 2.4.11 and is
     the single worst keyboard defect on the surface. Forest-600 is the
     darkest step that still reads as brand rather than as an error. */
  --focus-color: var(--forest-600);
  --focus-ring: 0 0 0 3px color-mix(in srgb, var(--forest-600) 30%, transparent);

  /* ==== Surfaces the scale was missing ====
   * The dashboard used 20 distinct near-white tints where the brand scale
   * offers four. These two carry the weight: --card was #fffaf0 (36 uses,
   * the de-facto card interior) and --ground was #eee9df (the body).
   * --ground's exact value is load-bearing: the --ink-soft alpha above is
   * calibrated against it, so changing it silently invalidates that math. */
  --card: #fffaf0;
  --ground: #eee9df;

  /* The fourth status hue. It already shipped as the ink of `.status.review`
     but had no token, so it could not be reused or themed. */
  --info: #185079;

  /* ==== Tone triplets ====
   * State color lived in three incompatible vocabularies: `.status`
   * (review/draft/hold), `.queue-ticket` (review/hold/playing/done) and
   * `.schedule-block` (session/closed/review/hold/empty) — and "review" meant
   * blue in the first and amber in the other two. These five tones are the
   * shared meaning; the class names keep their own anatomy and just draw from
   * here, so a booking cannot be amber in one panel and blue in the next. */
  --tone-positive-ink: var(--success);
  --tone-positive-bg: var(--tint-mint);
  --tone-positive-line: color-mix(in srgb, var(--success) 25%, transparent);

  --tone-info-ink: var(--info);
  --tone-info-bg: var(--tint-blue);
  --tone-info-line: color-mix(in srgb, var(--info) 25%, transparent);

  --tone-warn-ink: var(--warn);
  --tone-warn-bg: var(--tint-amber);
  --tone-warn-line: color-mix(in srgb, var(--warn) 30%, transparent);

  --tone-danger-ink: var(--danger);
  --tone-danger-bg: var(--tint-rose);
  --tone-danger-line: color-mix(in srgb, var(--danger) 25%, transparent);

  --tone-neutral-ink: var(--ink-soft);
  --tone-neutral-bg: var(--soft);
  --tone-neutral-line: var(--line);
}

/* ==== Dark theme ====
 * Attribute-driven, never a bare `prefers-color-scheme` block: each surface
 * resolves the OS preference into an explicit data-theme via a boot script
 * (landing/assets/theme-boot.js, and admin's own inline one). One source of
 * truth means a page that has not been migrated cannot half-darken, and the
 * user's explicit choice always beats the OS.
 *
 * Only semantic aliases are re-pointed here. The raw scale is the brand and
 * does not change with the lights.
 *
 * Values are lifted from the admin console's shipped dark mode, which is the
 * one dark surface in the product that has had real use. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --ink: #e7f4ec;
  --ink-display: #f2faf5;
  --ink-soft: rgba(231, 244, 236, 0.72);
  --ink-mute: rgba(231, 244, 236, 0.46);
  --muted: var(--ink-soft);

  --ground: #101a16;
  --paper: #16231e;
  --card: #182720;
  --soft: #20312a;
  --sunk: #0c1512;

  /* Forest-700/600 are too dark to read as "action" on a dark ground; these
     are the same hue family lifted into the light range. */
  --green: #35a37f;
  --green-2: #4db894;

  --line: rgba(213, 232, 221, 0.12);
  --line-soft: rgba(213, 232, 221, 0.08);

  --success: #7ed7a4;
  --warn: #efbf70;
  --danger: #f28b82;
  --info: #8fc7e8;

  /* Pale tints cannot survive inversion — a #e7f5d8 chip on a dark card is a
     flashlight. Derived from each tone's own ink instead. */
  --tint-mint: color-mix(in srgb, var(--success) 16%, transparent);
  --tint-blue: color-mix(in srgb, var(--info) 16%, transparent);
  --tint-amber: color-mix(in srgb, var(--warn) 16%, transparent);
  --tint-rose: color-mix(in srgb, var(--danger) 16%, transparent);

  --tone-positive-line: color-mix(in srgb, var(--success) 30%, transparent);
  --tone-info-line: color-mix(in srgb, var(--info) 30%, transparent);
  --tone-warn-line: color-mix(in srgb, var(--warn) 30%, transparent);
  --tone-danger-line: color-mix(in srgb, var(--danger) 30%, transparent);

  /* Forest-tinted shadows vanish on a dark ground; depth has to come from
     black. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.22);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.28);
  --shadow: 0 12px 34px rgba(0, 0, 0, 0.34);
  --shadow-lg: 0 20px 70px rgba(0, 0, 0, 0.45);

  /* Lime is invisible on paper and perfect on ink — the inverse of light. */
  --focus-color: var(--lime-400);
  --focus-ring: 0 0 0 3px color-mix(in srgb, var(--lime-400) 34%, transparent);
}

