/* ==========================================================================
   FONTS — self-hosted. No Google Fonts CDN call: the VPS serves these, so the
   pages carry no third-party request and render identically offline.
   Latin + latin-ext only; 77 kB for the whole type system.
   ========================================================================== */

@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;              /* variable axis — Regular to Black */
  font-display: swap;
  src: url("../brand/fonts/golos-text-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("../brand/fonts/golos-text-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../brand/fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal; font-weight: 500; font-display: swap;
  src: url("../brand/fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
}

/* ============================================================================
   rocket-ship design tokens — SINGLE SOURCE OF TRUTH
   Derived from: Branding/Brand Guideline/rocketship Branding.pdf
   Every other artefact (tokens.json, Tailwind @theme, Figma variables) is
   generated from this file. Edit here, then run design/scripts/build-tokens.py
   ----------------------------------------------------------------------------
   TIER 1  primitives  --rs-*     raw values, never used directly in components
   TIER 2  semantic    --color-*  theme-aware, this is what components consume
   TIER 3  component   --btn-*    per-component contracts
   ========================================================================== */

/* ==========================================================================
   TIER 1 — PRIMITIVES
   ========================================================================== */

:root {
  /* --- Brand blue ---------------------------------------------------------
     Anchor #0053E6 lifted from the wordmark SVG (fill: #0053e6).
     OKLCH 50.6% 0.2322 261.9. Ramp generated at fixed hue 261.9 with chroma
     tapering toward both ends so light tints do not turn garish.
     ---------------------------------------------------------------------- */
  --rs-blue-50:  #F0F5FF;
  --rs-blue-100: #E1ECFF;
  --rs-blue-200: #C3D8FF;
  --rs-blue-300: #95BBFF;
  --rs-blue-400: #4986FB;
  --rs-blue-500: #0053E6; /* LOCKED — brand primary, do not shift */
  --rs-blue-600: #0045C2;
  --rs-blue-700: #00359A;
  --rs-blue-800: #00236F;
  --rs-blue-900: #001346;
  --rs-blue-950: #000624;

  /* --- Neutrals -----------------------------------------------------------
     Tinted toward the brand hue (261.9) at chroma 0.003–0.0095. The tint is
     barely nameable but it is what stops the greys reading as a different
     brand from the blue. Never use a pure grey here.
     ---------------------------------------------------------------------- */
  --rs-neutral-0:    #FFFFFF;
  --rs-neutral-50:   #F9FAFC;
  --rs-neutral-100:  #F1F3F6;
  --rs-neutral-200:  #E4E6EA;
  --rs-neutral-300:  #CED1D6;
  --rs-neutral-400:  #9EA2A7;
  --rs-neutral-500:  #777A80;
  --rs-neutral-600:  #585B60;
  --rs-neutral-700:  #3C3E43;
  --rs-neutral-750:  #2D2F33;
  --rs-neutral-800:  #222428;
  --rs-neutral-850:  #1B1D21;
  --rs-neutral-900:  #16181C;
  --rs-neutral-925:  #0D0F13;
  --rs-neutral-950:  #06070A;
  --rs-neutral-1000: #010102;

  /* --- Status ramps -------------------------------------------------------
     Hues chosen so the four status colours stay distinguishable under
     deuteranopia: blue 262, green 152, amber 80, red 27. Green and red are
     never the only signal — shape/label always carries the meaning too.
     ---------------------------------------------------------------------- */
  --rs-green-50:  #EDF9F0;
  --rs-green-100: #DDF1E1;
  --rs-green-200: #BEE2C6;
  --rs-green-300: #8FCB9F;
  --rs-green-400: #3EA361;
  --rs-green-500: #00793C;
  --rs-green-600: #006531;
  --rs-green-700: #004F25;

  --rs-amber-50:  #FCF4E9;
  --rs-amber-100: #F7E9D6;
  --rs-amber-200: #ECD3B2;
  --rs-amber-300: #DBB37C;
  --rs-amber-400: #E5A400;
  --rs-amber-500: #885A00;
  --rs-amber-600: #724B00;
  --rs-amber-700: #593A00;

  --rs-red-50:  #FFF2F0;
  --rs-red-100: #FFE4E0;
  --rs-red-200: #FFC8C1;
  --rs-red-300: #F6A096;
  --rs-red-400: #DC5E55;
  --rs-red-500: #BD0F18;
  --rs-red-600: #A1000E;
  --rs-red-700: #7F0009;

  /* --- Hi-viz ------------------------------------------------------------
     Taken from the PPE in the brand book (vest / helmet pages). This is the
     ONE colour in the system with a usage law attached:
     RESERVED FOR LIVE STATE ONLY — a vehicle moving right now, a shift
     clocked in right now, a stream connected right now. Never decorative.
     If it appears twice on a screen, one of them is wrong.
     ---------------------------------------------------------------------- */
  --rs-hiviz: #C0F516;

  /* --- Geometry ----------------------------------------------------------
     There is no decorative accent shape in this system, by decision.

     Three were tried and all three are recorded so they are not retried: a bar
     skewed to the logo's 23.04deg edge (read as a strike THROUGH tall table
     rows), an L-shaped registration bracket (closed to a filled block below
     10px), and a 6px square (legible, but redundant next to the selected-row
     tint that already carries the same state).

     Active state is carried by surface, colour and weight. Direction is
     carried by the 2px tab underline. Identity is carried by the technical
     elevations, the waybill blocks and the hi-viz law. Nothing needs a badge
     stuck to its left edge.
     ---------------------------------------------------------------------- */
  --rs-mark-ratio: 2.584; /* 352.55 / 136.45 */

  /* --- Spacing — 4pt scale, semantic names ------------------------------ */
  --space-3xs: 0.25rem;  /*  4px */
  --space-2xs: 0.5rem;   /*  8px */
  --space-xs:  0.75rem;  /* 12px */
  --space-sm:  1rem;     /* 16px */
  --space-md:  1.5rem;   /* 24px */
  --space-lg:  2rem;     /* 32px */
  --space-xl:  3rem;     /* 48px */
  --space-2xl: 4rem;     /* 64px */
  --space-3xl: 6rem;     /* 96px */
  --space-4xl: 8rem;     /* 128px */

  /* Marketing sections breathe with the viewport; product UI never does. */
  --space-section: clamp(4rem, 2.5rem + 7vw, 10rem);
  --space-gutter:  clamp(1.25rem, 0.75rem + 2.5vw, 4rem);

  /* --- Typography --------------------------------------------------------
     Display is Golos Text — a neo-grotesque chosen by the client over the
     Space Grotesk used in the printed brand book. See DESIGN.md §5: the book
     should be updated to match, or the printed and digital lockups drift.
     Golos ships a 400-900 variable axis, so the display scale starts at
     Regular; there is no Light.
     Technical/data copy stays IBM Plex Mono, the brand book's own label face.
     Body/UI copy runs on the system stack: it renders SF Pro on the Apple
     devices most field staff carry, costs 0 kb, and is the actual source of
     the "Apple-clean" reading feel the brief asks for.
     ---------------------------------------------------------------------- */
  --font-display: "Golos Text", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-jp: "Noto Sans JP", var(--font-ui); /* only for 運送会社 brand lockups */

  /* Marketing display scale — fluid, 1.28 ratio at both ends */
  --text-display-xl: clamp(3rem, 1rem + 8vw, 7.5rem);
  --text-display-lg: clamp(2.25rem, 1.15rem + 4.4vw, 4.5rem);
  --text-display-md: clamp(1.75rem, 1.15rem + 2.4vw, 3rem);
  --text-display-sm: clamp(1.375rem, 1.05rem + 1.3vw, 2rem);

  /* Product UI scale — fixed rem. Dashboards must not resize with viewport. */
  --text-2xs:  0.6875rem; /* 11px — mono micro-labels only */
  --text-xs:   0.75rem;   /* 12px */
  --text-sm:   0.8125rem; /* 13px */
  --text-base: 0.9375rem; /* 15px — default body */
  --text-md:   1rem;      /* 16px — mobile form inputs, prevents iOS zoom */
  --text-lg:   1.125rem;  /* 18px */
  --text-xl:   1.375rem;  /* 22px */
  --text-2xl:  1.75rem;   /* 28px */
  --text-3xl:  2.25rem;   /* 36px */

  --leading-tight:   1.08; /* display */
  --leading-snug:    1.25; /* headings */
  --leading-normal:  1.5;  /* body */
  --leading-relaxed: 1.6;  /* long-form and ALL light-on-dark body */

  --tracking-display: -0.03em;
  --tracking-tight:   -0.01em;
  --tracking-normal:  0em;
  --tracking-label:   0.08em; /* mono uppercase micro-labels */
  --tracking-wide:    0.16em; /* SHIPPING COMPANY lockup */

  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --measure-prose: 68ch;
  --measure-narrow: 46ch;

  /* --- Radius ------------------------------------------------------------
     The mark is a hard-edged parallelogram with zero radius. The system stays
     tight: data surfaces are square, only touch targets soften.
     ---------------------------------------------------------------------- */
  --radius-none: 0;
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
  --radius-full: 999px;

  /* --- Elevation ---------------------------------------------------------
     Structure is carried by surface steps + hairlines, not shadows. Shadows
     exist for true overlays only — things that float above the page and must
     be dismissible. If a card has a shadow it is a bug.
     ---------------------------------------------------------------------- */
  --shadow-popover: 0 4px 12px -2px rgb(6 7 10 / 0.10), 0 1px 3px rgb(6 7 10 / 0.06);
  --shadow-sheet:   0 16px 40px -8px rgb(6 7 10 / 0.18), 0 2px 8px rgb(6 7 10 / 0.08);
  --shadow-toast:   0 8px 24px -4px rgb(6 7 10 / 0.14);

  /* --- Motion ------------------------------------------------------------ */
  --duration-instant: 90ms;
  --duration-fast: 140ms;
  --duration-normal: 220ms;
  --duration-slow: 380ms;
  --duration-deliberate: 620ms; /* hero reveal only */

  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.30, 1);
  --ease-in-out:    cubic-bezier(0.65, 0, 0.35, 1);

  --stagger-step: 55ms;

  /* --- Layout ------------------------------------------------------------ */
  --container-prose: 44rem;
  --container-content: 72rem;
  --container-wide: 88rem;
  --hq-sidebar-w: 15rem;
  --hq-sidebar-w-collapsed: 3.5rem;
  --hq-topbar-h: 3.5rem;
  --hq-tabbar-h: 3.75rem; /* mobile bottom nav */
  --z-sticky: 100;
  --z-overlay: 200;
  --z-toast: 300;
}

