/* Learnium portal: tokens.css (design system v2, docs/plans/PORTAL_REDESIGN_PROPOSAL.md Parts 3.1 to 3.3 and 4).
   The ONE place where colour literals live. Every other portal stylesheet uses var(--token) only
   (tools/check_tokens.py enforces it). Load order on a portal page: ../css/style.css, tokens.css, components.css, portal.css, page sheets ...
   Light values sit on :root; dark values apply when the device is dark (unless the person locked light)
   or when the person chose dark. theme-init.js sets data-theme on <html> before first paint. */

/* ==== SEEDS: the only colour literals in this file, besides the plain greys on lines tagged "neutral" ====
   To re-theme the portal, change --brand-light and --brand-dark (and, if wanted, the status seeds). Everything
   else derives from these with color-mix(); browsers from 2023 (Chrome 111, Safari 16.2, Firefox 113) support it.
   Brand v3 since 2026-11-03 (same palette as ../../css/style.css): cypress on light surfaces, sage on ink.
   After a change run python3 tools/check_tokens.py and open portal/js/tests/run-imat-tests.html:
   tokens.test.js re-checks every contrast pair in both themes. */
:root {
  --brand-light: #1E4B3A;         /* cypress: the accent on light surfaces (and on the light island in either theme) */
  --brand-dark: #A9C3AE;          /* sage: the accent on dark surfaces (and on the always-dark surfaces in either theme) */
  --brand: var(--brand-light);    /* the accent: buttons, links, focus, chart slot 1, mastery ramp; the dark blocks switch it to --brand-dark */
  --night: #101412;               /* the always-dark brand ink (same value as style.css) */
  --neutral-hue-mix: 4%;          /* how much --brand tints the light greys */
  --neutral-hue-mix-dark: 8%;     /* the same for the dark greys and the always-dark text colours */
  --seed-success: #1E7C43;
  --seed-warning: #B07500;
  --seed-danger: #B3261E;
  --seed-info: #2F6FBE;
  --seed-success-dark: #2FA86A;   /* the same four for the dark theme (brighter, so they read on dark surfaces) */
  --seed-warning-dark: #D9A441;
  --seed-danger-dark: #E06B6B;
  --seed-info-dark: #6B9BE8;
}
/* ==== end of SEEDS ==== */

