/* ==========================================================================
   DESIGN TOKENS & CSS CUSTOM PROPERTIES

   CE FICHIER EST LE VOCABULAIRE. Il n'y en a pas d'autre.

   Un nom qui n'est pas ici n'existe pas : en CSS, `var(--inconnu)` SANS repli
   rend la déclaration invalide au calcul et la propriété retombe à sa valeur
   initiale — un `background` devient `transparent`, un `border-top` devient
   `0px none`. Ce n'est pas « une teinte approximative », c'est la propriété qui
   disparaît (audit 2026-09-05, `CSS-01` : 104 déclarations mesurées ainsi).

   Écrire `var(--inconnu, #hex)` ne corrige rien : ça installe un SECOND
   vocabulaire (`--bg-primary`, `--color-primary`, `--border-color`,
   `--surface-2`, `--radius-md`…) dont le hex est la seule valeur réelle
   (`CSS-02` : 71 noms, 261 usages). Le jour où le socle change `--surface`, ces
   pages ne bougent pas — et personne ne le voit, parce qu'elles n'ont jamais
   l'air cassées.

   ⇒ On RENOMME vers le token existant ; on ne définit ici que ce qui manque
     vraiment. La table de correspondance « fantôme → canonique » vit dans
     `cli/css-token-aliases.php` (source unique, machine-lisible) et se lit avec
     `php cli/probe-css-tokens.php --aliases`. La liste des noms définis se sort
     avec `--print-tokens`.

   ⇒ Un repli n'est JAMAIS une seconde valeur. Quand le token existe, le repli
     ne peint rien (le token gagne toujours) mais il MENT : mesuré, 233 replis
     sur 348 contredisent leur token, dont six `--primary` dont aucun n'est le
     bleu marine de la marque (`CSS-03`). Le seul repli légitime est celui d'un
     document rendu SANS cette feuille (PDF, e-mail).

   Sonde : `php cli/probe-css-tokens.php` (fantômes, déclarations sans repli,
   replis menteurs, par app), branchée dans `ops/nightly-probes.sh`.
   ========================================================================== */

