/* SOTIS PJ2 light theme tokens: "Bureau et feuille, version données".
   The only stylesheet allowed to hold colour literals, font stacks and raw scale values
   (gate: frontend/tests/test_design_system.py).
   Tier 0: private primitives (--_*), read only inside this file.
   Tier 1: public role tokens, written as var(--_*).
   Tier 2: layout, z-index and motion.
   The chart section is mirrored in sotis_pj2_backend/analysis/chart_theme.py and pinned by tests
   on both sides: change a value on both sides. Always light: no prefers-color-scheme block
   anywhere.

   Colour decisions, all checked with the dataviz palette validator:
   - numbers printed inside heatmap and confusion-matrix cells use --ink-on-data (#000000) or
     --ink-on-data-inverse (text_on: black above relative luminance 0.179);
   - one colour, one meaning per screen: bleu canard means "held-out data and the model's
     output" (validation, test, predictions, posterior), training data takes its own hue
     (orge), the reference role is ink so it clears every chromatic role, and observed values
     and priors take a stone grey; zones Q1 to Q4 carry no colour (words in tables, labelled
     guides in charts);
   - the diverging arms are balanced (OKLCH L 0.44 at both poles, 0.70 at both quarter stops);
   - text never wears a series colour. */

@font-face {
  font-family: "Red Hat Text";
  src: url("../fonts/red-hat-text.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: block;
}

:root {
  /* ---------- tier 0: primitives (private) ---------- */
  --_white: #ffffff;
  --_black: #000000;
  --_graphite-25: #f3f6f9;
  --_graphite-50: #edf1f5;
  --_graphite-75: #eaeff4;
  --_graphite-90: #e8edf2;
  --_graphite-100: #e3e9f0;
  --_graphite-150: #dde3ea;
  --_graphite-200: #c3ccd6;
  --_graphite-250: #b3bcc6;
  --_graphite-350: #8a94a0;
  --_graphite-400: #77838f;
  --_graphite-500: #566170;
  --_graphite-600: #3d4856;
  --_graphite-800: #1f2933;
  --_stone-500: #57544e;
  --_violet-50: #efeeff;
  --_violet-200: #bbb6ef;
  --_violet-500: #6441c9;
  --_violet-600: #5835b5;
  --_violet-700: #5531b2;
  --_yellow-300: #f7e64d;
  --_green-50: #e8f4ec;
  --_green-200: #a7d3b6;
  --_green-500: #2b8048;
  --_green-700: #1b6b3f;
  --_amber-50: #fdf3dc;
  --_amber-200: #ecc77f;
  --_amber-500: #b8740b;
  --_amber-700: #8a5300;
  --_red-50: #fdecea;
  --_red-200: #f0aba5;
  --_red-500: #c8322b;
  --_red-700: #b42318;
  --_red-800: #9a1f15;
  --_navy-50: #ebf3ff;
  --_navy-500: #3b6eb9;
  --_navy-700: #235193;
  --_cyan-50: #e9f5f7;
  --_cyan-500: #268899;
  --_cyan-700: #026771;
  --_mauve-50: #f8eff9;
  --_mauve-500: #a166aa;
  --_mauve-700: #86528e;
  --_wine-50: #f8eef2;
  --_wine-500: #aa3f72;
  --_wine-700: #7c234f;
  --_copper-50: #f9ede4;
  --_copper-500: #a3592b;
  --_copper-700: #7d4220;
  --_petrol-50: #e3f1f7;
  --_petrol-500: #00668f;
  --_petrol-700: #00506f;
  --_teal-100: #e2f9f6;
  --_teal-150: #e2f3f1;
  --_teal-200: #b3ede5;
  --_teal-300: #6fd2c7;
  --_teal-400: #27b5a9;
  --_teal-500: #0c998e;
  --_teal-600: #097e75;
  --_teal-700: #03655d;
  --_barley-500: #a19507;
  --_orange-300: #e97c4a;
  --_orange-500: #e26728;
  --_orange-600: #c05319;
  --_orange-700: #86370c;
  --_azure-300: #5aa3ec;
  --_azure-500: #2985d7;
  --_azure-600: #116bb5;
  --_azure-700: #085491;
  --_plum-50: #f6ebf2;
  --_plum-500: #a2397f;
  --_olive-500: #7a8c20;
  --_pink-500: #cf4a86;

  /* ---------- tier 1: roles ---------- */
  /* surfaces */
  --canvas: var(--_graphite-50);
  --surface: var(--_white);
  --surface-sunken: var(--_graphite-25);
  --surface-raised: var(--_white);
  --surface-hover: var(--_graphite-75);
  --surface-selected: var(--_graphite-100);
  --input-bg: var(--_white);
  --scrim: rgba(23, 31, 41, 0.42);

  /* lines */
  --line: var(--_graphite-150);
  --line-strong: var(--_graphite-200);
  --line-control: var(--_graphite-400);
  --focus-ring: var(--_violet-500);

  /* ink */
  --ink: var(--_graphite-800);
  --ink-2: var(--_graphite-600);
  --ink-3: var(--_graphite-500);
  --ink-disabled: var(--_graphite-350);
  --ink-on-accent: var(--_white);
  /* numbers printed inside a coloured data cell (heatmap, confusion matrix): text_on() picks
     --ink-on-data above relative luminance 0.179, --ink-on-data-inverse at or below
     (worst case 4.58:1 over both scales, swept at 1/400) */
  --ink-on-data: var(--_black);
  --ink-on-data-inverse: var(--_white);
  /* the opaque end of a fade mask (a mask reads alpha only; never painted as a colour) */
  --mask-opaque: var(--_black);

  /* accent: Sotis violet, for actions, focus and control state only */
  --accent: var(--_violet-500);
  --accent-hover: var(--_violet-700);
  --accent-ink: var(--_violet-600);
  --accent-soft: var(--_violet-50);
  --accent-line: var(--_violet-200);

  /* brand: the yellow appears once, in the logo */
  --brand-mark: var(--_graphite-800);
  --brand-spark: var(--_yellow-300);
  --brand-bar: var(--_white);

  /* status: state only, always with an icon and a word */
  --success: var(--_green-500);
  --success-ink: var(--_green-700);
  --success-soft: var(--_green-50);
  --success-line: var(--_green-200);
  --warning: var(--_amber-500);
  --warning-ink: var(--_amber-700);
  --warning-soft: var(--_amber-50);
  --warning-line: var(--_amber-200);
  --danger: var(--_red-500);
  --danger-ink: var(--_red-700);
  --danger-hover: var(--_red-800);          /* filled danger button on hover, white 8.14:1 */
  --danger-soft: var(--_red-50);
  --danger-line: var(--_red-200);
  --info: var(--_graphite-500);
  --info-ink: var(--_graphite-600);
  --info-soft: var(--_graphite-50);
  --info-line: var(--_graphite-200);

  /* dataset states: neutral facts, told apart by icon (funnel, arrows) and numbers */
  --state-filter: var(--_graphite-500);
  --state-filter-ink: var(--_graphite-600);
  --state-filter-soft: var(--_graphite-50);
  --state-transform: var(--_graphite-500);
  --state-transform-ink: var(--_graphite-600);
  --state-transform-soft: var(--_graphite-50);

  /* column types: glyph badges in the UI, never chart marks, neutral on Comparer and inside
     chart pickers (.types-neutral) */
  --type-integer: var(--_navy-500);
  --type-integer-ink: var(--_navy-700);
  --type-integer-soft: var(--_navy-50);
  --type-float: var(--_graphite-400);
  --type-float-ink: var(--_graphite-600);
  --type-float-soft: var(--_graphite-50);
  --type-categorical: var(--_wine-500);
  --type-categorical-ink: var(--_wine-700);
  --type-categorical-soft: var(--_wine-50);
  --type-datetime: var(--_cyan-500);
  --type-datetime-ink: var(--_cyan-700);
  --type-datetime-soft: var(--_cyan-50);
  --type-boolean: var(--_mauve-500);
  --type-boolean-ink: var(--_mauve-700);
  --type-boolean-soft: var(--_mauve-50);

  /* comparison identity: Comparer page only, always with letter badges */
  --compare-a: var(--_copper-500);
  --compare-a-ink: var(--_copper-700);
  --compare-a-soft: var(--_copper-50);
  --compare-b: var(--_petrol-500);
  --compare-b-ink: var(--_petrol-700);
  --compare-b-soft: var(--_petrol-50);

  /* the SQL step's preview (sql_step.js): what a query adds, changes and removes in the
     Table, on the status families (a fill, its mark, the ink of its sign); the legend names
     them, so colour is never the only carrier */
  --sql-added-soft: var(--_green-50);
  --sql-added-mark: var(--_green-500);
  --sql-added-ink: var(--_green-700);
  --sql-modified-soft: var(--_amber-50);
  --sql-modified-mark: var(--_amber-500);
  --sql-modified-ink: var(--_amber-700);
  --sql-removed-soft: var(--_red-50);
  --sql-removed-mark: var(--_red-500);
  --sql-removed-ink: var(--_red-700);

  /* SQL code (sql_highlight.js: the SQL drawer's editor, a SQL step's query in the
     preparation's drawer): text roles, read at 4.5:1 on the input, the surface and the
     sunken surface; quoted names keep --ink. The selection is translucent: the editor's
     textarea draws it over the coloured layer */
  --code-keyword: var(--_navy-700);
  --code-function: var(--_teal-700);
  --code-string: var(--_green-700);
  --code-number: var(--_copper-700);
  --code-comment: var(--_graphite-500);
  --code-selection: rgba(100, 65, 201, 0.18);

  /* charts (mirror: analysis/chart_theme.py) */
  --chart-surface: var(--_white);
  --chart-grid: var(--_graphite-90);
  --chart-axis: var(--_graphite-250);
  --chart-ink: var(--_graphite-600);
  --chart-ink-muted: var(--_graphite-500);
  --chart-context: var(--_graphite-350);
  --series-1: var(--_teal-500);
  --series-2: var(--_copper-500);
  --series-3: var(--_petrol-500);
  --series-4: var(--_orange-500);
  --series-5: var(--_plum-500);
  --series-6: var(--_olive-500);
  --series-7: var(--_azure-500);
  --series-8: var(--_pink-500);
  /* ML roles: one colour, one meaning on any screen (checked per screen with the validator) */
  --series-held-out: var(--_teal-500);        /* data the model did not train on, and its output */
  --series-predicted: var(--_teal-500);
  --series-validation: var(--_teal-500);
  --series-test: var(--_teal-500);
  --series-posterior: var(--_teal-500);
  --series-after: var(--_teal-500);
  --series-train: var(--_barley-500);         /* orge: the data the model learned from */
  --series-actual: var(--_stone-500);         /* observed values, where they are marks */
  --series-prior: var(--_stone-500);          /* dotted line + 12 % wash; never shares a screen with actual */
  --series-reference: var(--_graphite-800);   /* dashed lines, pinned scenario, the "before" state */
  --series-before: var(--_graphite-800);
  --series-density: var(--_graphite-800);     /* KDE on Distributions, where no reference line is drawn */
  --series-interval: var(--_teal-150);        /* swatch; charts draw alpha(series-predicted, .12) */
  --series-over: var(--_orange-600);          /* above a reference: over-estimation, r > 0, above the ROPE */
  --series-under: var(--_azure-600);          /* below a reference: under-estimation, r < 0, below the ROPE */
  --series-neutral: var(--_graphite-150);     /* the neutral middle of a three-part bar (inside the ROPE) */
  --series-outlier: var(--_plum-500);
  /* table cells marked by a check (10 % of --series-outlier on white): ink on it 12.71:1, the
     prune ring 5.28:1 */
  --series-outlier-wash: var(--_plum-50);
  --diverging-negative-strong: var(--_azure-700);
  --diverging-negative-light: var(--_azure-300);
  --diverging-negative: var(--_azure-600);
  --diverging-neutral: var(--_graphite-50);
  --diverging-positive: var(--_orange-600);
  --diverging-positive-light: var(--_orange-300);
  --diverging-positive-strong: var(--_orange-700);
  --sequential-100: var(--_teal-100);
  --sequential-200: var(--_teal-200);
  --sequential-300: var(--_teal-300);
  --sequential-400: var(--_teal-400);
  --sequential-500: var(--_teal-500);
  --sequential-600: var(--_teal-600);
  --sequential-700: var(--_teal-700);

  /* elevation and shape: cards are flat; the one sheet per page casts the paper shadow;
     floating layers cast shadow-2 / shadow-3 */
  --shadow-1: 0 1px 2px rgba(22, 34, 51, 0.08);
  --shadow-2: 0 2px 4px rgba(22, 34, 51, 0.06), 0 10px 24px -6px rgba(22, 34, 51, 0.16);
  --shadow-3: 0 4px 8px -2px rgba(22, 34, 51, 0.08), 0 24px 48px -12px rgba(22, 34, 51, 0.28);
  --shadow-paper: 0 1px 1px rgba(22, 34, 51, 0.05), 0 3px 6px -1px rgba(22, 34, 51, 0.06),
    0 12px 24px -6px rgba(22, 34, 51, 0.10), 0 28px 56px -18px rgba(22, 34, 51, 0.16);
  --radius-s: 6px;
  --radius-m: 10px;
  --radius-l: 16px;
  --radius-pill: 999px;

  /* type */
  --font-sans: "Red Hat Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --text-xs: 12.5px;
  --text-s: 13.5px;
  --text-table: 14px;
  --text-m: 15px;
  --text-l: 17px;
  --text-lead: 20px;
  --text-xl: 24px;
  --text-2xl: 44px;
  --text-tick: 12px;
  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-normal: 1.5;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-heading: 650;
  --weight-bold: 700;

  /* spacing (4 px base) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;

  /* ---------- tier 2: layout, z-index, motion ---------- */
  --rail-width: 232px;
  --rail-pad: 12px;
  --topbar-height: 56px;
  --subbar-height: 44px;
  --content-max: 1600px;
  --sticky-top: 0px;
  --appbar-scroll-away: 0px;
  --drawer-width: 400px;
  --drawer-width-wide: 560px;
  --notes-width: 380px;
  /* The wide notes drawer (#notesWideBtn): about 78 characters a line in a note. */
  --notes-width-wide: 560px;
  --control-height: 36px;
  --control-height-s: 30px;
  --control-height-l: 44px;
  --row-height: 36px;
  --table-col-min: 120px;
  --z-sticky: 10;
  --z-chrome: 50;
  --z-dropdown: 100;
  --z-notes: 900;
  --z-overlay: 1000;
  --z-modal: 1100;
  --z-toast: 1200;
  --z-tooltip: 1300;
  --duration-fast: 120ms;
  --duration-normal: 200ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);
}

/* Under 1100 px the rail becomes a top bar whose last row (the current section's views or
   steps) sticks; in-content sticky blocks sit under it. The bar scrolls away by the height of
   the rows above that last row, which depends on the breakpoint (critique: no hard-coded
   negative top): two rows (brand + sections) down to 780 px, three under it (the dataset chip
   drops to its own row). */
@media (max-width: 1099px) {
  :root {
    --sticky-top: var(--subbar-height);
    --appbar-scroll-away: calc(-1 * (var(--topbar-height) + var(--subbar-height)));
  }
}

@media (max-width: 779px) {
  :root {
    --appbar-scroll-away: calc(-1 * (var(--topbar-height) + var(--subbar-height) + var(--subbar-height)));
  }
}

@media (prefers-reduced-motion: reduce) {
  :root { --duration-fast: 0ms; --duration-normal: 0ms; }
}
