/* ============================================================================
   M1 DESIGN SYSTEM — TOKENS
   Build Plan §8.1. The only file that may contain a raw colour value.
   Components consume SEMANTIC tokens only; if a component references --n-500 or
   a hex literal, that is a bug.

   Layers, in order:
     1. primitives  raw ramps, no meaning attached
     2. brand       the one slot each system may override
     3. semantic    what components actually use — defined for BOTH themes
     4. density     pos / back-office / customer
     5. motion, type, radius, elevation
   ========================================================================= */

:root {
  /* ---------------------------------------------------------------- 1. PRIMITIVES
     Neutral ramp is blue-tinted so it sits with the M1 ink (#0c1a2e) rather
     than looking grey next to it. */
  --n-0:    #ffffff;
  --n-25:   #fafbfd;
  --n-50:   #f4f6fa;
  --n-100:  #e9edf4;
  --n-200:  #d7dee9;
  --n-300:  #b9c4d5;
  --n-400:  #909db5;
  --n-500:  #6b7a94;
  --n-600:  #53627d;
  --n-700:  #3e4c63;
  --n-800:  #2b3749;
  --n-900:  #1a2433;
  --n-950:  #0c1a2e;   /* the established M1 ink */
  --n-1000: #060d18;

  /* intent ramps — meaning is fixed across every system, unlike brand */
  --success-400: #34d399;  --success-500: #10b981;  --success-600: #059669;  --success-700: #047857;
  --warning-400: #fbbf24;  --warning-500: #f59e0b;  --warning-600: #d97706;  --warning-800: #92400e;
  --danger-400:  #fb7185;  --danger-500:  #e11d48;  --danger-600:  #be123c;  --danger-700:  #9f1239;
  --info-400:    #38bdf8;  --info-500:    #0ea5e9;  --info-600:    #0284c7;  --info-700:    #0369a1;

  /* ---------------------------------------------------------------- 2. BRAND
     THE ONLY TOKENS A SYSTEM MAY OVERRIDE. Default is M1 (from m1timepilot,
     the reference site). Per-system files live in tokens/brand/.
     Everything else — spacing, type, radius, elevation, motion, components —
     is identical across all eleven verticals. That is what makes them one
     platform wearing different colours rather than eleven products. */
  --brand-50:  #eff6ff;
  --brand-100: #dbeafe;
  --brand-200: #bfdbfe;
  --brand-300: #93c5fd;
  --brand-400: #60a5fa;
  --brand-500: #2563eb;   /* m1timepilot --primary */
  --brand-600: #1d4ed8;   /* m1timepilot --primary-dark */
  --brand-700: #1e40af;
  --brand-800: #1e3a8a;
  --brand-900: #172554;
  --accent-500: #10b981;  /* m1timepilot --accent */
  --accent-600: #059669;

  /* ---------------------------------------------------------------- 5. TYPE */
  --font-head: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  /* Arabic gets its own stack; Latin fonts render Arabic badly even when they claim support */
  --font-arabic: 'IBM Plex Sans Arabic', 'Noto Sans Arabic', 'Segoe UI', Tahoma, sans-serif;

  --text-2xs: 0.6875rem;  /* 11 */
  --text-xs:  0.75rem;    /* 12 */
  --text-sm:  0.8125rem;  /* 13 */
  --text-md:  0.875rem;   /* 14 — back-office default */
  --text-lg:  1rem;       /* 16 */
  --text-xl:  1.125rem;   /* 18 */
  --text-2xl: 1.375rem;   /* 22 */
  --text-3xl: 1.75rem;    /* 28 */
  --text-4xl: 2.25rem;    /* 36 */
  --text-5xl: 3rem;       /* 48 */

  --leading-tight: 1.25;
  --leading-base:  1.5;
  --leading-loose: 1.7;
  /* Arabic needs more room: taller ascenders/descenders and no capital height
     to hide behind. Applied on [lang=ar] in base.css, not guessed per component. */
  --leading-arabic: 1.85;

  --weight-regular: 400;
  --weight-medium:  500;
  --weight-semibold:600;
  --weight-bold:    700;

  /* ---------------------------------------------------------------- SPACING
     4px base. Named by step, not by use, so it stays honest. */
  --space-0:  0;
  --space-1:  0.25rem;   /* 4  */
  --space-2:  0.5rem;    /* 8  */
  --space-3:  0.75rem;   /* 12 */
  --space-4:  1rem;      /* 16 */
  --space-5:  1.25rem;   /* 20 */
  --space-6:  1.5rem;    /* 24 */
  --space-8:  2rem;      /* 32 */
  --space-10: 2.5rem;    /* 40 */
  --space-12: 3rem;      /* 48 */
  --space-16: 4rem;      /* 64 */

  /* ---------------------------------------------------------------- RADIUS */
  --radius-xs:   4px;
  --radius-sm:   6px;
  --radius-md:   10px;
  --radius-lg:   14px;   /* m1timepilot --radius */
  --radius-xl:   20px;
  --radius-full: 999px;

  /* ---------------------------------------------------------------- MOTION */
  --motion-instant: 0ms;
  --motion-fast:    120ms;
  --motion-base:    200ms;
  --motion-slow:    320ms;
  --ease-standard:   cubic-bezier(.2, 0, 0, 1);
  --ease-decelerate: cubic-bezier(0, 0, 0, 1);
  --ease-accelerate: cubic-bezier(.3, 0, 1, 1);

  /* ---------------------------------------------------------------- FOCUS
     One focus treatment everywhere. Keyboard users should never have to hunt. */
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;
}

