/* tokens.css — the design token layer. Loaded BEFORE styles.css on every view.
 *
 * Nothing in here styles anything. It only names values, so that:
 *   1. a dark theme is a different set of values, not a different stylesheet;
 *   2. Phase 5's per-tenant branding overrides a handful of tokens rather than
 *      hunting hex literals through 750 lines of rules.
 *
 * Three things in here are load-bearing and easy to break:
 *
 * - `color-scheme` is the fix for a real bug, not a nicety. Before this file
 *   existed the app shipped light-only, and Chrome's Auto Dark Theme
 *   *algorithmically inverted* it on a phone set to dark: the token said
 *   #f5f5f5 and `body` measured rgb(24,26,27). That heuristic does not know the
 *   GPS pin colours and status badges carry meaning. Declaring `color-scheme`
 *   tells the browser we handle dark ourselves and it stops interfering.
 *
 * - The dark values are declared once, as `--d-*`, and then *mapped* twice
 *   (once for `prefers-color-scheme`, once for `[data-theme="dark"]`). The
 *   mapping is duplicated because CSS has no way to share it; the colours are
 *   not. Edit `--d-*`, never the mapping.
 *
 * - Dark is not an inversion. Cool near-black ground, text at 90% white rather
 *   than pure white, and every semantic colour re-picked at a lighter value so
 *   it still clears WCAG AA against that ground. Shadows go darker and more
 *   transparent, not the same values.
 */

