/* GENERATED FILE — do not edit.
   Source: packages/ui-kit/src/tokens.css
   Regenerate: npm run sync:tokens --workspace @tssg/app-identity */

/* ═══════════════════════════════════════════════════════════════════════════
   TSSG OPERATIONS DESIGN TOKENS
   Direction: Dispatch, with Bajan Light as the same tokens relaxed.
   Agreed with Kemar 2026-08-09 (docs/design/directions-v1.html).

   Two axes, deliberately independent:
     THEME    light | dark   — colour only
     DENSITY  compact | comfortable — spacing and type only

   That independence is the whole point. Staff get compact, clients and field
   officers get comfortable, and both get either theme. One system, no forks.

   ── Theme resolution, and the bug this avoids ────────────────────────────
   A viewer is in one of THREE states, not two:
     1. explicit light  → [data-theme="light"]
     2. explicit dark   → [data-theme="dark"]
     3. system (default)→ NOTHING is stamped; only prefers-color-scheme applies

   Praxis handles states 1 and 2 but not 3, so an un-stamped visitor on a dark
   OS gets the light palette. Every block below therefore appears twice: once
   under the media query (guarded so an explicit light choice still wins) and
   once under the attribute (so the toggle wins in both directions).

   NEVER define a colour only inside a media query or a [data-theme] block.
   Style through the tokens; that is what makes all three states resolve.

   ── Typefaces ────────────────────────────────────────────────────────────
   System stacks, not a webfont. Praxis @imports Sora and Inter from Google.
   Here that would be a render-blocking third-party request on the critical
   path, and the field officer surface is used outdoors on Barbadian mobile
   data. The personality comes from scale, weight, case and spacing instead.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Type stacks ──────────────────────────────────────────────────── */
  --ui-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --ui-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* ── Type scale (comfortable is the base; compact overrides below) ── */
  --ui-text-xs:   11.5px;
  --ui-text-sm:   13px;
  --ui-text-base: 15px;
  --ui-text-lg:   17px;
  --ui-text-xl:   21px;
  --ui-text-2xl:  27px;
  --ui-text-3xl:  34px;
  --ui-leading-tight: 1.2;
  --ui-leading-body:  1.55;

  /* Uppercase micro-labels. Letter-spacing is not decoration here — at this
     size, unspaced uppercase is measurably harder to read. */
  --ui-label-size: 10px;
  --ui-label-track: 0.13em;

  /* ── Space scale ──────────────────────────────────────────────────── */
  --ui-space-1: 4px;
  --ui-space-2: 8px;
  --ui-space-3: 12px;
  --ui-space-4: 16px;
  --ui-space-5: 22px;
  --ui-space-6: 30px;
  --ui-space-7: 44px;
  --ui-space-8: 64px;

  /* ── Density-driven (comfortable default) ─────────────────────────── */
  --ui-row-h:      52px;
  --ui-row-pad-y:  14px;
  --ui-row-pad-x:  20px;
  --ui-control-h:  42px;   /* >= 44px effective with border — WCAG 2.2 target size */
  --ui-gap:        var(--ui-space-4);
  --ui-pad-card:   var(--ui-space-5);

  /* ── Shape ────────────────────────────────────────────────────────── */
  --ui-radius-sm: 4px;
  --ui-radius-md: 8px;
  --ui-radius-lg: 12px;
  --ui-radius-pill: 999px;
  --ui-border-w: 1px;

  /* ── Motion ───────────────────────────────────────────────────────── */
  --ui-ease: cubic-bezier(.2, .6, .3, 1);
  --ui-dur-fast: 110ms;
  --ui-dur: 190ms;

  /* ── Layout ───────────────────────────────────────────────────────── */
  --ui-nav-h: 56px;
  --ui-measure: 68ch;
  --ui-container: 1240px;

  /* ═══ COLOUR — LIGHT (the base; Bajan Light relaxed) ═══════════════ */
  --ui-bg:            #F4F7F8;
  --ui-surface:       #FFFFFF;
  --ui-surface-raise: #EAF0F1;
  --ui-surface-sunk:  #E3EBEC;
  --ui-line:          #D3DEE0;
  --ui-line-strong:   #78898D;

  --ui-text:       #0E2328;
  --ui-text-muted: #4E6268;
  --ui-text-faint: #5A6E74;
  --ui-text-on-accent: #FFFFFF;

  /* Brand accent — marine. One hue family, two lightnesses across themes,
     so the accent is recognisably the same colour in both. */
  --ui-accent:       #0E5A66;
  --ui-accent-hover: #0A464F;
  --ui-accent-soft:  rgba(14, 90, 102, 0.09);
  --ui-accent-line:  rgba(14, 90, 102, 0.34);

  /* Semantic. Separate from the accent by design — a status colour that is
     also the brand colour cannot signal anything. */
  --ui-ok:        #15683E;
  --ui-ok-soft:   rgba(21, 104, 62, 0.10);
  --ui-attn:      #85560F;   /* pending, action needed. Amber's real job. */
  --ui-attn-soft: rgba(133, 86, 15, 0.11);
  --ui-crit:      #A5382F;
  --ui-crit-soft: rgba(165, 56, 47, 0.10);
  --ui-info:      var(--ui-accent);
  --ui-info-soft: var(--ui-accent-soft);

  /* Duty state — operations-specific, and not the same thing as OK/critical.
     An officer off duty is not an error. */
  --ui-duty-on:     #0E6E7D;
  --ui-duty-off:    #5A6E74;
  --ui-duty-standby:#85560F;

  --ui-focus: #0E5A66;
  --ui-shadow-1: 0 1px 2px rgba(9, 26, 30, .07), 0 4px 14px rgba(9, 26, 30, .06);
  --ui-shadow-2: 0 4px 12px rgba(9, 26, 30, .09), 0 18px 44px rgba(9, 26, 30, .10);
  --ui-scrim: rgba(9, 26, 30, .48);

  color-scheme: light;
}

