/* =========================================================================
   tokens.css — squelette
   Architecture reprise de Medusa (nommage par rôle) + Grafana (densité).

   Deux couches, et l'ordre compte :
     1. PRIMITIVES — des valeurs brutes. Aucun composant ne les lit.
     2. SÉMANTIQUE  — des rôles. C'est la SEULE couche que le code applicatif
                      a le droit d'utiliser.

   Tout le reste est structurel et ne devrait pas bouger d'un projet à l'autre.
   ========================================================================= */

@font-face {
  /* Polices self-hosted (vendor/fonts). Nécessaires au specimen.html, qui est
     ouvert en file:// sans passer par Next.js : sans ces @font-face,
     --font-ui / --font-mono retomberaient sur sans-serif / monospace.
     Les apps Next.js chargent déjà leurs polices via next/font/layout.tsx ;
     ces déclarations y sont inertes (les polices de ces apps ne sont pas
     référencées par nom). unicode-range copiées du CSS de Google Fonts. */
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("vendor/fonts/public-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("vendor/fonts/public-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url("vendor/fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url("vendor/fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ---------------------------------------------------------------------
     1. PRIMITIVES
     --------------------------------------------------------------------- */


  /* Échelle typographique — base 14px, fermée, interlignes pairs */
  --text-2xs:  10px;  --lh-2xs:  16px;
  --text-xs:   12px;  --lh-xs:   18px;
  --text-sm:   13px;  --lh-sm:   20px;
  --text-base: 14px;  --lh-base: 20px;   /* corps */
  --text-md:   16px;  --lh-md:   22px;
  --text-lg:   18px;  --lh-lg:   24px;
  --text-xl:   22px;  --lh-xl:   28px;

  /* Tous les textes « compacts » (tableaux, listes, badges) partagent 20px
     d'interligne. C'est ce qui garde les lignes alignées. */
  --lh-compact: 20px;

  --tracking-tight:  -0.25px;  /* ≥ 22px */
  --tracking-normal:  0;
  --tracking-wide:    0.15px;  /* ≤ 14px */

  --weight-regular: 400;
  --weight-medium:  500;
  --weight-strong:  600;       /* plafond. 700 est interdit. */

  /* Espacement — grille de 8px, échelle fermée */
  --space-0:  0;     --space-1:  2px;   --space-2:  4px;
  --space-3:  8px;   --space-4:  12px;  --space-5:  16px;
  --space-6:  20px;  --space-7:  24px;  --space-8:  32px;
  --space-9:  40px;  --space-10: 48px;  --space-11: 64px;
  --space-12: 80px;

  /* Rayons — hiérarchisés, pas uniformes */
  --radius-badge:  2px;
  --radius-field:  4px;   /* inputs, boutons */
  --radius-panel:  8px;   /* cartes, popovers */
  --radius-modal:  12px;
  --radius-pill:   999px;



  /* Mouvement */
  --duration-instant: 75ms;
  --duration-fast:    150ms;
  --duration-normal:  300ms;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* ---------------------------------------------------------------------
     2. SÉMANTIQUE — la seule couche utilisable dans les composants
     --------------------------------------------------------------------- */

  /* Surfaces */
  --bg-app:        var(--neutral-1);
  --bg-subtle:     var(--neutral-2);
  --bg-component:  var(--neutral-3);
  --bg-hover:      var(--neutral-4);
  --bg-active:     var(--neutral-5);
  --bg-solid:      var(--accent-9);

  /* Texte */
  --fg-muted:      var(--neutral-11);
  --fg-default:    var(--neutral-12);
  --fg-on-solid:   #fff;
  --fg-accent:     var(--accent-11);

  /* Élévation — nommée par rôle, jamais par taille.
     Les bordures sont des box-shadow à spread 1px : elles ne modifient pas
     la boîte et se combinent avec l'anneau de focus. */
  --borders-base:
    0 1px 2px 0 rgb(0 0 0 / .12),
    0 0 0 1px rgb(0 0 0 / .08);

  --borders-focus:
    0 0 0 1px var(--bg-app),
    0 0 0 3px color-mix(in srgb, var(--accent-9) 60%, transparent);

  --borders-error:
    0 0 0 1px var(--danger-9, #e11d48),
    0 0 0 3px color-mix(in srgb, var(--danger-9, #e11d48) 15%, transparent);

  --elevation-card-rest:
    0 0 0 1px rgb(0 0 0 / .08),
    0 1px 2px -1px rgb(0 0 0 / .08),
    0 2px 4px 0 rgb(0 0 0 / .04);

  --elevation-card-hover:
    0 0 0 1px rgb(0 0 0 / .08),
    0 1px 2px -1px rgb(0 0 0 / .08),
    0 2px 8px 0 rgb(0 0 0 / .10);

  --elevation-flyout:
    0 0 0 1px rgb(0 0 0 / .08),
    0 4px 8px 0 rgb(0 0 0 / .08),
    0 8px 16px 0 rgb(0 0 0 / .08);

  --elevation-modal:
    0 0 0 1px rgb(0 0 0 / .08),
    0 8px 16px 0 rgb(0 0 0 / .08),
    0 16px 32px 0 rgb(0 0 0 / .08);
}

/* Mode sombre. Le liseré clair sur l'arête supérieure est ce qui donne aux
   surfaces un aspect taillé plutôt que collé à plat — ne le retire pas.

   --borders-focus est redéclaré ici (même source, mêmes var()) : un var()
   imbriqué dans un token se résout UNE SEULE FOIS, sur l'élément qui le
   DÉCLARE. Déclaré une fois dans :root, le liseré var(--bg-app) fige la
   valeur CLAIRE et l'hérite telle quelle dans tout scope sombre. La
   redéclaration dans ce bloc refait la substitution en sombre → le liseré
   suit --bg-app (clair #fcfcfd / sombre #111113). C'est le SEUL token
   composé qui embarque un var() d'une couleur changeant clair/sombre ;
   --borders-error n'en a pas (red-9 est identique dans les deux thèmes). */
[data-theme="dark"] {
  --borders-base:
    0 -1px 0 0 rgb(255 255 255 / .06),
    0 0 0 1px rgb(255 255 255 / .06),
    0 2px 2px 0 rgb(0 0 0 / .24);

  --borders-focus:
    0 0 0 1px var(--bg-app),
    0 0 0 3px color-mix(in srgb, var(--accent-9) 60%, transparent);

  --elevation-card-rest:
    0 -1px 0 0 rgb(255 255 255 / .06),
    0 0 0 1px rgb(255 255 255 / .06),
    0 1px 2px 0 rgb(0 0 0 / .32),
    0 2px 4px 0 rgb(0 0 0 / .32);

  --elevation-modal:
    0 0 0 1px rgb(255 255 255 / .10),
    0 4px 8px 0 rgb(0 0 0 / .32),
    0 8px 16px 0 rgb(0 0 0 / .32);
}

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