:root {
  color-scheme: light;

  /* ── Base palette ────────────────────────────────────────────────────────
     Six names. Semantic, not literal — `--surface-raised`, never `--white` —
     because a tenant override of "white" is meaningless. */
  --ink:        #16181D;  /* cool near-black: light-theme text, dark-theme ground */
  --paper:      #FAFAF8;  /* warm off-white */
  --graphite:   #5A6068;  /* muted text (6.1:1 on paper) */
  --hairline:   #DDDCD6;  /* the 1px rule that does the work shadows used to */

  /* The one functional accent. This is the existing brand orange, measured,
     not re-chosen — so it survives a re-brand as a token swap.

     It takes DARK text, not white. White on #e8821a is 2.75:1, which the old
     `.btn-primary` shipped and which fails AA; #16181D on it is 6.5:1. That is
     also the useful side effect of keeping accent visually separate from the
     status badges, which are all light-tint-on-dark-text. */
  --accent:     #e8821a;
  --on-accent:  #16181D;

  /* The accent AS TEXT or as a hairline, which is a different problem: #e8821a
     on a light surface measures 2.63:1, below both the 4.5:1 text bar and the
     3:1 non-text bar. This is the darkened form that clears AA (4.89:1), and in
     dark theme it collapses back to --accent, which already clears it there at
     6.46:1. Use --accent for fills, --accent-text for anything thin. */
  --accent-text: #AD5600;

  /* ── Signal colours ──────────────────────────────────────────────────────
     Held deliberately distinct from --accent. The old palette had
     --color-primary #e8821a and --color-warning #f39c12 — both orange, near
     indistinguishable, and orange is *also* a GPS pin state. Brand and state
     were the same signal. Warning is now unambiguously yellow-amber.

     State is never encoded in hue alone anywhere in this app; see the badge
     and pin rules in styles.css. These values are the colour half only. */
  --signal-success: #15803D;
  --signal-warning: #A16207;
  --signal-danger:  #B91C1C;
  --signal-info:    #1D4ED8;

  /* Text on a signal-coloured FILL (a danger button, a toast). This has to flip
     with the theme: light theme's signals are 700-weights that take white, dark
     theme's are 400-weights that take near-black. White on dark-theme's
     #4ADE80 is 1.7:1. */
  --on-signal: #FAFAF8;

  /* Tints for badge/alert fills. Light theme only — dark theme uses a
     translucent wash of the signal colour instead, since a pale tint on a dark
     ground reads as a glowing block. */
  /* Measured, not eyeballed: the first pass used #E7F3EB / #FBF2DC and the badge
     label came out at 4.40:1 and 4.42:1 — under AA, and badge text is 12px bold,
     which is not "large text". These clear it at 4.58 and 4.57. */
  --tint-success: #EDF7F1;
  --tint-warning: #FDF6E6;
  --tint-danger:  #FBEAEA;
  --tint-info:    #E8EDFB;

  /* ── Surfaces ────────────────────────────────────────────────────────────
     Three depths, plus "chrome" for the sidebar/topbar/table-head band. Chrome
     used to be a navy (#2c5f8a) — a second brand hue doing structural work.
     It is now neutral, which is both more restrained and one less colour for a
     tenant theme to fight. */
  --surface-sunken: #F1F0EB;  /* page ground */
  --surface:        #FAFAF8;  /* cards, modals */
  --surface-raised: #FFFFFF;  /* inputs, popovers, things on top of cards */
  --surface-chrome: #1F2227;  /* sidebar, topbar, thead */
  --on-chrome:      rgba(255,255,255,0.92);
  --on-chrome-dim:  rgba(255,255,255,0.64);

  /* A filled neutral block that is not chrome: the secondary button. Distinct
     from --surface-chrome because in dark theme chrome goes *darker* than the
     page (a topbar recedes) while a button has to come *forward*. */
  --fill-neutral:    #1F2227;
  --on-fill-neutral: rgba(255,255,255,0.92);

  --text:         #16181D;
  --text-muted:   #5A6068;
  --text-inverse: #FAFAF8;

  --border:        #DDDCD6;
  /* --border is a decorative hairline; --border-strong is the edge of a CONTROL
     (a field, a ghost button, a chip) and WCAG 1.4.11 holds those to 3:1 against
     the surface behind them. #B9B8B0 measured 1.91:1 — a form field with no
     visible boundary. This clears it at 3.28:1 without becoming a heavy rule. */
  --border-strong: #8C8B82;
  --focus-ring:    #1D4ED8;
  --focus-glow:    rgba(29,78,216,0.24);

  /* Scrim behind modals and the mobile drawer. Theme-aware: the same 55% black
     over a near-black page is barely a scrim at all. */
  --scrim: rgba(14,16,19,0.55);

  /* Chrome drawn ON TOP of photography and map tiles — delete buttons, play
     badges, the tap-to-activate veil. Theme-independent by definition: a photo
     is a photo whatever the page around it is doing. */
  --overlay-fill: rgba(14,16,19,0.66);
  --on-overlay:   #FAFAF8;

  /* Map pins. Deliberately NOT remapped in the dark blocks below: a pin is drawn
     on OpenStreetMap tiles, which are light whatever the page is doing, so the
     dark-theme signal colours (picked to sit on a near-black ground) are the
     wrong ones there. The shape differences in makeIcon() carry the meaning;
     these only have to stay legible against a street map. */
  --pin-nav:  #C25E00;
  --pin-drop: #B91C1C;
  --pin-both: #15803D;

  /* Route lines and their pins (routing lab, later Phase 7). Same rule as the
     pins: drawn on light tiles, so not remapped for dark. Dark enough to carry
     white pin numbers and to read as a 4px line on a street map. Hue is never
     the only signal — every route pin is also labelled with its route letter
     and sequence number — so beyond eight routes the palette simply repeats. */
  --route-1: #1D4ED8;
  --route-2: #B91C1C;
  --route-3: #15803D;
  --route-4: #7E22CE;
  --route-5: #C25E00;
  --route-6: #0F766E;
  --route-7: #A21CAF;
  --route-8: #4B5563;

  /* Borders carry the hierarchy; shadows only lift things that genuinely
     float (modals, the driver's detail panel, toasts). */
  --shadow-sm: 0 1px 2px rgba(22,24,29,0.06);
  --shadow:    0 4px 12px rgba(22,24,29,0.10);
  --shadow-lg: 0 12px 32px rgba(22,24,29,0.18);

  /* ── Type ────────────────────────────────────────────────────────────────
     Archivo for the interface. IBM Plex Mono for door PINs, key-safe codes,
     registrations, odometer readings, timestamps and money — functional, not
     decorative: it makes 0/O and 1/l unambiguous, which is a real failure mode
     reading a key-safe code off a phone in the dark. */
  --font-ui:   'Archivo', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;
  --font-main: var(--font-ui);  /* legacy alias, see bottom of file */

  /* One strict scale, in px. Replaces the old scattered
     0.75/0.78/0.8/0.85/0.875/0.9/0.95/1rem. Nothing interactive is allowed
     below --text-base: under 16px, iOS zooms the viewport on field focus. */
  --text-xs:   0.75rem;   /* 12px — captions, table meta. Never interactive. */
  --text-sm:   0.875rem;  /* 14px — labels, hints */
  --text-base: 1rem;      /* 16px — body, every input, every button */
  --text-lg:   1.25rem;   /* 20px — card and modal titles */
  --text-xl:   1.5rem;    /* 24px — page titles */
  --text-2xl:  2rem;      /* 32px — stat values */

  --leading-tight: 1.25;
  --leading-body:  1.55;
  --tracking-tight: -0.01em;  /* Archivo sets a touch wide at display sizes */

  /* ── Space ───────────────────────────────────────────────────────────────
     8px grid, with a 4px half-step. Every padding/margin/gap in styles.css
     resolves to one of these. */
  --space-1: 0.25rem;  /*  4px */
  --space-2: 0.5rem;   /*  8px */
  --space-3: 0.75rem;  /* 12px */
  --space-4: 1rem;     /* 16px */
  --space-5: 1.5rem;   /* 24px */
  --space-6: 2rem;     /* 32px */
  --space-7: 3rem;     /* 48px */

  /* ── Geometry ────────────────────────────────────────────────────────────
     Rounding used sparingly and consistently: 4px on controls, 8px on the
     surfaces that contain them, full round only on things that are genuinely
     pills (badges) or circles (icons). */
  --radius-sm:   4px;
  --radius:      6px;
  --radius-lg:   10px;
  --radius-pill: 999px;

  /* 44px is the floor, not a suggestion. The driver is gloved and moving. */
  --touch-min:     44px;
  --touch-comfort: 52px;

  --transition:      140ms ease;
  --transition-slow: 260ms ease;
  --sidebar-width:   240px;
}