/* ═══ COLOUR — DARK ════════════════════════════════════════════════════
   Not an inversion. Dispatch's control-room ground carries a blue bias, the
   accent lifts to stay legible on it, and the semantic colours are re-picked
   rather than lightened — a lightened #A5382F reads pink on this ground.
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ui-bg:            #0A1015;
    --ui-surface:       #111A20;
    --ui-surface-raise: #17222A;
    --ui-surface-sunk:  #070C10;
    --ui-line:          #22303A;
    --ui-line-strong:   #5A7280;

    --ui-text:       #DDE7EC;
    --ui-text-muted: #93A7B2;
    --ui-text-faint: #7C909C;
    --ui-text-on-accent: #04171B;

    --ui-accent:       #4FBCCD;
    --ui-accent-hover: #71CEDC;
    --ui-accent-soft:  rgba(79, 188, 205, 0.14);
    --ui-accent-line:  rgba(79, 188, 205, 0.40);

    --ui-ok:        #55AE79;
    --ui-ok-soft:   rgba(85, 174, 121, 0.15);
    --ui-attn:      #E4A445;
    --ui-attn-soft: rgba(228, 164, 69, 0.15);
    --ui-crit:      #E4756F;
    --ui-crit-soft: rgba(228, 117, 111, 0.15);
    --ui-info:      var(--ui-accent);
    --ui-info-soft: var(--ui-accent-soft);

    --ui-duty-on:     #4FBCCD;
    --ui-duty-off:    #7C909C;
    --ui-duty-standby:#E4A445;

    --ui-focus: #71CEDC;
    --ui-shadow-1: 0 1px 2px rgba(0, 0, 0, .45), 0 4px 14px rgba(0, 0, 0, .35);
    --ui-shadow-2: 0 4px 12px rgba(0, 0, 0, .5), 0 18px 44px rgba(0, 0, 0, .45);
    --ui-scrim: rgba(2, 8, 11, .62);

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --ui-bg:            #0A1015;
  --ui-surface:       #111A20;
  --ui-surface-raise: #17222A;
  --ui-surface-sunk:  #070C10;
  --ui-line:          #22303A;
  --ui-line-strong:   #5A7280;

  --ui-text:       #DDE7EC;
  --ui-text-muted: #93A7B2;
  --ui-text-faint: #7C909C;
  --ui-text-on-accent: #04171B;

  --ui-accent:       #4FBCCD;
  --ui-accent-hover: #71CEDC;
  --ui-accent-soft:  rgba(79, 188, 205, 0.14);
  --ui-accent-line:  rgba(79, 188, 205, 0.40);

  --ui-ok:        #55AE79;
  --ui-ok-soft:   rgba(85, 174, 121, 0.15);
  --ui-attn:      #E4A445;
  --ui-attn-soft: rgba(228, 164, 69, 0.15);
  --ui-crit:      #E4756F;
  --ui-crit-soft: rgba(228, 117, 111, 0.15);
  --ui-info:      var(--ui-accent);
  --ui-info-soft: var(--ui-accent-soft);

  --ui-duty-on:     #4FBCCD;
  --ui-duty-off:    #7C909C;
  --ui-duty-standby:#E4A445;

  --ui-focus: #71CEDC;
  --ui-shadow-1: 0 1px 2px rgba(0, 0, 0, .45), 0 4px 14px rgba(0, 0, 0, .35);
  --ui-shadow-2: 0 4px 12px rgba(0, 0, 0, .5), 0 18px 44px rgba(0, 0, 0, .45);
  --ui-scrim: rgba(2, 8, 11, .62);

  color-scheme: dark;
}

/* ═══ DENSITY — COMPACT ════════════════════════════════════════════════
   Staff and the control plane. Roughly twice the records per screen.
   Colour is untouched: density and theme never interact.

   Note what does NOT shrink: --ui-control-h stays at a 44px effective
   target. A denser table is fine; a smaller tap target is a WCAG 2.2
   failure and a mis-tap on a dispatch board is an operational one.
   ═══════════════════════════════════════════════════════════════════════ */
