/*! ===========================================================================
 *  Alpéia — design tokens  v1.0.0
 *  Produced by kanban task t_540564a4, from the founding charter
 *  "Charte graphique Alpéia" v1.0.0 (task t_4711df44).
 *
 *  This is the ONLY file of the system allowed to contain literal colour
 *  values. base.css, components.css and index.html consume tokens only.
 *
 *  Three layers, read in this order:
 *    1. @font-face   — the three self-hosted WOFF2 (charter R-T8: no
 *                      third-party font CDN, Swiss nLPD / GDPR).
 *    2. Primitives   — the charter's OWN token names (--alpeia-*), copied
 *                      verbatim from kit/tokens/alpeia-tokens.css. Never edit
 *                      these by hand: regenerate them from the charter.
 *    3. Semantics    — English layer used by every stylesheet and component
 *                      (--color-*, --space-*, --text-*, …). Each semantic
 *                      token points at a charter primitive, so no colour,
 *                      size or shadow is ever invented (charter R-C1…R-C4).
 *
 *  Dark theme: the same tokens, re-encoded — no new colour (charter §3.5).
 *  Two blocks are provided: [data-theme="dark"] for the JS switch used by
 *  index.html, and a prefers-color-scheme fallback for JS-less readers.
 * =========================================================================== */

/* --- Layer 1 — self-hosted fonts -----------------------------------------
   Same declarations as kit/tokens/alpeia-fontes.css; only the path differs
   (fonts/ sits next to this file). Keep the OFL licences shipped with the
   WOFF2 files (see fonts/OFL-*.txt). */