/* ==========================================================================
   TIER 2 — SEMANTIC (light is the default; dark overrides below)
   Components read ONLY from this tier.
   ========================================================================== */

:root {
  color-scheme: light;

  /* surfaces — four steps, no more */
  --color-surface-page:    var(--rs-neutral-50);
  --color-surface-raised:  var(--rs-neutral-0);
  --color-surface-sunken:  var(--rs-neutral-100);
  --color-surface-overlay: var(--rs-neutral-0);
  --color-surface-inverse: var(--rs-neutral-950);

  /* text */
  --color-text-primary:   var(--rs-neutral-900);
  --color-text-secondary: var(--rs-neutral-700);
  --color-text-muted:     var(--rs-neutral-600);
  --color-text-disabled:  var(--rs-neutral-400);
  --color-text-inverse:   var(--rs-neutral-50);
  --color-text-on-brand:  var(--rs-neutral-0);
  --color-text-link:      var(--rs-blue-600);

  /* lines — hairline separates, divider groups. Divider is deliberately
     below 1.2:1; it is a rhythm cue, never a load-bearing boundary. */
  --color-border-hairline: var(--rs-neutral-300);
  --color-border-divider:  var(--rs-neutral-200);
  --color-border-strong:   var(--rs-neutral-400);
  --color-border-brand:    var(--rs-blue-500);

  /* brand */
  --color-brand:         var(--rs-blue-500);
  --color-brand-hover:   var(--rs-blue-600);
  --color-brand-active:  var(--rs-blue-700);
  --color-brand-subtle:  var(--rs-blue-50);
  --color-brand-subtle-border: var(--rs-blue-200);
  --color-brand-text:    var(--rs-blue-600);

  /* status — -fg is the text/icon, -bg the tint, -dot the solid marker */
  --color-success-fg:  var(--rs-green-700);
  --color-success-bg:  var(--rs-green-50);
  --color-success-dot: var(--rs-green-500);
  --color-warning-fg:  var(--rs-amber-700);
  --color-warning-bg:  var(--rs-amber-50);
  --color-warning-dot: var(--rs-amber-500);
  --color-danger-fg:   var(--rs-red-700);
  --color-danger-bg:   var(--rs-red-50);
  --color-danger-dot:  var(--rs-red-500);
  --color-info-fg:     var(--rs-blue-700);
  --color-info-bg:     var(--rs-blue-50);
  --color-info-dot:    var(--rs-blue-500);

  /* live — see usage law on --rs-hiviz */
  --color-live:       var(--rs-hiviz);
  --color-live-on:    var(--rs-neutral-1000);

  /* interaction */
  --color-focus-ring: var(--rs-blue-500);
  --color-hover-wash: color-mix(in oklch, var(--rs-neutral-900) 5%, transparent);
  --color-press-wash: color-mix(in oklch, var(--rs-neutral-900) 9%, transparent);
  --color-selected:   var(--rs-blue-50);
  --color-scrim:      color-mix(in oklch, var(--rs-neutral-950) 45%, transparent);
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --color-surface-page:    var(--rs-neutral-950);
  --color-surface-raised:  var(--rs-neutral-925);
  --color-surface-sunken:  var(--rs-neutral-1000);
  --color-surface-overlay: var(--rs-neutral-900);
  --color-surface-inverse: var(--rs-neutral-50);

  --color-text-primary:   var(--rs-neutral-100);
  --color-text-secondary: var(--rs-neutral-300);
  --color-text-muted:     var(--rs-neutral-400);
  --color-text-disabled:  var(--rs-neutral-600);
  --color-text-inverse:   var(--rs-neutral-900);
  --color-text-on-brand:  var(--rs-neutral-0);
  --color-text-link:      var(--rs-blue-300);

  --color-border-hairline: var(--rs-neutral-800);
  --color-border-divider:  var(--rs-neutral-850);
  --color-border-strong:   var(--rs-neutral-700);
  --color-border-brand:    var(--rs-blue-400);

  --color-brand:         var(--rs-blue-500);
  --color-brand-hover:   var(--rs-blue-400);
  --color-brand-active:  var(--rs-blue-300);
  --color-brand-subtle:  color-mix(in oklch, var(--rs-blue-500) 16%, var(--rs-neutral-950));
  --color-brand-subtle-border: color-mix(in oklch, var(--rs-blue-500) 34%, var(--rs-neutral-950));
  --color-brand-text:    var(--rs-blue-300);

  --color-success-fg:  var(--rs-green-300);
  --color-success-bg:  color-mix(in oklch, var(--rs-green-500) 20%, var(--rs-neutral-950));
  --color-success-dot: var(--rs-green-400);
  --color-warning-fg:  var(--rs-amber-300);
  --color-warning-bg:  color-mix(in oklch, var(--rs-amber-400) 18%, var(--rs-neutral-950));
  --color-warning-dot: var(--rs-amber-400);
  --color-danger-fg:   var(--rs-red-300);
  --color-danger-bg:   color-mix(in oklch, var(--rs-red-500) 20%, var(--rs-neutral-950));
  --color-danger-dot:  var(--rs-red-400);
  --color-info-fg:     var(--rs-blue-300);
  --color-info-bg:     color-mix(in oklch, var(--rs-blue-500) 18%, var(--rs-neutral-950));
  --color-info-dot:    var(--rs-blue-400);

  --color-focus-ring: var(--rs-blue-400);
  --color-hover-wash: color-mix(in oklch, var(--rs-neutral-0) 7%, transparent);
  --color-press-wash: color-mix(in oklch, var(--rs-neutral-0) 12%, transparent);
  --color-selected:   color-mix(in oklch, var(--rs-blue-500) 22%, var(--rs-neutral-950));
  --color-scrim:      color-mix(in oklch, var(--rs-neutral-1000) 65%, transparent);
}