/* ── Dark values ───────────────────────────────────────────────────────────
   Declared once here; mapped below. */
:root {
  --d-surface-sunken: #0E1013;
  --d-surface:        #16181D;
  --d-surface-raised: #1F2228;
  --d-surface-chrome: #0E1013;

  --d-fill-neutral:    #2B3038;
  --d-on-fill-neutral: rgba(255,255,255,0.90);

  --d-text:         rgba(255,255,255,0.90);
  --d-text-muted:   rgba(255,255,255,0.60);
  --d-text-inverse: #16181D;

  --d-border:        rgba(255,255,255,0.13);
  --d-border-strong: rgba(255,255,255,0.36);  /* 3.34:1, same reason as above */
  --d-focus-ring:    #93B4FD;
  --d-focus-glow:    rgba(147,180,253,0.30);
  --d-accent-text:   #e8821a;
  --d-scrim:         rgba(0,0,0,0.70);
  --d-on-signal:     #16181D;

  /* Re-picked, not lightened mechanically — each of these clears 4.5:1 against
     --d-surface (#16181D). The 700-weights used in light theme sit at ~1.5:1
     there and would be unreadable. */
  --d-signal-success: #4ADE80;
  --d-signal-warning: #FBBF24;
  --d-signal-danger:  #F87171;
  --d-signal-info:    #60A5FA;

  /* A wash of the signal colour rather than a pale tint. */
  --d-tint-success: rgba(74,222,128,0.14);
  --d-tint-warning: rgba(251,191,36,0.14);
  --d-tint-danger:  rgba(248,113,113,0.14);
  --d-tint-info:    rgba(96,165,250,0.14);

  --d-shadow-sm: 0 1px 2px rgba(0,0,0,0.40);
  --d-shadow:    0 4px 12px rgba(0,0,0,0.50);
  --d-shadow-lg: 0 12px 32px rgba(0,0,0,0.64);
}