@font-face {
  font-family: "Inter";
  src: url("fonts/Inter-var.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("fonts/SourceSerif4-var.woff2") format("woff2-variations");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/JetBrainsMono-var.woff2") format("woff2-variations");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* --- Layer 2 — primitives (charter token names, verbatim) -----------------
   Source: kit/tokens/alpeia-tokens.css v1.0.0. The charter states (§3.4)
   that these names are "the only authorised way to name a colour in code";
   they are therefore kept as-is, in French, and are the single source of
   truth for every value below. */
:root {
  /* Brand and neutral colours — the 30 official values (charter §3.2) */
  --alpeia-bleu-050: #EEF5FA;
  --alpeia-bleu-100: #DCE9F4;
  --alpeia-bleu-200: #BBD6E9;
  --alpeia-bleu-600: #2C7CB0;
  --alpeia-bleu-700: #12507A;
  --alpeia-bleu-800: #0C3C5E;   /* brand primary */
  --alpeia-bleu-850: #0D3252;
  --alpeia-bleu-900: #0A2A42;
  --alpeia-vert-050: #EAF3EE;
  --alpeia-vert-200: #BCDDCB;
  --alpeia-vert-600: #1F6B4C;
  --alpeia-vert-800: #14402F;   /* brand secondary */
  --alpeia-or-050: #FBF3E2;
  --alpeia-or-300: #E0BE7E;
  --alpeia-or-600: #A8761C;
  --alpeia-or-700: #8A5F12;
  --alpeia-granit-000: #FFFFFF;
  --alpeia-granit-050: #F6F8FA;
  --alpeia-granit-100: #EAEFF3;
  --alpeia-granit-200: #D3DBE1;
  --alpeia-granit-300: #AEBAC3;
  --alpeia-granit-400: #7C8A95;
  --alpeia-granit-500: #5C6A75;
  --alpeia-granit-600: #414E58;
  --alpeia-granit-700: #2B353D;
  --alpeia-granit-800: #191F25;   /* ink */
  --alpeia-granit-900: #0E1317;
  --alpeia-brique-050: #FBECEA;
  --alpeia-brique-300: #E9988F;
  --alpeia-brique-600: #A32A22;

  /* Semantic colours (light theme) — charter §3.4 */
  --alpeia-fond-page: #F6F8FA;
  --alpeia-fond-surface: #FFFFFF;
  --alpeia-fond-alterne: #EAEFF3;
  --alpeia-bordure-decorative: #D3DBE1;
  --alpeia-bordure-controle: #7C8A95;
  --alpeia-texte-courant: #191F25;
  --alpeia-texte-secondaire: #5C6A75;
  --alpeia-texte-attenue: #7C8A95;
  --alpeia-marque-primaire: #0C3C5E;
  --alpeia-marque-secondaire: #14402F;
  --alpeia-accent: #8A5F12;
  --alpeia-accent-graphique: #A8761C;
  --alpeia-lien: #12507A;
  --alpeia-succes: #1F6B4C;
  --alpeia-avertissement: #8A5F12;
  --alpeia-erreur: #A32A22;
  --alpeia-anneau-focus: #2C7CB0;

  /* Typography — charter §4.1 and §4.2 */
  --alpeia-famille-titre: "Source Serif 4", Georgia, "Times New Roman", serif;
  --alpeia-famille-texte: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --alpeia-famille-code: "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  --alpeia-taille-micro: 0.75rem;    /* 12 px — legal mentions only */
  --alpeia-taille-petit: 0.875rem;   /* 14 px — captions and metadata */
  --alpeia-taille-base: 1rem;        /* 16 px — absolute minimum */
  --alpeia-taille-moyen: 1.125rem;   /* 18 px — lead paragraph */
  --alpeia-taille-h4: 1.25rem;
  --alpeia-taille-h3: 1.5rem;
  --alpeia-taille-h2: 2rem;
  --alpeia-taille-h1: 2.5rem;
  --alpeia-taille-affiche: 3.5rem;
  --alpeia-interligne-texte: 1.6;
  --alpeia-interligne-titre: 1.2;
  --alpeia-interligne-affiche: 1.08;
  --alpeia-interlettrage-majuscules: 0.06em;
  --alpeia-largeur-lecture: 70ch;
  --alpeia-graisse-texte: 400;
  --alpeia-graisse-accent: 500;
  --alpeia-graisse-titre: 600;
  --alpeia-graisse-fort: 700;

  /* Spacing — 4 px grid, charter §7.2 */
  --alpeia-espace-1: 0.25rem;
  --alpeia-espace-2: 0.5rem;
  --alpeia-espace-3: 0.75rem;
  --alpeia-espace-4: 1rem;
  --alpeia-espace-6: 1.5rem;
  --alpeia-espace-8: 2rem;
  --alpeia-espace-12: 3rem;
  --alpeia-espace-16: 4rem;
  --alpeia-espace-24: 6rem;

  /* Radii, shadows, motion, grid — charter §7.1 and §7.3 */
  --alpeia-rayon-none: 0;
  --alpeia-rayon-sm: 2px;
  --alpeia-rayon-md: 4px;
  --alpeia-rayon-lg: 8px;
  --alpeia-rayon-pilule: 999px;
  --alpeia-ombre-sm: 0 1px 2px rgba(25, 31, 37, 0.06), 0 1px 1px rgba(25, 31, 37, 0.04);
  --alpeia-ombre-md: 0 2px 6px rgba(25, 31, 37, 0.08), 0 1px 2px rgba(25, 31, 37, 0.06);
  --alpeia-ombre-lg: 0 8px 24px rgba(25, 31, 37, 0.10), 0 2px 6px rgba(25, 31, 37, 0.06);
  --alpeia-ombre-focus: 0 0 0 2px var(--alpeia-fond-page), 0 0 0 4px var(--alpeia-anneau-focus);
  --alpeia-ombre-focus-sur-aplat: 0 0 0 2px var(--alpeia-marque-primaire), 0 0 0 4px var(--alpeia-granit-000);
  --alpeia-duree-rapide: 120ms;
  --alpeia-duree-standard: 200ms;
  --alpeia-duree-lent: 320ms;
  --alpeia-courbe: cubic-bezier(0.2, 0, 0, 1);
  --alpeia-largeur-max-contenu: 1200px;
  --alpeia-gouttiere: 1.5rem;
  --alpeia-colonnes: 12;
  --alpeia-bp-sm: 640px;
  --alpeia-bp-md: 900px;
  --alpeia-bp-lg: 1200px;
}

/* --- Layer 3 — semantics (English, used by base.css / components.css) -----
   Every value is an alias of a charter token: renaming a charter token here
   is the only edit needed. Sizes and rhythm are aliased as well, so a
   component never hard-codes a colour or a text size (charter §8.1). */
:root {
  /* Surfaces and text */
  --color-bg: var(--alpeia-fond-page);
  --color-surface: var(--alpeia-fond-surface);
  --color-surface-alt: var(--alpeia-fond-alterne);
  --color-text: var(--alpeia-texte-courant);
  --color-text-muted: var(--alpeia-texte-secondaire);
  /* Note: the charter's "texte atténué" (granit-400, 3.54:1) is AA for
     large text only. No component uses it below 24 px, so the semantic
     layer exposes no token for it; --alpeia-texte-attenue stays available
     for a display-size use case (see README.md, "Known limits"). */
  --color-border: var(--alpeia-bordure-decorative);   /* decorative: exempt from 3:1 */
  --color-border-control: var(--alpeia-bordure-controle);
  --color-border-disabled: var(--alpeia-granit-300);
  --color-focus: var(--alpeia-anneau-focus);   /* focus ring, charter R-A4 */
  /* Field surface. Light: white on the page. Dark: the page colour itself,
     because the charter's dark control border (bleu-600) only reaches 3:1
     against the page (3.24:1) and not against the elevated surface
     (2.52:1). Keeps WCAG 1.4.11 satisfied in both themes. */
  --color-field-bg: var(--alpeia-fond-surface);

  /* Brand and accents. Interactive states stay inside the palette: the
     primary aplat steps one family shade darker (light) or lighter (dark),
     so hover and active are perceivable in both themes without leaving the
     30 official values. */
  --color-brand: var(--alpeia-marque-primaire);
  --color-brand-hover: var(--alpeia-bleu-850);
  --color-brand-active: var(--alpeia-bleu-900);
  --color-brand-alt: var(--alpeia-marque-secondaire);
  --color-accent: var(--alpeia-accent);
  --color-accent-graphic: var(--alpeia-accent-graphique); /* graphics only, never running text */
  --color-link: var(--alpeia-lien);

  /* States */
  --color-success: var(--alpeia-succes);
  --color-warning: var(--alpeia-avertissement);
  --color-danger: var(--alpeia-erreur);
  --color-info: var(--alpeia-bleu-700);               /* charter §8.4, "note" box */

  /* Text selection. Light: bleu-200 block, bleu-800 ink. */
  --color-selection-surface: var(--alpeia-bleu-200);
  --color-selection-text: var(--alpeia-bleu-800);   /* 7.63:1 in both themes */

  /* Text on the brand aplat. The brand is re-encoded in the dark theme
     (see the brand patch below), so this ink flips with it. */
  --color-on-brand: var(--alpeia-granit-000);

  /* State surfaces. Light: the pale 050 tint of the state family.
     Dark: the elevated surface (bleu-850) — no new hue. */
  --color-info-surface: var(--alpeia-bleu-050);
  --color-success-surface: var(--alpeia-vert-050);
  --color-warning-surface: var(--alpeia-or-050);
  --color-danger-surface: var(--alpeia-brique-050);

  /* Typography */
  --font-heading: var(--alpeia-famille-titre);
  --font-body: var(--alpeia-famille-texte);
  --font-mono: var(--alpeia-famille-code);
  --text-display: var(--alpeia-taille-affiche);
  --text-h1: var(--alpeia-taille-h1);
  --text-h2: var(--alpeia-taille-h2);
  --text-h3: var(--alpeia-taille-h3);
  --text-h4: var(--alpeia-taille-h4);
  --text-lead: var(--alpeia-taille-moyen);
  --text-base: var(--alpeia-taille-base);
  --text-sm: var(--alpeia-taille-petit);
  --text-xs: var(--alpeia-taille-micro);
  --leading-body: var(--alpeia-interligne-texte);
  --leading-heading: var(--alpeia-interligne-titre);
  --leading-display: var(--alpeia-interligne-affiche);
  --tracking-caps: var(--alpeia-interlettrage-majuscules);
  --weight-body: var(--alpeia-graisse-texte);
  --weight-accent: var(--alpeia-graisse-accent);
  --weight-heading: var(--alpeia-graisse-titre);
  --weight-strong: var(--alpeia-graisse-fort);
  --measure: var(--alpeia-largeur-lecture);

  /* Spacing scale */
  --space-0: 0;
  --space-1: var(--alpeia-espace-1);
  --space-2: var(--alpeia-espace-2);
  --space-3: var(--alpeia-espace-3);
  --space-4: var(--alpeia-espace-4);
  --space-6: var(--alpeia-espace-6);
  --space-8: var(--alpeia-espace-8);
  --space-12: var(--alpeia-espace-12);
  --space-16: var(--alpeia-espace-16);
  --space-24: var(--alpeia-espace-24);

  /* Radii and elevation */
  --radius-none: var(--alpeia-rayon-none);
  --radius-sm: var(--alpeia-rayon-sm);
  --radius-md: var(--alpeia-rayon-md);
  --radius-lg: var(--alpeia-rayon-lg);
  --radius-pill: var(--alpeia-rayon-pilule);
  --shadow-sm: var(--alpeia-ombre-sm);
  --shadow-md: var(--alpeia-ombre-md);
  --shadow-lg: var(--alpeia-ombre-lg);
  --shadow-focus: var(--alpeia-ombre-focus);

  /* Motion */
  --duration-fast: var(--alpeia-duree-rapide);
  --duration-base: var(--alpeia-duree-standard);
  --duration-slow: var(--alpeia-duree-lent);
  --ease-standard: var(--alpeia-courbe);

  /* Layout. The four "derived" values below are not in the charter's token
     file; they encode charter §8.1 (header heights, logo width) and R-A4 /
     R-A5 (focus offset, 44 px target). Documented as derived in README.md. */
  --layout-max-width: var(--alpeia-largeur-max-contenu);
  --layout-gutter: var(--alpeia-gouttiere);
  --layout-columns: var(--alpeia-colonnes);
  --bp-sm: var(--alpeia-bp-sm);
  --bp-md: var(--alpeia-bp-md);
  --bp-lg: var(--alpeia-bp-lg);
  --header-height: 64px;            /* derived — charter §8.1, mobile */
  --header-height-desktop: 88px;    /* derived — charter §8.1, desktop */
  --logo-width: 120px;              /* derived — charter §8.2 and annex H */
  --control-height: 44px;           /* derived — charter R-A5 */
  --table-min-width: 34rem;         /* derived — keeps data columns legible
                                       on a phone; the table then scrolls
                                       inside its own container (charter R-A10
                                       allows a scrollable two-dimensional
                                       region) */
  --focus-offset: 2px;              /* derived — charter R-A4 */
}

/* --- Dark theme ----------------------------------------------------------
   Two blocks: the [data-theme="dark"] switch (driven by the 3-line script
   in index.html) and a prefers-color-scheme fallback for JS-less readers.
   Both carry the same values, so the two paths cannot drift. */
[data-theme="dark"] {
  --alpeia-fond-page: #0A2A42;
  --alpeia-fond-surface: #0C3C5E;
  --alpeia-fond-alterne: #0D3252;
  --alpeia-bordure-decorative: rgba(44, 124, 176, 0.45);
  --alpeia-bordure-controle: #2C7CB0;
  --alpeia-texte-courant: #F6F8FA;
  --alpeia-texte-secondaire: #AEBAC3;
  --alpeia-texte-attenue: #7C8A95;
  --alpeia-lien: #BBD6E9;
  --alpeia-accent: #E0BE7E;
  --alpeia-accent-graphique: #A8761C;
  --alpeia-succes: #BCDDCB;
  --alpeia-avertissement: #E0BE7E;
  --alpeia-erreur: #E9988F;
  --alpeia-anneau-focus: #FFFFFF;

  /* Brand patch. Charter §3.4 lists dark values for the two brand tokens
     below (marque-primaire -> bleu-200, marque-secondaire -> vert-200), but
     the shipped token file omits them from its dark blocks ("le mode sombre
     inverse l'encodage", §3.5). Without them, headings and primary surfaces
     would keep the light-theme dark blue on the dark background (1.2:1).
     The values below are the charter's, taken verbatim from its §3.4 table. */
  --alpeia-marque-primaire: var(--alpeia-bleu-200);
  --alpeia-marque-secondaire: var(--alpeia-vert-200);

  /* Dark-only overrides of the semantic layer */
  --color-field-bg: var(--alpeia-bleu-900);
  --color-brand-hover: var(--alpeia-bleu-100);
  --color-brand-active: var(--alpeia-bleu-050);
  --color-on-brand: var(--alpeia-bleu-800);   /* dark text on the light brand aplat */
  --color-info: var(--alpeia-bleu-200);
  --color-info-surface: var(--alpeia-bleu-850);
  --color-success-surface: var(--alpeia-bleu-850);
  --color-warning-surface: var(--alpeia-bleu-850);
  --color-danger-surface: var(--alpeia-bleu-850);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --alpeia-fond-page: #0A2A42;
    --alpeia-fond-surface: #0C3C5E;
    --alpeia-fond-alterne: #0D3252;
    --alpeia-bordure-decorative: rgba(44, 124, 176, 0.45);
    --alpeia-bordure-controle: #2C7CB0;
    --alpeia-texte-courant: #F6F8FA;
    --alpeia-texte-secondaire: #AEBAC3;
    --alpeia-texte-attenue: #7C8A95;
    --alpeia-lien: #BBD6E9;
    --alpeia-accent: #E0BE7E;
    --alpeia-accent-graphique: #A8761C;
    --alpeia-succes: #BCDDCB;
    --alpeia-avertissement: #E0BE7E;
    --alpeia-erreur: #E9988F;
    --alpeia-anneau-focus: #FFFFFF;
    --alpeia-marque-primaire: var(--alpeia-bleu-200);
    --alpeia-marque-secondaire: var(--alpeia-vert-200);
    --color-field-bg: var(--alpeia-bleu-900);
    --color-brand-hover: var(--alpeia-bleu-100);
    --color-brand-active: var(--alpeia-bleu-050);
    --color-on-brand: var(--alpeia-bleu-800);
    --color-info: var(--alpeia-bleu-200);
    --color-info-surface: var(--alpeia-bleu-850);
    --color-success-surface: var(--alpeia-bleu-850);
    --color-warning-surface: var(--alpeia-bleu-850);
    --color-danger-surface: var(--alpeia-bleu-850);
  }
}