/* System preference when the user has made no explicit choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --color-surface-page:    var(--rs-neutral-950);
    --color-surface-raised:  var(--rs-neutral-925);
    --color-surface-sunken:  var(--rs-neutral-1000);
    --color-surface-overlay: var(--rs-neutral-900);
    --color-surface-inverse: var(--rs-neutral-50);

    --color-text-primary:   var(--rs-neutral-100);
    --color-text-secondary: var(--rs-neutral-300);
    --color-text-muted:     var(--rs-neutral-400);
    --color-text-disabled:  var(--rs-neutral-600);
    --color-text-inverse:   var(--rs-neutral-900);
    --color-text-link:      var(--rs-blue-300);

    --color-border-hairline: var(--rs-neutral-800);
    --color-border-divider:  var(--rs-neutral-850);
    --color-border-strong:   var(--rs-neutral-700);
    --color-border-brand:    var(--rs-blue-400);

    --color-brand-hover:   var(--rs-blue-400);
    --color-brand-active:  var(--rs-blue-300);
    --color-brand-subtle:  color-mix(in oklch, var(--rs-blue-500) 16%, var(--rs-neutral-950));
    --color-brand-subtle-border: color-mix(in oklch, var(--rs-blue-500) 34%, var(--rs-neutral-950));
    --color-brand-text:    var(--rs-blue-300);

    --color-success-fg:  var(--rs-green-300);
    --color-success-bg:  color-mix(in oklch, var(--rs-green-500) 20%, var(--rs-neutral-950));
    --color-success-dot: var(--rs-green-400);
    --color-warning-fg:  var(--rs-amber-300);
    --color-warning-bg:  color-mix(in oklch, var(--rs-amber-400) 18%, var(--rs-neutral-950));
    --color-warning-dot: var(--rs-amber-400);
    --color-danger-fg:   var(--rs-red-300);
    --color-danger-bg:   color-mix(in oklch, var(--rs-red-500) 20%, var(--rs-neutral-950));
    --color-danger-dot:  var(--rs-red-400);
    --color-info-fg:     var(--rs-blue-300);
    --color-info-bg:     color-mix(in oklch, var(--rs-blue-500) 18%, var(--rs-neutral-950));
    --color-info-dot:    var(--rs-blue-400);

    --color-focus-ring: var(--rs-blue-400);
    --color-hover-wash: color-mix(in oklch, var(--rs-neutral-0) 7%, transparent);
    --color-press-wash: color-mix(in oklch, var(--rs-neutral-0) 12%, transparent);
    --color-selected:   color-mix(in oklch, var(--rs-blue-500) 22%, var(--rs-neutral-950));
    --color-scrim:      color-mix(in oklch, var(--rs-neutral-1000) 65%, transparent);
  }
}

/* ==========================================================================
   TIER 3 — COMPONENT CONTRACTS
   ========================================================================== */

