/* =========================================================================
   UST — socle : fontes, réinitialisation, éléments, focus, motion
   Aucune valeur littérale ici : tout vient de tokens.css.
   ========================================================================= */

/* --- Fontes auto-hébergées (C6) ------------------------------------------
   Trois familles, deux sous-ensembles chacune (latin, latin-ext), woff2.
   Spectral n'existe pas en variable : deux instances statiques, 300 et 400.
   Epilogue et Martian Mono sont variables, INSTANCIÉES aux seules graisses
   employées (wght 400-600 et 300-500) — l'axe complet 100-900 pesait 40 %
   de plus. Total servi : 166 Ko sur huit fichiers, 67 Ko sur le chemin
   critique (les trois latin).
   Aucun <link> vers fonts.googleapis.com nulle part : le Caddyfile pose
   font-src 'self', la CSP de production bloquerait le CDN.                 */

@font-face {
  font-family: "Spectral"; font-style: normal; font-weight: 300;
  font-display: swap; src: url("/assets/fonts/spectral-300-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: "Spectral"; font-style: normal; font-weight: 300;
  font-display: swap; src: url("/assets/fonts/spectral-300-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: "Spectral"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/spectral-400-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: "Spectral"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/spectral-400-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: "Epilogue"; font-style: normal; font-weight: 400 600;
  font-display: swap; src: url("/assets/fonts/epilogue-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: "Epilogue"; font-style: normal; font-weight: 400 600;
  font-display: swap; src: url("/assets/fonts/epilogue-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: "Martian Mono"; font-style: normal; font-weight: 300 500;
  font-display: swap; src: url("/assets/fonts/martianmono-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: "Martian Mono"; font-style: normal; font-weight: 300 500;
  font-display: swap; src: url("/assets/fonts/martianmono-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;
}

/* --- Réinitialisation ---------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

/* Zéro smooth scroll (§8) : le défilement n'est pas un effet. */
html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--nuit);
  color: var(--texte);
  font-family: var(--f-corps);
  font-size: var(--d-corps);
  font-weight: var(--g-corps);
  line-height: var(--i-corps);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img, svg, video { display: block; max-width: 100%; }
img, video { height: auto; }
input, button, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

/* --- Titrage — Spectral 300, plafonné à 96 px (§6) ------------------------ */
h1, h2, h3, h4, h5, h6 { text-wrap: balance; font-weight: var(--g-corps); }

.d-hero, .d-h1, .d-h2 {
  font-family: var(--f-display);
  font-weight: var(--g-display);
  line-height: var(--i-serre);
  letter-spacing: var(--l-display);
  /* Spectral sert des chiffres elzéviriens : un nom de produit — « DWARF 3 »
     — exige des chiffres capitales. */
  font-variant-numeric: lining-nums;
}
.d-hero, .d-h1 { font-size: var(--d-display); }
.d-h2 { font-size: var(--d-h2); }
.d-hero em, .d-h1 em, .d-h2 em { font-style: italic; font-weight: var(--g-display-forte); }

.d-h3 {
  font-family: var(--f-corps); font-size: var(--d-h3);
  font-weight: var(--g-corps-moyen); line-height: var(--i-titre); letter-spacing: -.015em;
}
.d-h4 {
  font-family: var(--f-corps); font-size: var(--d-h4);
  font-weight: var(--g-corps-fort); line-height: var(--i-titre); letter-spacing: -.01em;
}
.d-lead { font-size: var(--d-lead); color: var(--champ); line-height: 1.55; }

/* La lampe n'éclaire que ce que la main touche (loi n° 2) : un mot accentué
   par l'auteur se marque à la graisse, pas à la couleur d'accent. */
strong { font-weight: var(--g-corps-fort); color: var(--texte); }

p { max-width: var(--lecture); }
p + p { margin-top: var(--e-3); }

/* --- La donnée : Martian Mono, 12 px plancher (C8) ------------------------
   Elle porte exclusivement la donnée mesurée — poses, dates, définitions,
   désignations, prix, rapports. Jamais un paragraphe. */
.mono {
  font-family: var(--f-data); font-size: var(--d-mono);
  font-weight: var(--g-mono); line-height: var(--i-mono);
  letter-spacing: var(--l-mono); font-variant-numeric: tabular-nums;
}
/* Règle dure du système (§6) : tout nombre mesuré est en Martian Mono,
   y compris dans un titre ; l'unité reste dans la famille de la prose. */
.nombre {
  font-family: var(--f-data); font-weight: var(--g-mono);
  font-variant-numeric: tabular-nums; letter-spacing: 0;
}
.brow {
  font-family: var(--f-data); font-size: var(--d-mono);
  font-weight: var(--g-mono); line-height: var(--i-mono);
  text-transform: uppercase; letter-spacing: var(--l-brow);
  color: var(--label);
}

/* --- Liens --------------------------------------------------------------- */
a { color: inherit; text-decoration-color: var(--filet-haut); text-underline-offset: .25em; }
.lien {
  color: var(--lampe); text-decoration: none; font-weight: var(--g-corps-moyen);
  display: inline-block; line-height: 1.5; padding-bottom: 2px;
  border-bottom: 1px solid var(--lampe-bord);
  transition: color var(--t-ui) ease, border-color var(--t-ui) ease;
}
@media (hover: hover) {
  a:hover { text-decoration-color: currentColor; }
  .lien:hover { color: var(--lampe-haute); border-color: var(--lampe-haute); }
}

/* --- Focus tokenisé ------------------------------------------------------ */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur);
  outline-offset: var(--focus-o);
  border-radius: 2px;
}

.saut {
  position: absolute; left: var(--marge); top: var(--e-1); z-index: 100;
  transform: translateY(-200%);
  background: var(--ciel); color: var(--texte); border: 1px solid var(--filet-haut);
  padding: var(--e-2) var(--e-3); border-radius: var(--r-s);
  font-weight: var(--g-corps-moyen); text-decoration: none;
}
.saut:focus { transform: translateY(0); }

::selection { background: var(--selection); color: var(--nuit); }

/* --- Mise en page -------------------------------------------------------- */
.enveloppe { padding-inline: var(--marge); }
.contenu   { max-width: var(--contenu); margin-inline: auto; }
.etroit    { max-width: var(--etroit); margin-inline: auto; }
.section   { padding-block: var(--section); }
/* LA SECTION DE TÊTE RESPIRE MOINS PAR LE HAUT. Sur une page qui vend, le
   pli est une ressource : 150 px de vide au-dessus du premier mot, c'est
   150 px de moins pour la photographie, le prix et l'appel.
   ET MOINS PAR LE BAS AUSSI, PARCE QUE L'AIR Y ÉTAIT COMPTÉ DEUX FOIS.
   Le bas gardait --section, et la section suivante ajoutait le sien : deux
   fois 150 px à 1440, soit 300 px mesurés entre le dernier mot de
   l'ouverture et le premier de la section suivante, quand le héros de
   l'accueil, qui est le même bloc dans le même rôle, n'en laisse que 206. L'écart se
   voyait sur les 62 pages qui ouvrent au filet ou au nu, et le plus sur les
   plus courtes, où il occupait tout le milieu du premier écran.
   La valeur n'est pas choisie : c'est --e-6, exactement le padding-block que
   .hero se donne au-delà de 62rem. L'ouverture rend donc le même air que
   l'étalon, mesuré à 196 px au lieu de 300. */
.section--tete { padding-top: clamp(2rem, 1.1rem + 2.8vw, 4rem); padding-bottom: var(--e-6); }
/* Le fil d'Ariane porte sa propre marge basse pour les pages qui ne sont pas
   en pile. Dans une pile, la gouttière s'en charge, et les deux s'ajoutaient. */
.pile > .fil { margin-bottom: 0; }
.section-large { padding-block: var(--section-large); }
/* Un filet, jamais une différence de fond seule : la hiérarchie des plans
   vit sous 2:1 et doit survivre à un téléphone en plein soleil (§5). */
.section--filet { border-top: 1px solid var(--filet); }
/* LE FOND RELEVÉ D'UNE SECTION, ET IL A ENFIN UN NOM.
   Quinze sections des gabarits écrivaient `style="background: var(--ciel)"`
   en style en ligne. Ce n'était pas une valeur littérale — c'est bien le
   jeton — mais c'était la même décision recopiée quinze fois, donc quinze
   endroits à corriger le jour où l'alternance change. Le rythme de sections
   de la doctrine (_design/COHERENCE.md) s'écrit avec cette classe.
   Les styles en ligne restants posent exactement la même valeur : ils
   gagnent tant qu'ils sont là, et rien ne bouge à mesure qu'ils partent. */
.section--ciel { background: var(--ciel); }

.pile { display: flex; flex-direction: column; }
.pile-2 { gap: var(--e-2); } .pile-3 { gap: var(--e-3); }
.pile-4 { gap: var(--e-4); } .pile-5 { gap: var(--e-5); }
.pile-6 { gap: var(--e-6); } .pile-8 { gap: var(--e-8); }

.grille { display: grid; gap: var(--gouttiere); }
.autofit   { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.autofit-l { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }

.defile-x { overflow-x: auto; overscroll-behavior-x: contain; }

.u-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --- Révélation au défilement — 560 ms, jouée une fois (§8) --------------
   L'état caché est conditionné à .js, classe posée avant le premier rendu :
   sans JavaScript la page est COMPLÈTE. Ne pas régresser en refactorisant. */
.js [data-rev] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--t-revele) var(--courbe), transform var(--t-revele) var(--courbe);
  transition-delay: calc(var(--i, 0) * var(--t-cadence));
}
.js [data-rev].vu { opacity: 1; transform: none; }

/* --- Les deux gardes, obligatoires (§8) ---------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .js [data-rev] { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
/* Toute règle de survol est gardée : rien ne se déclenche au doigt. */
@media (hover: none) {
  .js [data-rev] { opacity: 1; transform: none; }
}

/* Cible tactile minimale (WCAG 2.2, 2.5.8) pour les liens de texte isolés
   dans une liste : sans cela un lien de source mesure 23 px de haut. */
li > a:only-child, .lex__voir a,
/* Le forum ajoute ses liens de texte isolés à la même règle plutôt que de
   recopier la valeur cinq fois : le titre d'un sujet dans la liste, les deux
   pas de la pagination, les actions sous un message, chaque appareil déclaré
   dans une fiche, et les deux résumés de <details>. */
.sujet__lien, .forum-pages__pas, .msg__action, .fiche__appareils a,
.msg__signal > summary, .forum-droits__fermer > summary {
  display: inline-flex; align-items: center; min-height: 1.5rem;
}