:root {
  color-scheme: light dark;

  /* ---- surfaces and text (brand tint = --brand mixed into a plain grey) ---- */
  --bg: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #FBFBFB);  /* neutral */
  --bg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #F6F6F6);  /* neutral */
  --surface: #FFFFFF;  /* neutral */
  --surface-2: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #F6F6F6);  /* neutral */
  --surface-raised: #FFFFFF;  /* neutral: dialogs, popovers: pair with --shadow-md (light) */
  --border: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #E9E9E9);  /* neutral */
  --border-strong: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #D4D4D4);  /* neutral */
  --fg: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #121212);  /* neutral */
  --fg-muted: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #606060);  /* neutral */
  --fg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix), #6B6B6B);  /* neutral */

  /* ---- accent: everything derives from --brand ---- */
  --accent: var(--brand);
  --accent-hover: color-mix(in oklch, var(--brand) 78%, black);   /* cypress -> #123327, on cypress-deep #143327 (tuned in the browser 2026-11-03) */
  --accent-text: color-mix(in srgb, var(--brand) 90%, black);
  --accent-soft: color-mix(in srgb, var(--brand) 12%, white);
  --accent-soft-text: color-mix(in srgb, var(--brand) 62%, black);   /* text on --accent-soft */
  --accent-fg: #FFFFFF;  /* neutral: white on cypress; the dark blocks switch it to --night (ink on sage) */

  /* ---- status: each derives from its seed ---- */
  --success: var(--seed-success);  --success-soft: color-mix(in srgb, var(--seed-success) 12%, white);  --success-text: color-mix(in srgb, var(--seed-success) 88%, black);
  --warning: var(--seed-warning);  --warning-soft: color-mix(in srgb, var(--seed-warning) 14%, white);  --warning-text: color-mix(in srgb, var(--seed-warning) 78%, black);
  --danger:  var(--seed-danger);   --danger-soft:  color-mix(in srgb, var(--seed-danger) 10%, white);   --danger-text:  color-mix(in srgb, var(--seed-danger) 90%, black);
  --info:    var(--seed-info);     --info-soft:    color-mix(in srgb, var(--seed-info) 12%, white);     --info-text:    color-mix(in srgb, var(--seed-info) 78%, black);

  /* text on a filled status colour (buttons, loud chips) and the hover shade of that fill */
  --on-success: #FFFFFF;  /* neutral */
  --success-hover: color-mix(in srgb, var(--seed-success) 80%, black);
  --on-danger: #FFFFFF;  /* neutral */
  --danger-hover: color-mix(in srgb, var(--seed-danger) 80%, black);

  --focus: var(--brand);
  --overlay: color-mix(in srgb, var(--night) 45%, transparent);
  --glass-highlight: color-mix(in srgb, white 35%, transparent);   /* 1 px top edge of the glass header and floating chrome */

  /* ---- elevation (light: shadows; dark: empty shadows (valid inside a box-shadow list), surfaces step up and borders carry it) ---- */
  --shadow-sm: 0 1px 2px color-mix(in srgb, var(--night) 5%, transparent);
  --shadow-md: 0 10px 30px color-mix(in srgb, var(--night) 8%, transparent);
  --shadow-lg: 0 22px 50px color-mix(in srgb, var(--night) 12%, transparent);
  --elev-border: transparent;          /* raised surfaces add `border: 1px solid var(--elev-border)` */

  /* ---- mastery ramp (IMAT topics, heat calendar): five steps of --brand into the surface, square cells ---- */
  --m1: color-mix(in srgb, var(--brand) 12%, var(--surface));
  --m2: color-mix(in srgb, var(--brand) 35%, var(--surface));
  --m3: color-mix(in srgb, var(--brand) 60%, var(--surface));
  --m4: color-mix(in srgb, var(--brand) 80%, var(--surface));
  --m5: var(--brand);

  /* ---- chart palette: five categorical slots, one per IMAT section (fixed order); slots 2 to 5 are deliberately not brand ---- */
  --chart-1: var(--brand);
  --chart-2: #1BAF7A;  /* categorical */
  --chart-3: #EDA100;  /* categorical */
  --chart-4: #2A78D6;  /* categorical */
  --chart-5: #E34948;  /* categorical */

  /* ---- always-dark surfaces (login aside, next-step card, demo banner, footer, tour spotlight, file viewer):
         theme-independent on purpose, all pass 4.5:1 on --night ---- */
  --on-night: color-mix(in srgb, var(--brand-dark) var(--neutral-hue-mix-dark), #F7F7F7);  /* neutral */
  --on-night-muted: color-mix(in srgb, var(--brand-dark) var(--neutral-hue-mix-dark), #AAAAAA);  /* neutral */
  --on-night-accent: var(--brand-dark);   /* sage on ink, the same in both themes (10:1) */
  --danger-night: color-mix(in srgb, var(--seed-danger) 80%, black);   /* urgent next-step card; --on-night text is 7.6:1 on it */
  --overlay-strong: color-mix(in srgb, var(--night) 78%, transparent);   /* document viewer backdrop */

  /* ---- light island: the IMAT "Watch it" figures keep real black and white squares in either theme ---- */
  --island-bg: #FFFFFF;  /* neutral */
  --island-fg: color-mix(in srgb, var(--brand-light) var(--neutral-hue-mix), #101010);  /* neutral */
  --island-muted: color-mix(in srgb, var(--brand-light) var(--neutral-hue-mix), #5C5C5C);  /* neutral */
  --island-border: color-mix(in srgb, var(--brand-light) var(--neutral-hue-mix), #EAEAEA);  /* neutral */
  --island-accent: var(--brand-light);   /* cypress text and rings on the white island, in either theme */
  --island-ok: var(--seed-success);
  --island-bad: var(--seed-danger);

  /* ---- type (size / line-height, px) ---- */
  --fs-meta: 12px;     --lh-meta: 16px;
  --fs-dense: 13px;    --lh-dense: 18px;
  --fs-ui: 14px;       --lh-ui: 20px;
  --fs-read: 16px;     --lh-read: 24px;
  --fs-section: 20px;  --lh-section: 26px;
  --fs-page: 24px;     --lh-page: 30px;
  --fs-hero-num: 32px; --lh-hero-num: 36px;
  --fs-hero: 44px;     --lh-hero: 48px;

  /* ---- space (4 px base), layout ---- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 24px; --space-6: 32px; --space-7: 48px;
  --gutter: 24px;
  --content-max: 1200px;
  --reading-max: 760px;
  --dialog-w: 520px;
  --palette-w: 600px;
  --panel-w: 440px;

  /* ---- motion (transform and opacity only; reduced motion zeroes the durations) ---- */
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 260ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}
@media (min-width: 1281px) { :root { --gutter: 32px; } }

/* ---- the native controls follow an explicit choice, not only the device ---- */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* ---- legacy names used by style.css, portal.css and the page sheets, aliased to the new tokens ----
   Plain :root: tokens.css loads after style.css, so these win by order (portal.css no longer redefines them).
   Delete a line here when no rule references the name any more (tools/check_tokens.py counts them).
   --night, --white, --black, --line-dark, --radius, --header-h and the font stacks stay in style.css. */
:root {
  --ink: var(--fg);
  --ink-soft: var(--fg-muted);
  --violet: var(--accent);
  --violet-dark: var(--accent-hover);
  --violet-light: var(--accent-text);
  --violet-soft: var(--accent-soft);
  --gray-bg: var(--bg);
  --paper: var(--surface);
  --line: var(--border);
  --gold: var(--warning);
  --gold-light: var(--warning-soft);
  --ok: var(--success);
  --warn: var(--warning);
}


/* ---- dark theme: the device is dark and the person did not lock light ---- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* keep both dark blocks identical (the media query one and the [data-theme="dark"] one) */
    --brand: var(--brand-dark);
    --bg: var(--night);
    --bg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #060606);  /* neutral */
    --surface: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #0C0C0C);  /* neutral */
    --surface-2: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #151515);  /* neutral */
    --surface-raised: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #151515);  /* neutral */
    --border: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #232323);  /* neutral */
    --border-strong: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #3A3A3A);  /* neutral */
    --fg: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #F7F7F7);  /* neutral */
    --fg-muted: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #AAAAAA);  /* neutral */
    --fg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #8E8E8E);  /* neutral */
    --accent-hover: color-mix(in srgb, var(--brand) 88%, white);
    --accent-text: color-mix(in srgb, var(--brand) 85%, white);
    --accent-soft: color-mix(in srgb, var(--brand) 15%, var(--surface));
    --accent-soft-text: color-mix(in srgb, var(--brand) 60%, white);
    --accent-fg: var(--night);   /* ink on sage (white on sage fails contrast) */
    --success: var(--seed-success-dark);  --success-soft: color-mix(in srgb, var(--seed-success-dark) 22%, var(--surface));  --success-text: color-mix(in srgb, var(--seed-success-dark) 65%, white);
    --warning: var(--seed-warning-dark);  --warning-soft: color-mix(in srgb, var(--seed-warning-dark) 22%, var(--surface));  --warning-text: color-mix(in srgb, var(--seed-warning-dark) 65%, white);
    --danger:  var(--seed-danger-dark);   --danger-soft:  color-mix(in srgb, var(--seed-danger-dark) 22%, var(--surface));   --danger-text:  color-mix(in srgb, var(--seed-danger-dark) 65%, white);
    --info:    var(--seed-info-dark);     --info-soft:    color-mix(in srgb, var(--seed-info-dark) 22%, var(--surface));     --info-text:    color-mix(in srgb, var(--seed-info-dark) 65%, white);
    --on-success: var(--night);  --success-hover: color-mix(in srgb, var(--success) 85%, white);
    --on-danger:  var(--night);  --danger-hover:  color-mix(in srgb, var(--danger) 85%, white);
    --glass-highlight: color-mix(in srgb, white 8%, transparent);
    --focus: var(--accent-text);
    --overlay: color-mix(in srgb, black 60%, transparent);
    --shadow-sm: 0 0 0 0 transparent;
    --shadow-md: 0 0 0 0 transparent;
    --shadow-lg: 0 0 0 0 transparent;
    --elev-border: var(--border-strong);
    --m1: color-mix(in srgb, var(--brand) 15%, var(--surface));
    --m2: color-mix(in srgb, var(--brand) 37%, var(--surface));
    --m3: color-mix(in srgb, var(--brand) 60%, var(--surface));
    --m4: color-mix(in srgb, var(--brand) 82%, var(--surface));
    --m5: color-mix(in srgb, var(--brand) 90%, white);
    --chart-1: color-mix(in srgb, var(--brand) 92%, white);
    --chart-2: #199E70;  /* categorical */
    --chart-3: #C98500;  /* categorical */
    --chart-4: #3987E5;  /* categorical */
    --chart-5: #E66767;  /* categorical */
    /* the amber legacy name is used as text on always-dark bars, so it brightens instead of darkening */
    --gold-light: var(--warning-text);
  }
}
:root[data-theme="dark"] {
  /* keep both dark blocks identical (the media query one and the [data-theme="dark"] one) */
  --brand: var(--brand-dark);
  --bg: var(--night);
  --bg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #060606);  /* neutral */
  --surface: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #0C0C0C);  /* neutral */
  --surface-2: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #151515);  /* neutral */
  --surface-raised: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #151515);  /* neutral */
  --border: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #232323);  /* neutral */
  --border-strong: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #3A3A3A);  /* neutral */
  --fg: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #F7F7F7);  /* neutral */
  --fg-muted: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #AAAAAA);  /* neutral */
  --fg-subtle: color-mix(in srgb, var(--brand) var(--neutral-hue-mix-dark), #8E8E8E);  /* neutral */
  --accent-hover: color-mix(in srgb, var(--brand) 88%, white);
  --accent-text: color-mix(in srgb, var(--brand) 85%, white);
  --accent-soft: color-mix(in srgb, var(--brand) 15%, var(--surface));
  --accent-soft-text: color-mix(in srgb, var(--brand) 60%, white);
  --accent-fg: var(--night);   /* ink on sage (white on sage fails contrast) */
  --success: var(--seed-success-dark);  --success-soft: color-mix(in srgb, var(--seed-success-dark) 22%, var(--surface));  --success-text: color-mix(in srgb, var(--seed-success-dark) 65%, white);
  --warning: var(--seed-warning-dark);  --warning-soft: color-mix(in srgb, var(--seed-warning-dark) 22%, var(--surface));  --warning-text: color-mix(in srgb, var(--seed-warning-dark) 65%, white);
  --danger:  var(--seed-danger-dark);   --danger-soft:  color-mix(in srgb, var(--seed-danger-dark) 22%, var(--surface));   --danger-text:  color-mix(in srgb, var(--seed-danger-dark) 65%, white);
  --info:    var(--seed-info-dark);     --info-soft:    color-mix(in srgb, var(--seed-info-dark) 22%, var(--surface));     --info-text:    color-mix(in srgb, var(--seed-info-dark) 65%, white);
  --on-success: var(--night);  --success-hover: color-mix(in srgb, var(--success) 85%, white);
  --on-danger:  var(--night);  --danger-hover:  color-mix(in srgb, var(--danger) 85%, white);
  --glass-highlight: color-mix(in srgb, white 8%, transparent);
  --focus: var(--accent-text);
  --overlay: color-mix(in srgb, black 60%, transparent);
  --shadow-sm: 0 0 0 0 transparent;
  --shadow-md: 0 0 0 0 transparent;
  --shadow-lg: 0 0 0 0 transparent;
  --elev-border: var(--border-strong);
  --m1: color-mix(in srgb, var(--brand) 15%, var(--surface));
  --m2: color-mix(in srgb, var(--brand) 37%, var(--surface));
  --m3: color-mix(in srgb, var(--brand) 60%, var(--surface));
  --m4: color-mix(in srgb, var(--brand) 82%, var(--surface));
  --m5: color-mix(in srgb, var(--brand) 90%, white);
  --chart-1: color-mix(in srgb, var(--brand) 92%, white);
  --chart-2: #199E70;  /* categorical */
  --chart-3: #C98500;  /* categorical */
  --chart-4: #3987E5;  /* categorical */
  --chart-5: #E66767;  /* categorical */
  /* the amber legacy name is used as text on always-dark bars, so it brightens instead of darkening */
  --gold-light: var(--warning-text);
}


/* ---- reduced motion: the three durations become zero, so everything built on them goes static ---- */
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0ms; --dur: 0ms; --dur-slow: 0ms; }
  :root.theming, :root.theming * { transition: none !important; }
}

/* ---- theme switch crossfade (theme-init.js adds .theming to <html> for 260 ms) ---- */
:root.theming, :root.theming * { transition: background-color 200ms, color 200ms, border-color 200ms; }

/* ---- the theme button in the portal header (inserted by theme-toggle.js) ---- */
.theme-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 32px; height: 32px; padding: 0; margin: 0;
  background: transparent; color: var(--fg-muted);
  border: 1px solid var(--border-strong); border-radius: 0; cursor: pointer;
  transition: background-color var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.theme-btn:hover { background: var(--surface-2); color: var(--fg); }
.theme-btn:active { background: var(--bg-subtle); }
.theme-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.theme-btn svg { width: 20px; height: 20px; display: block; fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: square; stroke-linejoin: miter; }
