/* ============================================================
 * design-kit / tokens.css
 * Version: see ../../.kit-version
 *
 * Source: Figma `UI-Element_v2` + the CovMo5 front-end source.
 * Variable names are the product's own. Do not invent new ones — when the
 * prototype reaches R&D, the names have to line up.
 *
 * Usage: link this before any style of your own, then use var(--…) for
 * everything. No literal values.
 *   <html data-app="dashboard">   module accent (one of 8; omit for neutral)
 *   <html data-theme="dark">      pin the theme (omit to follow the system)
 * ============================================================ */

:root {
  color-scheme: light dark;

  /* --- Fonts ----------------------------------------------- */
  --font-sans:    Roboto, "Noto Sans TC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono:    "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-display: Montserrat, var(--font-sans);   /* product wordmark only */

  /* --- Type: four sizes, no more --------------------------- */
  --fs-large:  16px;  --lh-large:  24px;
  --fs-medium: 14px;  --lh-medium: 22px;
  --fs-small:  12px;  --lh-small:  18px;   /* body */
  --fs-mini:   10px;  --lh-mini:   16px;
  --fw-regular: 400;
  --fw-semibold: 600;

  /* Headings (Roboto 600, line-height 200%) */
  --fs-h1: 32px;  --fs-h2: 25px;  --fs-h3: 20px;  --fs-h4: 16px;  --fs-h5: 14px;
  --lh-heading: 2;

  /* --- Spacing / radius / motion --------------------------- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px; --space-6: 24px; --space-8: 32px;
  /* Radius: the product uses 4px (206 sites) and 8px (43). Use those two.
     --radius-6 and --radius-10 are DEPRECATED as of 2026-09-23: 6px occurs
     once in the whole product and 10px twice, so this kit's earlier claim
     that the 4/6/8/10 scale "came from the product" was not true for those
     two. They are kept so that prototypes built against 2026.09.x keep
     working; they will go in the next major version. Do not use them. */
  --radius-4: 4px; --radius-6: 6px; --radius-8: 8px; --radius-10: 10px;

  /* Elevation: the product has exactly one, and it carries a hairline with it
     — the token means "a surface floating above the page", not "a shadow".
     Use it whole; a dropdown with the shadow but no outline is not the
     product's dropdown. (CovMo5 styledComponents/shadowCss, 72 uses.)
     For a hairline on one edge the product writes it out longhand instead:
     box-shadow: inset 0 -1px 0 var(--divider);   ← bottom
     box-shadow: inset 0  1px 0 var(--divider);   ← top */
  --shadow-float: 0 3px 6px 0 rgb(36 36 36 / .2);
  --shadow-float-outline: 1px solid var(--divider);
  --transition-fast:   .15s;
  --transition-switch: .2s;
  --transition-theme:  .25s;
  --window-gap: 12px;
  /* Verified against CovMo5 develop-q2-2026 @ 991b1e0b:
     TOP_CONTAINER_HEIGHT = 40 (app/common_modules/constants/ui/space/index.ts).
     Was 56px until 2026-09-23 — 56 had no source on any side. Call Window's own
     header is 40 too; Figma's 36 is wrong. The 1px bottom divider is INSIDE
     this 40, because the product is border-box throughout. */
  --header-height: 40px;
  /* Same source, constants/ui/zIndex. The product's full scale runs -1…99;
     only the two levels this kit actually needs are defined here. */
  --z-header: 50;   /* Z_INDEX_TOP_BAR_0 */
  --z-flyout: 71;   /* Z_INDEX_FLYOUT_1 — floats above the bar */

  /* --- Theme colours (light) ------------------------------- */
  --primary:          rgb(252 252 252);
  --primary-invert:   rgb(36 36 36);
  --primary-a90:      rgb(252 252 252 / .9);
  --secondary:        #F2F2F2;
  --secondary-invert: #333333;
  --tertiary:         #E6E6E6;
  --quaternary:       #D9D9D9;
  --quinary:          #CCCCCC;
  --quinary-invert:   #8C8C8C;
  --senary:           #BFBFBF;
  --senary-invert:    #A6A6A6;
  --septenary:        #B2B2B2;
  --red-primary:      #8E2D32;
  --red-secondary:    #FFC2D1;
  --red-tertiary:     #FF7B9C;

  /* Semantic aliases. The product's THEME/* tokens point at these — do not redefine. */
  --background:  var(--tertiary);
  --divider:     var(--quaternary);
  --text:        var(--quinary);
  --placeholder: var(--septenary);
  --scroll:      #CCCCCC;

  /* --- Text on solid fills (fixed across themes and modules) ---
   * The product's UI_WHITE / UI_BLACK constants. --primary flips with the
   * theme, so it must NOT be used for text on a solid button: the text would
   * be readable in one theme and invisible in the other.
   *
   * These follow the product, not a contrast measurement. Until 2026-09-23 this
   * kit put DARK text on the module colour and on success, because dark scores
   * better on 7 of the 8 modules. That was the kit deciding for itself: the
   * product's button config uses UI_WHITE on the module colour, on success and
   * on danger, and the design system's own component sheet says the same in both
   * themes. Only warning takes dark text, and the product ships no warning
   * button at all — that one comes from the sheet alone.
   *
   * ⚠️ The cost of matching the product: white text clears 4.5:1 on NONE of the
   * eight module colours. As of 2026.09.3's new global colours it lands at
   * 3.86-3.92 on seven of them and 3.30 on optimization -- so nothing is below
   * 3:1 any more, which is the part that mattered, but nothing reaches AA either.
   * Success is 3.92. This is the design system's own position, reproduced rather
   * than quietly corrected here, and it is on the list going back to the design
   * team. If you need an accessible prototype more than a faithful one, do NOT
   * reach for dark text: 2026.09.3's ramps equalised light and dark contrast at
   * the 500 step on purpose, so --ink-dark now clears 4.5:1 on exactly one module
   * out of eight. What works is darkening the FILL -- white on var(--app-700)
   * clears it on all eight (5.87-6.57), white on var(--app-600) on seven. Do that
   * in your own stylesheet and write down why.
   */
  --ink-dark:  rgb(36 36 36);
  --ink-light: rgb(252 252 252);
  --ink-on-app:     var(--ink-light);
  --ink-on-success: var(--ink-light);
  --ink-on-warning: var(--ink-dark);
  --ink-on-danger:  var(--ink-light);

  /* --- Status colours (same in both themes) ----------------
   * From the design system's own component sheet (COMPONENTs, both themes),
   * which is the only place success / danger / warning are specified together.
   * Product names: UI_FOREST_GREEN_500, UI_YELLOW_500, UI_CRIMSON_RED_600.
   *
   * Two changes on 2026-09-23, in order. In 2026.09.2 --success went #4FA426 →
   * #61992D and --warning #FFB24D → #FFD11A: the old pair came from Figma's
   * MISC/SUCCESS and MISC/WARNING, a different hue family altogether
   * (UI_LIME_GREEN_700 and UI_ORANGE_300), and the orange was the odd one out
   * even inside this file — --callout-warning-2 is #FFF3CC, i.e. UI_YELLOW_100,
   * and had been yellow all along. Then in 2026.09.3 the new global colours took
   * --success #61992D → #568D1E. --warning did not move again.
   *
   * Darker step for hover and pale step for a focus ring, when you need them:
   *   success  hover #487B17   ring #CDDFAF
   *   danger   hover #B3363C   ring #FF9FB7
   *   warning  hover #E6B800   ring #FFF3CC
   * No tokens for those — nothing in this kit uses them yet, and an unused
   * token is worse than none. Write the literal and cite this comment.
   */
  --success: #568D1E;
  --warning: #FFD11A;
  --danger:  #D04047;
  --link:    #0383DB;
  --normal:  #00B346;
  --failure: #E94C5F;
  --others:  #737373;

  /* --- Charts: use in order, do not pick your own ---------- */
  --chart-1: #098F82;   /* aqua green   */
  --chart-2: #0383DB;   /* sky blue     */
  --chart-3: #CC2CFF;   /* orchid       */
  --chart-4: #E46600;   /* orange       */
  --chart-5: #7479C7;   /* slate blue   */
  --chart-6: #91B356;   /* forest green */

  /* Severity: one colour at graded opacity. Map fills and the legend share these. */
  --sev-1: .30;  --sev-2: .45;  --sev-3: .60;  --sev-4: .75;  --sev-5: .90;

  /* --- Tables ---------------------------------------------- */
  --table-head-bg: var(--tertiary);
  --table-row-alt: var(--secondary);

  /* --- Radio technologies ---------------------------------- */
  --tech-gsm:  #5AB89F;  --tech-umts: #E6B800;  --tech-lte:  #B3363C;
  --tech-nsa:  #B220D7;  --tech-sa:   #0271BD;  --tech-wifi: #FFFF00;

  /* --- Header categories ----------------------------------- */
  --cat-dimension: #EDA139;
  --cat-attribute: #89A6EC;
  --cat-kpi:       #91B356;

  /* --- Callouts (light theme uses dark steps; dark inverts) - */
  --callout-default-1:  #3A8E1C;  --callout-default-2:  #D9F0C7;  --callout-default-3:  #A9E083;
  --callout-info-1:     #205D82;  --callout-info-2:     #C8E7F8;  --callout-info-3:     #91CDEC;
  --callout-warning-1:  #B27A00;  --callout-warning-2:  #FFF3CC;  --callout-warning-3:  #FFE366;

  /* --- Neutral ramp: the app colours when no module is set --
   * This is the theme's own grey scale, on purpose: with no module chosen
   * there is no accent to show, so the app colours ARE the theme colours.
   * See the `:root:not([data-app])` block below, which says so in one place
   * rather than leaving you to notice that two sets of values coincide. */
  --app-50:  #F2F2F2;  --app-100: #E6E6E6;  --app-200: #D9D9D9;
  --app-300: #CCCCCC;  --app-400: #BFBFBF;  --app-500: #B2B2B2;
  --app-600: #A6A6A6;  --app-700: #8C8C8C;  --app-800: #737373;
  --app-900: #595959;  --app-950: #333333;
}