:root {
  /* Color System */
  --primary: #193153;
  --primary-hover: #0f1f38;
  --primary-light: #e8edf4;
  --primary-2: #2a4970;      /* compagnon de dégradé de --primary (barres de progression) */
  --accent: #10b981;
  --accent-hover: #059669;
  --accent-light: #ecfdf5;
  --success: #10b981;
  --warning: #f59e0b;
  --warning-hover: #d97706;  /* nuance d'appui des boutons/états warning (amber-600) */
  --error: #ef4444;
  --error-hover: #dc2626;    /* nuance d'appui des boutons/états danger (red-600) */
  --info: #3b82f6;
  
  /* Neutral Palette */
  --gray-50: #f9fafb;
  --gray-100: #f3f4f6;
  --gray-200: #e5e7eb;
  --gray-300: #d1d5db;
  --gray-400: #9ca3af;
  --gray-500: #6b7280;
  --gray-600: #4b5563;
  --gray-700: #374151;
  --gray-800: #1f2937;
  --gray-900: #111827;
  
  /* Semantic Colors */
  --bg: var(--gray-50);
  --surface: #fff;
  /* Surface de survol / fond léger des chromes (topbar, items de menu).
     Longtemps référencée avec des fallbacks divergents (#f5f5f5, #f8f8f8,
     #f8fafc) faute d'être définie — définie 2026-08-27, une seule teinte. */
  --color-surface-2: var(--gray-100);
  --border: var(--gray-200);
  --text: var(--gray-800);
  --text-primary: var(--gray-900);
  --text-secondary: var(--gray-600);
  --text-muted: var(--gray-500);

  /* ── Palette d'état — 14 teintes sémantiques ────────────────────────────
     Une teinte = un sens, pas un code métier : chaque app mappe ses propres
     codes de statut sur l'une de ces 14 couleurs (build : lk_catalog_project_status
     → config/statuses/project.php ; configurateur : DossierStates).
     Format : --state-{teinte}-bg (fond de pastille) / -fg (texte) / -dot
     (point coloré). Toutes contrastées AA sur fond clair.

     Vivaient dans build/public/assets/css/modules/configurator/dossiers.css
     jusqu'au 2026-08-01 — une CSS de module posait donc des variables dans
     :root, et dossier.css devait espérer que dossiers.css soit chargé avant
     lui (commentaire d'en-tête du fichier). Remontées ici, elles sont
     disponibles partout, dans l'ordre du cascade, sans dépendance d'ordre.
     Consommées par .badge-status-{teinte} (badges.css). ── */

  /* Étape 1 — Offre de prix */
  --state-slate-bg:    #f1f5f9;  --state-slate-fg:    #475569;  --state-slate-dot:    #94a3b8;
  --state-blue-bg:     #dbeafe;  --state-blue-fg:     #1d4ed8;  --state-blue-dot:     #3b82f6;
  --state-green-bg:    #d1fae5;  --state-green-fg:    #166534;  --state-green-dot:    #22c55e;
  --state-red-bg:      #fee2e2;  --state-red-fg:      #991b1b;  --state-red-dot:      #ef4444;

  /* Étape 2 — Éléments techniques */
  --state-orange-bg:   #ffedd5;  --state-orange-fg:   #9a3412;  --state-orange-dot:   #f97316;
  --state-teal-bg:     #ccfbf1;  --state-teal-fg:     #115e59;  --state-teal-dot:     #14b8a6;

  /* Étape 3 — Production */
  --state-amber-bg:    #fef3c7;  --state-amber-fg:    #92400e;  --state-amber-dot:    #d97706;
  --state-violet-bg:   #ede9fe;  --state-violet-fg:   #5b21b6;  --state-violet-dot:   #8b5cf6;
  --state-navy-bg:     #dbeafe;  --state-navy-fg:     #1e3a8a;  --state-navy-dot:     #1d4ed8;
  --state-forest-bg:   #d1fae5;  --state-forest-fg:   #064e3b;  --state-forest-dot:   #059669;

  /* Teinte hors-étapes — sky (15e, ajoutée 2026-08-28) : la paire historique
     de badge-info (sky-100/800) devenait un hex annoté partout ; la voici
     nommée. Dot = sky-500, même cran que les autres points. */
  --state-sky-bg:      #e0f2fe;  --state-sky-fg:      #075985;  --state-sky-dot:      #0ea5e9;

  /* Étape 4 — Facturation / Règlement */
  --state-indigo-bg:   #e0e7ff;  --state-indigo-fg:   #3730a3;  --state-indigo-dot:   #6366f1;
  --state-emerald-bg:  #d1fae5;  --state-emerald-fg:  #065f46;  --state-emerald-dot:  #10b981;
  --state-pine-bg:     #cffaef;  --state-pine-fg:     #064e3b;  --state-pine-dot:     #047857;
  --state-graphite-bg: #e2e8f0;  --state-graphite-fg: #1e293b;  --state-graphite-dot: #475569;

  /* Typography */
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  /* Chasse fixe — le SEUL token créé par l'audit `CSS-02` (2026-09-06), parce
     qu'il manquait vraiment : `--font-mono` était consommé 5 fois sans exister
     (build `components/catalog.css:1115`, `modules/configurator/products.css:318,328`
     et deux sites airfact), et 12 autres feuilles écrivaient leur propre pile
     à la main — 6 piles DIFFÉRENTES relevées, de `Courier New` à `ui-monospace`.
     Une référence, un code produit, une formule : même chasse partout. */
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
               'Liberation Mono', 'Courier New', monospace;

  /* ── Typographie des « grands nombres » ─────────────────────────────────
     Source unique pour toute valeur mise en avant (tuile KPI, total
     financier, montant inline). Avant 2026-08-27 chaque surface posait sa
     taille en dur (1.75rem / 2rem / 1.25rem / 1.125rem) — mêmes valeurs,
     désormais nommées. Un nouveau « grand nombre » consomme un de ces
     jetons, il n'invente pas une taille. */
  --value-size:      1.75rem;  /* valeur d'une tuile KPI avec icône (.dash-stat-value) */
  --value-size-lg:   2rem;     /* tuile --no-icon (verticale) */
  --value-size-md:   1.25rem;  /* total financier en pied de panneau */
  --value-size-sm:   1.125rem; /* montant inline (po-amount) */
  --value-weight:    700;
  --value-label-size:    0.825rem; /* libellé sous la valeur d'une tuile */
  --value-label-size-sm: 0.75rem;  /* libellé UPPERCASE des tuiles --no-icon */


  /* Spacing Scale */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  
  /* Design Properties */
  --radius: 0.5rem;
  --radius-sm: 0.25rem;
  --radius-lg: 0.75rem;
  --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.06);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.07), 0 2px 4px -2px rgb(0 0 0 / 0.05);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.08), 0 4px 6px -4px rgb(0 0 0 / 0.05);
  --transition: 200ms ease;

  /* ── Échelle d'empilement — 9 niveaux RELEVÉS (phase 2), pas inventés ────
     Documente la hiérarchie réelle de la plateforme ; un nouveau z-index
     consomme un de ces jetons, il n'invente pas une valeur. Les micro-ordres
     internes à un composant (0/1/2/5, pile du FAB Xori, utilitaires .z-10…50)
     restent des nombres : ils n'ordonnent que leur propre contexte.
     kebab (--z-float) > modales : NÉCESSAIRE — un menu détaché s'ouvre aussi
     depuis une ligne de tableau affichée dans une modale. */
  --z-topbar:      90;    /* barre de titre collante */
  --z-popover:    200;    /* popover ancré au chrome (inbox, menu user, panneau ms) */
  --z-chrome:    1000;    /* chrome fixe : sidebar, drawer, dropdowns ancrés */
  --z-chrome-2:  1100;    /* sur-chrome : popup de sous-menu de la sidebar */
  --z-modal:     2000;    /* voile + boîte de modale */
  --z-doc-overlay: 9800;  /* visionneuse de pièces jointes (au-dessus des modales) */
  --z-lightbox:  9900;    /* lightbox image plein écran */
  --z-float:     9999;    /* détaché du flux : kebab, toasts, voile de transition */
  --z-float-top: 10001;   /* menu détaché devant TOUT, toasts compris (status-badge-menu) */
  
  /* Layout Constants */
  /* `--sidebar-width` est LE levier de la colonne de gauche : layout.css (une
     copie par app, quatre fichiers identiques) en tire le `margin-left` et le
     `width` de `.main-content`, et le `left` de `.app-topbar`. Le MODE RAIL le
     redéfinit sur <html> (navigation.css) et les quatre apps suivent sans être
     touchées. `--sidebar-width-full` reste la largeur DÉPLIÉE, dont le survol
     se sert pour recouvrir le contenu sans le repousser. */
  --sidebar-width-full: 250px;
  --sidebar-rail-width: 68px;   /* 44 px de cible + 2 x 12 px (--chrome-pad-x-self) */
  --sidebar-width: var(--sidebar-width-full);
  --header-height: 60px;
  /* UNE rangée de chrome. `--topbar-height` est la hauteur TOTALE de la barre
     et plusieurs pages la réhaussent (recherche en mobile, bande d'onglets) —
     il ne peut donc pas servir de plancher à la barre elle-même : elle se
     retrouverait figée à la hauteur qu'on vient de lui demander. D'où ce
     second nom, qui ne dit qu'une rangée et ne bouge jamais. */
  --chrome-row-height: 80px;
  --topbar-height: var(--chrome-row-height);
  --container-max-width: 1280px;

  /* Semantic Padding Tokens — capture intent, not raw values.
     Two grids coexist by design:
       - Self-contained chrome (sidebar) lives in its own column and uses
         tight padding for visual density.
       - Content-aligned chrome (topbar) shares horizontal padding with
         the main content frame so the title and table headers sit on the
         same vertical grid.
     Vertical rhythm is shared across all chrome surfaces. */
  --chrome-pad-y:      var(--space-4);   /* 16px — vertical breathing for any chrome strip */
  --chrome-pad-x-self: var(--space-3);   /* 12px — horizontal for self-contained chrome (sidebar) */
  --content-pad:       var(--space-8);   /* 32px — content frame and content-aligned chrome (topbar, main-content) */
}