/* ============================================================================
   3. SEMANTIC TOKENS — LIGHT
   Components reference these and nothing above them.
   ========================================================================= */
:root,
:root[data-theme='light'] {
  color-scheme: light;

  --surface-base:    var(--n-50);   /* page — deliberately not pure white, so a raised card reads as raised */
  --surface-raised:  var(--n-0);
  --surface-sunken:  var(--n-100);
  --surface-overlay: var(--n-0);
  --surface-inverse: var(--n-950);
  --surface-hover:   rgba(12, 26, 46, 0.04);
  --surface-active:  rgba(12, 26, 46, 0.08);
  --surface-selected:var(--brand-50);
  --surface-disabled:var(--n-100);

  --text-primary:   var(--n-950);
  --text-secondary: var(--n-700);
  --text-muted:     var(--n-600);   /* n-500 measured 4.01:1 on the page — under AA */
  --text-disabled:  var(--n-400);
  --text-inverse:   var(--n-0);
  --text-on-brand:  #ffffff;
  --text-link:      var(--brand-600);

  --border-subtle: var(--n-200);
  --border-strong: var(--n-500);   /* SC 1.4.11 wants 3:1 on a control boundary; n-300 was 1.76:1 */
  --border-focus:  var(--brand-500);

  /* FILL tokens — solid backgrounds. Paired with --text-on-brand / white. */
  --intent-brand:   var(--brand-500);
  --intent-brand-hover: var(--brand-600);
  --intent-success: var(--success-600);
  --intent-warning: var(--warning-600);
  --intent-danger:  var(--danger-500);
  --intent-info:    var(--info-600);

  /* TEXT tokens — the same meanings used as TEXT on a surface or a tint.
     Separate from the fills on purpose: a colour that carries white text at
     4.5:1 is almost never the same colour that reads at 4.5:1 as text. */
  --intent-brand-text:   var(--brand-700);
  --intent-success-text: var(--success-700);
  --intent-warning-text: var(--warning-800);
  --intent-danger-text:  var(--danger-700);
  --intent-info-text:    var(--info-700);

  /* tinted backgrounds for status chips/banners */
  --intent-success-surface: #ecfdf5;
  --intent-warning-surface: #fffbeb;
  --intent-danger-surface:  #fff1f2;
  --intent-info-surface:    #f0f9ff;
  --intent-brand-surface:   var(--brand-50);

  /* Elevation is theme-specific on purpose. In light, depth comes from shadow. */
  --elevation-0: none;
  --elevation-1: 0 1px 2px rgba(12, 26, 46, .06), 0 1px 3px rgba(12, 26, 46, .04);
  --elevation-2: 0 2px 4px rgba(12, 26, 46, .06), 0 4px 12px rgba(12, 26, 46, .07);
  --elevation-3: 0 8px 16px rgba(12, 26, 46, .08), 0 16px 32px rgba(12, 26, 46, .10);
  --elevation-4: 0 16px 32px rgba(12, 26, 46, .12), 0 32px 64px rgba(12, 26, 46, .14);
}

/* ============================================================================
   3b. SEMANTIC TOKENS — DARK
   Not an inversion. In dark, depth comes from SURFACE LIFT plus a hairline
   border; shadows alone are nearly invisible on a dark background, which is
   the single most common way dark mode ends up looking flat.
   ========================================================================= */