/* ============================================================
 * Module accents — one of 8, set on <html data-app="…">.
 * Unset = neutral: a new feature, or a prototype not yet assigned to a module.
 * ============================================================ */
[data-app="call-window"] {
  --app-50:#D6FCEA; --app-100:#ACE3CA; --app-200:#83CDB4; --app-300:#5AB89F;
  --app-400:#2CA490; --app-500:#098F82; --app-600:#067A7C; --app-700:#016671;
  --app-800:#0A535E; --app-900:#12414B; --app-950:#142E36;
}
[data-app="dashboard"], [data-app="system-admin"] {
  --app-50:#EEF8D5; --app-100:#CDDFAF; --app-200:#AEC882; --app-300:#91B356;
  --app-400:#6FA039; --app-500:#568D1E; --app-600:#487B17; --app-700:#386711;
  --app-800:#2E550E; --app-900:#224308; --app-950:#172F07;
}
[data-app="genai"] {
  --app-50:#F0F3FE; --app-100:#CCD7F3; --app-200:#AABEEF; --app-300:#89A6EC;
  --app-400:#6A90EA; --app-500:#4977F7; --app-600:#3D61E5; --app-700:#3152C5;
  --app-800:#2C4698; --app-900:#283774; --app-950:#252A37;
}
[data-app="geo-analysis"] {
  --app-50:#E9F4FF; --app-100:#C0DBF2; --app-200:#9AC3E9; --app-300:#75ADDF;
  --app-400:#5899CE; --app-500:#4982C3; --app-600:#416EAF; --app-700:#3C5C98;
  --app-800:#344B7A; --app-900:#2B3B5B; --app-950:#222A3C;
}
[data-app="optimization"] {
  --app-50:#FFF2E2; --app-100:#F6D8AA; --app-200:#EFBD72; --app-300:#EDA139;
  --app-400:#E98408; --app-500:#E46600; --app-600:#C35500; --app-700:#A94300;
  --app-800:#8E3300; --app-900:#702503; --app-950:#4C1B08;
}
[data-app="reporting"] {
  --app-50:#F1F2FE; --app-100:#D3D6F3; --app-200:#B9BCE7; --app-300:#A0A3DD;
  --app-400:#898DD2; --app-500:#7479C7; --app-600:#6165BA; --app-700:#5053AA;
  --app-800:#44467F; --app-900:#373958; --app-950:#282A35;
}
[data-app="subscriber-trace"] {
  --app-50:#E6F5FF; --app-100:#C1DCEB; --app-200:#95C5E0; --app-300:#63B0E1;
  --app-400:#2C9AE1; --app-500:#0383DB; --app-600:#0271BD; --app-700:#075DA6;
  --app-800:#124D87; --app-900:#133D65; --app-950:#132D3F;
}