/* The mapping. Duplicated for the two triggers — system preference, and an
   explicit [data-theme]. `:root:not([data-theme="light"])` so a page or a user
   can force light back on even on a dark device. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --surface-sunken: var(--d-surface-sunken);
    --surface:        var(--d-surface);
    --surface-raised: var(--d-surface-raised);
    --surface-chrome: var(--d-surface-chrome);
    --fill-neutral:    var(--d-fill-neutral);
    --on-fill-neutral: var(--d-on-fill-neutral);
    --text:           var(--d-text);
    --text-muted:     var(--d-text-muted);
    --text-inverse:   var(--d-text-inverse);
    --border:         var(--d-border);
    --border-strong:  var(--d-border-strong);
    --focus-ring:     var(--d-focus-ring);
    --focus-glow:     var(--d-focus-glow);
    --accent-text:    var(--d-accent-text);
    --scrim:          var(--d-scrim);
    --on-signal:      var(--d-on-signal);
    --signal-success: var(--d-signal-success);
    --signal-warning: var(--d-signal-warning);
    --signal-danger:  var(--d-signal-danger);
    --signal-info:    var(--d-signal-info);
    --tint-success:   var(--d-tint-success);
    --tint-warning:   var(--d-tint-warning);
    --tint-danger:    var(--d-tint-danger);
    --tint-info:      var(--d-tint-info);
    --shadow-sm:      var(--d-shadow-sm);
    --shadow:         var(--d-shadow);
    --shadow-lg:      var(--d-shadow-lg);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-sunken: var(--d-surface-sunken);
  --surface:        var(--d-surface);
  --surface-raised: var(--d-surface-raised);
  --surface-chrome: var(--d-surface-chrome);
  --fill-neutral:    var(--d-fill-neutral);
  --on-fill-neutral: var(--d-on-fill-neutral);
  --text:           var(--d-text);
  --text-muted:     var(--d-text-muted);
  --text-inverse:   var(--d-text-inverse);
  --border:         var(--d-border);
  --border-strong:  var(--d-border-strong);
  --focus-ring:     var(--d-focus-ring);
  --focus-glow:     var(--d-focus-glow);
  --accent-text:    var(--d-accent-text);
  --scrim:          var(--d-scrim);
  --on-signal:      var(--d-on-signal);
  --signal-success: var(--d-signal-success);
  --signal-warning: var(--d-signal-warning);
  --signal-danger:  var(--d-signal-danger);
  --signal-info:    var(--d-signal-info);
  --tint-success:   var(--d-tint-success);
  --tint-warning:   var(--d-tint-warning);
  --tint-danger:    var(--d-tint-danger);
  --tint-info:      var(--d-tint-info);
  --shadow-sm:      var(--d-shadow-sm);
  --shadow:         var(--d-shadow);
  --shadow-lg:      var(--d-shadow-lg);
}

/* ── Legacy aliases ────────────────────────────────────────────────────────
   The pre-Phase-3 token names, kept so the four dashboards whose composition
   is deferred to after Phase 4/5 keep rendering while they still reference
   them. Every one is now theme-aware for free, which is most of why the dark
   theme reaches those screens at all.

   `--color-primary` and `--color-warning` were the two near-identical oranges;
   the alias deliberately separates them. Delete this block when the last
   dashboard is composed. */
:root {
  --color-primary:   var(--accent);
  --color-secondary: var(--surface-chrome);
  --color-success:   var(--signal-success);
  --color-danger:    var(--signal-danger);
  --color-warning:   var(--signal-warning);
  --color-info:      var(--signal-info);
  --color-bg:        var(--surface-sunken);
  --color-surface:   var(--surface);
  --color-text:      var(--text);
  --color-muted:     var(--text-muted);
  --color-border:    var(--border);
  --radius-legacy:   var(--radius);
}