:root[data-theme='dark'] {
  color-scheme: dark;

  --surface-base:    var(--n-1000);
  --surface-raised:  var(--n-900);
  --surface-sunken:  #03070e;
  --surface-overlay: var(--n-800);
  --surface-inverse: var(--n-50);
  --surface-hover:   rgba(255, 255, 255, 0.06);
  --surface-active:  rgba(255, 255, 255, 0.10);
  --surface-selected:rgba(37, 99, 235, 0.18);
  --surface-disabled:var(--n-800);

  --text-primary:   var(--n-50);
  --text-secondary: var(--n-300);
  --text-muted:     var(--n-400);
  --text-disabled:  var(--n-600);
  --text-inverse:   var(--n-950);
  --text-on-brand:  #ffffff;
  --text-link:      var(--brand-300);

  --border-subtle: rgba(255, 255, 255, 0.10);
  --border-strong: rgba(255, 255, 255, 0.38);  /* 0.20 composited to 1.92:1 — under SC 1.4.11 */
  --border-focus:  var(--brand-400);

  /* Fills keep the 500 ramp so a white label still clears 4.5:1 on them.
     Lifting the FILL to 400 (the obvious move) drops white-on-brand to 2.54:1 —
     measured, not guessed. The lift belongs on the TEXT tokens instead. */
  --intent-brand:   var(--brand-500);
  --intent-brand-hover: var(--brand-600);
  --intent-success: var(--success-600);
  --intent-warning: var(--warning-600);
  --intent-danger:  var(--danger-500);
  --intent-info:    var(--info-600);

  /* TEXT on dark surfaces and tints: here the ramp does lift. */
  --intent-brand-text:   var(--brand-300);
  --intent-success-text: var(--success-400);
  --intent-warning-text: var(--warning-400);
  --intent-danger-text:  var(--danger-400);
  --intent-info-text:    var(--info-400);

  --intent-success-surface: rgba(16, 185, 129, .14);
  --intent-warning-surface: rgba(245, 158, 11, .14);
  --intent-danger-surface:  rgba(225, 29, 72, .16);
  --intent-info-surface:    rgba(14, 165, 233, .14);
  --intent-brand-surface:   rgba(37, 99, 235, .18);

  --elevation-0: none;
  --elevation-1: 0 1px 2px rgba(0,0,0,.40), inset 0 0 0 1px rgba(255,255,255,.04);
  --elevation-2: 0 4px 12px rgba(0,0,0,.50), inset 0 0 0 1px rgba(255,255,255,.06);
  --elevation-3: 0 16px 32px rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,255,255,.08);
  --elevation-4: 0 32px 64px rgba(0,0,0,.65), inset 0 0 0 1px rgba(255,255,255,.10);
}

/* ============================================================================
   4. DENSITY — §8.1
   back-office : information-dense tables and forms (default)
   pos         : gloves, wet hands, arm's length, kitchen lighting
   customer    : spacious, marketing-adjacent
   Set with data-density on any container; it cascades.
   ========================================================================= */
:root,
[data-density='back-office'] {
  --control-height:   2.25rem;   /* 36 */
  --control-padding-x:var(--space-3);
  --control-font:     var(--text-md);
  --control-radius:   var(--radius-sm);
  --stack-gap:        var(--space-3);
  --section-gap:      var(--space-6);
  --tap-target:       2.25rem;
}

[data-density='pos'] {
  --control-height:   3.5rem;    /* 56 — comfortably hit with a gloved thumb */
  --control-padding-x:var(--space-5);
  --control-font:     var(--text-xl);
  --control-radius:   var(--radius-md);
  --stack-gap:        var(--space-4);
  --section-gap:      var(--space-6);
  --tap-target:       3rem;      /* 48 — above the 44px WCAG 2.1 AA floor */
}

[data-density='customer'] {
  --control-height:   2.75rem;   /* 44 */
  --control-padding-x:var(--space-4);
  --control-font:     var(--text-lg);
  --control-radius:   var(--radius-md);
  --stack-gap:        var(--space-4);
  --section-gap:      var(--space-10);
  --tap-target:       2.75rem;
}

