/* ============================================================================
   BASE — remise à zéro, typographie, accessibilité de fond.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* `scroll-padding-block-start` et non `-top` : propriété logique, donc juste
   aussi en écriture de droite à gauche. Sa valeur empêche le titre visé par une
   ancre de finir SOUS la barre de navigation collante — WCAG 2.4.11. */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: calc(var(--h-nav) + var(--e5));
  tab-size: 2;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--texte);
  font-family: var(--font-corps);
  font-size: var(--fs-corps);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip; /* `clip` et non `hidden` : `hidden` crée un conteneur de
                       défilement qui casse `position: sticky` chez les enfants. */
}

/* Le grain, posé une seule fois sur toute la page. Sans lui, les dégradés
   sombres se découpent en bandes visibles sur écran OLED. Il est décoratif :
   il ne doit jamais intercepter un clic. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--grain);
  opacity: 0.5;
  mix-blend-mode: soft-light;
}

img, svg, video { display: block; max-inline-size: 100%; height: auto; }

/* Les navigateurs appliquent `margin-inline: 40px` à `figure` et `blockquote`. Ce défaut
   remonte aux origines du HTML et il coûte cher ici : sur un écran de 375 px, il retirait
   80 px — près d'un quart de la largeur — à chaque schéma, qui se retrouvait dessiné sur
   198 px au lieu de 800. Les textes de 13 unités tombaient alors à 3 px réels, donc
   parfaitement illisibles, sans qu'aucun contrôle automatique ne s'en émeuve : la page ne
   débordait pas, le contraste restait bon, et rien n'était « cassé » au sens des gates.
   Une marge héritée qu'on ne remet pas à zéro est une décision qu'on laisse prendre par
   quelqu'un d'autre. */
figure, blockquote { margin-inline: 0; }

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.018em;
  text-wrap: balance;
  color: var(--texte);
}
h1 { font-size: var(--fs-hero); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: -0.012em; }
h4 {
  font-size: var(--fs-h4);
  font-family: var(--font-corps);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
}

p, ul, ol { margin: 0 0 var(--e4); }
p { max-inline-size: var(--mesure); }

/* Les nombres s'alignent en colonne : sans chasse fixe, un tableau de montants
   fait onduler ses colonnes et devient impossible à comparer d'un coup d'œil. */
.nb, td, th, time, .mono { font-variant-numeric: tabular-nums; }

a { color: var(--lime); text-underline-offset: 0.22em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

strong, b { font-weight: 650; color: var(--texte); }

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--surface-2);
  padding: 0.12em 0.38em;
  border-radius: var(--r-puce);
}

/* ── Focus ─────────────────────────────────────────────────────────────────
   `:focus-visible` et non `:focus` : le second dessinerait un anneau après un
   clic à la souris, ce qui pousse les auteurs à le supprimer — et à casser la
   navigation au clavier. L'anneau est un CONTOUR, jamais une lueur : sous
   contraste forcé, les ombres portées sont supprimées et une lueur seule
   disparaîtrait entièrement. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-puce);
}
:focus:not(:focus-visible) { outline: none; }

/* ── Lien d'évitement ─────────────────────────────────────────────────────
   Premier élément focalisable de la page : il permet de sauter la navigation
   sans traverser tous ses liens à la tabulation. Visible dès qu'il est atteint. */
.evitement {
  position: absolute;
  inset-block-start: var(--e3);
  inset-inline-start: var(--e3);
  z-index: 100;
  padding: var(--e3) var(--e5);
  background: var(--lime);
  color: var(--bg);
  font-weight: 650;
  border-radius: var(--r-petit);
  transform: translateY(-160%);
  transition: transform var(--t) var(--ease-sortie);
}
.evitement:focus-visible { transform: translateY(0); }

/* Réservé aux lecteurs d'écran. `clip-path` plutôt que `display:none`, qui
   retirerait l'élément de l'arbre d'accessibilité. */
.sr {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Contenants ───────────────────────────────────────────────────────────── */
.contenant {
  inline-size: min(100% - 2 * var(--e5), var(--largeur));
  margin-inline: auto;
  position: relative;
  z-index: 1;
}
.contenant--ample { inline-size: min(100% - 2 * var(--e5), var(--largeur-ample)); }

@media (max-width: 640px) {
  .contenant, .contenant--ample { inline-size: min(100% - 2 * var(--e4), var(--largeur)); }
}

/* ── Le socle sans JavaScript ──────────────────────────────────────────────
   Tout ce qui n'apparaît qu'après une animation d'entrée est masqué UNIQUEMENT
   sous `html.js`, classe posée par le script lui-même. Si le script ne s'exécute
   pas — erreur, réseau coupé, robot d'indexation, capture d'écran — la classe
   n'existe pas, la règle ne s'applique pas, et le contenu reste visible.
   Un état initial `opacity: 0` non protégé de cette façon n'est pas une
   animation : c'est du contenu rendu inaccessible par défaut. */
.reveal { opacity: 1; }