/* Ramp step -> semantic role (light). --app-primary is APP_500 in both themes, deliberately. */
:root {
  --app-primary:       var(--app-500);
  --app-secondary:     var(--app-50);
  --app-tertiary:      var(--app-100);   /* hover   */
  --app-quaternary:    var(--app-200);   /* border  */
  --app-quinary:       var(--app-300);   /* focus   */
  --app-senary:        var(--app-400);
  --app-senary-invert: var(--app-600);   /* hover 2 */
}

/* No module chosen: take the theme colour.
 *
 * Every role below already resolved to exactly this value in both themes,
 * because the neutral ramp is the theme's grey scale. Stating it directly
 * makes the intent readable, survives a change to either scale, and stops
 * the next person treating the coincidence as a bug to be fixed.
 *
 * ⚠️ The consequence is real and you must design around it: with no module,
 * an app colour and its theme counterpart are THE SAME COLOUR. A table whose
 * header is --tertiary and whose hover row is --app-tertiary shows one grey,
 * not two — and every static check still passes, because both tokens are
 * correct. In neutral, separate states with a border, a weight or --quinary,
 * not with accent-versus-surface. */
:root:not([data-app]) {
  --app-primary:       var(--septenary);
  --app-secondary:     var(--secondary);
  --app-tertiary:      var(--tertiary);
  --app-quaternary:    var(--quaternary);
  --app-quinary:       var(--quinary);
  --app-senary:        var(--senary);
  --app-senary-invert: var(--senary-invert);
}