/* ══ POINTS D'EXTENSION — les tokens qu'on lit ICI sans les définir ═══════════
   (documentation, pas des déclarations : les définir ici CASSERAIT le mécanisme)

   Quatre noms sont consommés par le socle alors que rien ne les définit dans
   cette feuille. Ce ne sont PAS des fantômes au sens de `CSS-02` : ce sont des
   points d'extension, posés par quelqu'un d'autre, et leur repli est le
   comportement PAR DÉFAUT — pas une couleur en dur déguisée.

   | token             | posé par                                   | défaut (repli)      |
   |-------------------|--------------------------------------------|---------------------|
   | `--row-bg`        | le `<tr>` qui se teinte (attribut ou règle) | `var(--surface)`    |
   | `--row-bg-hover`  | le même `<tr>`, SI le survol doit différer | `var(--row-bg)`     |
   | `--logo-color-1`  | la feuille de marque de l'APP (`brand.css`) | `var(--primary)`    |
   | `--logo-color-2`  | idem — seconde couleur de marque            | jaune logo, annoté  |

   `--row-bg` (`tables.css`) est le SEUL jeton obligatoire pour teindre une
   ligne, et une ligne se teint en UNE déclaration :

       .ma-ligne { --row-bg: var(--gray-50); }

   Le socle peint le `<tr>` avec, au repos comme au survol ; la colonne
   d'actions **collante** — qui doit être opaque, le contenu défile dessous —
   ne décide rien et COPIE sa ligne (`background: inherit`). Ne mettez PAS de
   `background` à côté du jeton : ce serait un second endroit où la couleur se
   décide, et c'est précisément ce qui divergeait.
   `--row-bg-hover` ne sert qu'à vouloir un survol DIFFÉRENT du repos ; sans
   lui la ligne GARDE sa teinte au survol (repli sur `--row-bg`).
   Les définir dans `:root` ici marcherait encore, mais dirait le contraire de
   ce qu'on veut enseigner : la teinte se déclare UNE fois, sur la ligne.
   Gardé par `cli/probe-ligne-teintee-colonne-collante.mjs`.
   Contrat détaillé dans `app-core/CLAUDE.md` § Tables.

   `--logo-color-1/2` : seule `build/public/assets/css/components/brand.css` les
   pose aujourd'hui. Le repli d'`--logo-color-1` est un TOKEN (`var(--primary)`),
   pas un hex : une app sans feuille de marque porte le bleu marine Corelia, ce
   qui est la bonne valeur par défaut.

   Ces quatre-là sont les EXEMPTIONS déclarées de `cli/probe-css-tokens.php`
   (tableau `$EXEMPTIONS`, avec la raison de chacun). Tout autre fantôme du
   socle est une dette, et la sonde sort en 1.
   ═════════════════════════════════════════════════════════════════════════ */