:root[data-density="compact"] {
  --ui-text-xs:   10.5px;
  --ui-text-sm:   12px;
  --ui-text-base: 13.5px;
  --ui-text-lg:   15px;
  --ui-text-xl:   18px;
  --ui-text-2xl:  23px;
  --ui-text-3xl:  29px;
  --ui-leading-body: 1.45;

  --ui-row-h:     34px;
  --ui-row-pad-y: 7px;
  --ui-row-pad-x: 14px;
  --ui-gap:       var(--ui-space-3);
  --ui-pad-card:  var(--ui-space-4);
  --ui-nav-h:     46px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* Explicit, from a token. A transparent body borrows whatever ground the
     host paints, which is how a page ends up light-on-light. */
  background: var(--ui-bg);
  color: var(--ui-text);
  font-family: var(--ui-font-sans);
  font-size: var(--ui-text-base);
  line-height: var(--ui-leading-body);
  -webkit-font-smoothing: antialiased;
  /* Non-negotiable: the page body never scrolls sideways. Wide content gets
     its own overflow container — see .ui-scroll. */
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  margin: 0;
  line-height: var(--ui-leading-tight);
  letter-spacing: -0.018em;
  text-wrap: balance;
  font-weight: 600;
}
h1 { font-size: var(--ui-text-3xl); }
h2 { font-size: var(--ui-text-2xl); }
h3 { font-size: var(--ui-text-xl); }
h4 { font-size: var(--ui-text-lg); }

p { margin: 0; max-width: var(--ui-measure); }

/* Any column of digits that a human compares. Non-tabular figures make a
   money column impossible to scan. */
.ui-num, td.ui-num, .ui-mono {
  font-variant-numeric: tabular-nums;
  font-family: var(--ui-font-mono);
}

.ui-label {
  font-family: var(--ui-font-mono);
  font-size: var(--ui-label-size);
  letter-spacing: var(--ui-label-track);
  text-transform: uppercase;
  color: var(--ui-text-faint);
}

/* Wide content scrolls inside itself, never the page. */
.ui-scroll { overflow-x: auto; max-width: 100%; }

/* ═══ FOCUS ════════════════════════════════════════════════════════════
   Visible on every focusable thing, in both themes. Never remove without a
   replacement — keyboard navigation is a stated requirement of the staff
   surface, not a nicety.
   ═══════════════════════════════════════════════════════════════════════ */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--ui-focus);
  outline-offset: 2px;
  border-radius: var(--ui-radius-sm);
}

/* ═══ MOTION ═══════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ═══ STATE SURFACES ═══════════════════════════════════════════════════
   Loading, empty and error are designed, not left to appear as blank
   panels (plan §10.4). These are the shared shells; each surface supplies
   its own copy.
   ═══════════════════════════════════════════════════════════════════════ */
.ui-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ui-space-3);
  padding: var(--ui-space-7) var(--ui-space-5);
  text-align: center;
  color: var(--ui-text-muted);
}
.ui-state h3 { color: var(--ui-text); }
.ui-state p { font-size: var(--ui-text-sm); max-width: 42ch; }
.ui-state--error { color: var(--ui-crit); }
.ui-state--error h3 { color: var(--ui-crit); }

/* Skeleton rows. Shape matches the content it stands in for, so the layout
   does not jump when real data lands. */
.ui-skeleton {
  background: linear-gradient(90deg, var(--ui-surface-raise) 0%, var(--ui-surface-sunk) 50%, var(--ui-surface-raise) 100%);
  background-size: 200% 100%;
  animation: ui-shimmer 1.4s var(--ui-ease) infinite;
  border-radius: var(--ui-radius-sm);
  height: 1em;
}
@keyframes ui-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}