/* ============================================================================
   REDUCED MOTION — §8.5. Zero the durations at token level so no component has
   to remember; anything animating still works, it just arrives immediately.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 0ms;
    --motion-base: 0ms;
    --motion-slow: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   6. DATA VISUALISATION — §8.3 charts
   The one palette that is NOT derived from brand. A series colour identifies an
   entity; if it moved with the brand, the same product line would be a different
   colour in Serve and in TimePilot, and a chart read side by side would lie.

   Every value below was produced by the validator, not chosen by eye, and
   checked against M1's OWN surfaces (#ffffff light, #1a2433 dark) rather than a
   generic white/black:

     light  lightness band PASS · chroma PASS · adjacent CVD worst 9.1 (protan)
            · normal-vision worst 19.6 · contrast 3 slots under 3:1 -> WARN
     dark   lightness band PASS · chroma PASS · adjacent CVD worst 8.4 (protan)
            · normal-vision worst 19.3 · contrast all >= 3:1 PASS

   THREE RULES THIS PALETTE ONLY WORKS UNDER:

   1. SLOTS ARE ASSIGNED IN ORDER AND NEVER CYCLED. The order is the
      colourblind-safety mechanism, not decoration — it is the ordering that
      clears the adjacent-pair gates. A ninth series is never a generated hue;
      it folds into "Other" or the chart becomes small multiples.

   2. THE ALL-PAIRS CAP IS THREE. In a form where any two series can end up
      adjacent — scatter, bubble, choropleth — only the first three slots clear
      the floors. The fourth puts yellow next to orange, which measures 13.7 in
      normal vision, below the 15 floor: a full-colour reader cannot reliably
      tell them apart. Cap at three and fold the rest, or facet.

   3. LIGHT MODE OWES RELIEF. Aqua, yellow and magenta sit under 3:1 on white,
      so a chart using them must carry visible direct labels or the table view
      that <m1-chart> ships. That is a requirement, not a nicety.

   Dark is SELECTED, not flipped: the same eight hues re-stepped for the dark
   band and validated as a set against #1a2433.

   Status colours are deliberately absent. good/warning/serious/critical are
   reserved and must never stand in for "series 4", or a neutral series starts
   reading as a failure.
   ========================================================================= */
:root,
:root[data-theme='light'] {
  --chart-1: #2563eb;   /* blue    — M1's own brand blue leads the set */
  --chart-2: #eb6834;   /* orange  */
  --chart-3: #1baf7a;   /* aqua    */
  --chart-4: #eda100;   /* yellow  */
  --chart-5: #e87ba4;   /* magenta */
  --chart-6: #008300;   /* green   */
  --chart-7: #4a3aa7;   /* violet  */
  --chart-8: #e34948;   /* red     */

  /* Sequential: ONE hue, light to dark. Never a rainbow. The lightest step is
     allowed to recede toward the surface because "near zero" should. */
  --chart-seq-1: #cde2fb; --chart-seq-2: #9ec5f4; --chart-seq-3: #6da7ec;
  --chart-seq-4: #3987e5; --chart-seq-5: #256abf; --chart-seq-6: #184f95;
  --chart-seq-7: #0d366b;
  /* An ORDINAL ramp (funnel stages, tiers) may not start lighter than this, or
     the first band disappears into the surface. */
  --chart-seq-floor: #86b6ef;

  /* Diverging: two poles that read as opposite, with a NEUTRAL grey midpoint.
     A hue at the midpoint would imply the middle means something. */
  --chart-div-neg: #2563eb;
  --chart-div-mid: #e9edf4;
  --chart-div-pos: #e34948;

  /* Chrome. Recessive by design — the data is the only thing allowed to be loud. */
  --chart-grid:     var(--n-100);
  --chart-axis:     var(--n-200);
  --chart-surface:  var(--surface-raised);
}

:root[data-theme='dark'] {
  --chart-1: #3987e5;
  --chart-2: #d95926;
  --chart-3: #199e70;
  --chart-4: #c98500;
  --chart-5: #d55181;
  --chart-6: #008300;
  --chart-7: #9085e9;
  --chart-8: #e66767;

  --chart-seq-1: #0d366b; --chart-seq-2: #184f95; --chart-seq-3: #256abf;
  --chart-seq-4: #3987e5; --chart-seq-5: #6da7ec; --chart-seq-6: #9ec5f4;
  --chart-seq-7: #cde2fb;
  --chart-seq-floor: #184f95;

  --chart-div-neg: #3987e5;
  --chart-div-mid: #2b3749;
  --chart-div-pos: #e66767;

  --chart-grid:    rgba(255, 255, 255, 0.08);
  --chart-axis:    rgba(255, 255, 255, 0.16);
  --chart-surface: var(--surface-raised);
}