:root {
  /* Controls. 44px is the floor for anything a driver taps in a moving
     vehicle or with gloves on — that is the whole reason -lg exists. */
  --control-h-sm: 2rem;    /* 32px — dense table row actions, desktop only */
  --control-h-md: 2.5rem;  /* 40px — default desktop */
  --control-h-lg: 2.75rem; /* 44px — all mobile, all field-facing actions */
  --control-h-xl: 3.25rem; /* 52px — primary CTA, selfie/check-in button */
  --control-px: var(--space-sm);
  --control-radius: var(--radius-sm);
  --control-border-w: 1px;

  --focus-ring-w: 2px;
  --focus-ring-offset: 2px;

  --field-h: var(--control-h-lg);
  --field-radius: var(--radius-sm);
  --field-label-size: var(--text-xs);

  --card-p: var(--space-md);
  --card-radius: var(--radius-md);
  --card-gap: var(--space-sm);

  --table-row-h: 3rem;
  --table-row-h-dense: 2.25rem;
  --table-cell-px: var(--space-xs);

  --badge-h: 1.5rem;
  --badge-px: var(--space-2xs);
  --badge-radius: var(--radius-xs);

  --sheet-radius: var(--radius-xl);
  --toast-radius: var(--radius-md);
}

/* ==========================================================================
   BASE — the minimum every surface inherits
   ========================================================================== */

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

body {
  margin: 0;
  background: var(--color-surface-page);
  color: var(--color-text-primary);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Light-on-dark type reads thinner than it is; give it more air. */
:root[data-theme="dark"] body { line-height: var(--leading-relaxed); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body { line-height: var(--leading-relaxed); }
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin: 0;
  text-wrap: balance;
}

p { text-wrap: pretty; max-width: var(--measure-prose); }

/* Numbers in tables must align vertically. Non-negotiable in a freight UI. */
[data-numeric], td[align="right"], .tabular {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "zero" 1;
}

/* The mono micro-label. Lifted straight from the brand book's
   "SYSTEM METRIC / 1:203,002 / ↳ NO ZONE 86°" corner blocks. */
.label-metric {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--focus-ring-w) solid var(--color-focus-ring);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
}

@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;
  }
}