/* ============================================================
 * Dark — follows the system; data-theme overrides it.
 * ============================================================ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary:          rgb(36 36 36);
    --primary-invert:   rgb(252 252 252);
    --primary-a90:      rgb(36 36 36 / .9);
    --secondary:        #333333;
    --secondary-invert: #F2F2F2;
    --tertiary:         #595959;
    --quaternary:       #737373;
    --quinary:          #8C8C8C;
    --quinary-invert:   #CCCCCC;
    --senary:           #A6A6A6;
    --senary-invert:    #BFBFBF;
    --septenary:        #B2B2B2;
    --red-primary:      #FF9FB7;
    --red-secondary:    #672426;
    --red-tertiary:     #B3363C;

    --callout-default-1:#C1E8A5; --callout-default-2:#256B12; --callout-default-3:#4FA426;
    --callout-info-1:   #ADD9F3; --callout-info-2:   #103E61; --callout-info-3:   #2F7BA2;
    --callout-warning-1:#FFEB99; --callout-warning-2:#806600; --callout-warning-3:#CC9900;

    --app-secondary:     var(--app-950);
    --app-tertiary:      var(--app-900);
    --app-quaternary:    var(--app-800);
    --app-quinary:       var(--app-700);
    --app-senary:        var(--app-600);
    --app-senary-invert: var(--app-400);
  }
}

:root[data-theme="dark"] {
  --primary:          rgb(36 36 36);
  --primary-invert:   rgb(252 252 252);
  --primary-a90:      rgb(36 36 36 / .9);
  --secondary:        #333333;
  --secondary-invert: #F2F2F2;
  --tertiary:         #595959;
  --quaternary:       #737373;
  --quinary:          #8C8C8C;
  --quinary-invert:   #CCCCCC;
  --senary:           #A6A6A6;
  --senary-invert:    #BFBFBF;
  --septenary:        #B2B2B2;
  --red-primary:      #FF9FB7;
  --red-secondary:    #672426;
  --red-tertiary:     #B3363C;

  --callout-default-1:#C1E8A5; --callout-default-2:#256B12; --callout-default-3:#4FA426;
  --callout-info-1:   #ADD9F3; --callout-info-2:   #103E61; --callout-info-3:   #2F7BA2;
  --callout-warning-1:#FFEB99; --callout-warning-2:#806600; --callout-warning-3:#CC9900;

  --app-secondary:     var(--app-950);
  --app-tertiary:      var(--app-900);
  --app-quaternary:    var(--app-800);
  --app-quinary:       var(--app-700);
  --app-senary:        var(--app-600);
  --app-senary-invert: var(--app-400);
}

