/* =============================================================================
   MÉCANIQUE — feuille unique.

   Thèse : un indicateur est une moyenne pondérée du passé, et on peut voir ses
   poids. Le décor en découle — la gouttière de pondération n'est pas un ornement
   posé sur la mise en page, elle EST la première colonne de la grille.

   La FORME, elle, vient du monogramme : traits épais, géométrie strictement
   angulaire, toutes les terminaisons coupées en biseau à 45°, aucun arrondi
   nulle part, monochrome absolu. La page en tire quatre conséquences, et une
   seule couleur ne s'y plie pas — l'accent, devenu rare :
     · le chanfrein remplace l'angle arrondi sur tout bloc porteur ;
     · le noir descend, le blanc devient franc, les filets remontent ;
     · les titres pèsent plus lourd et resserrent leur interlettrage ;
     · la trame de fond est visible, comme un plan coté.

   Trois règles de la norme frontend sont appliquées ici de façon visible, parce
   que chacune a déjà coûté une session :
     · tout `+` dans une fonction mathématique CSS porte une espace de chaque
       côté — sans elle, `clamp()` est invalide, `var()` échoue à la valeur
       calculée et TOUTE l'échelle typographique retombe à 16 px, en silence ;
     · le bloc `forced-colors` est en FIN de feuille, une media query n'ajoutant
       aucune spécificité, elle perd l'arbitrage par ordre source si elle est en
       tête ;
     · aucun `overflow-x: hidden` sur `body` — il se propage au viewport, écrête
       `scrollWidth` et rend la mesure de débordement structurellement incapable
       d'échouer.

   Les couleurs sont en sRGB hexadécimal et non en oklch : elles doivent être
   mesurables exactement par la formule WCAG (voir outils/contraste.mjs), et
   aucun navigateur n'implémente aujourd'hui le gamut mapping de CSS Color 4.
   ============================================================================= */

:root {
  /* --- Matière : noir d'atelier. Le monogramme est blanc pur sur noir pur, et
         la page tient le même écart : le fond descend, les calques suivent,
         le filet remonte. C'est le contraste qui fait la forme. ------------- */
  --fond:            #06080A;
  --calque-1:        #0D1216;
  --calque-2:        #151C22;
  --calque-3:        #1E272E;
  --filet:           #2E3941;   /* séparation décorative — pas de seuil WCAG */
  --filet-fort:      #6B7E8C;   /* bordure de contrôle : ≥ 3:1 exigé (WCAG 1.4.11) */

  /* --- Encre : blanc franc, sans dérive bleutée. --------------------------- */
  --encre:           #FFFFFF;
  --encre-douce:     #B9C6D2;
  --encre-faible:    #93A1AF;

  /* --- Accent : cyan de table lumineuse. Ratios mesurés, jamais recopiés.
         Il est devenu RARE — un lien, un état, une valeur vivante, un
         chiffre-clé, une série de données. Jamais un titre, jamais un
         ornement : une couleur qui décore n'informe plus. ------------------- */
  --accent:          #63D8E8;
  --accent-sourd:    #40919E;   /* barres de la gouttière : porteuses de sens, ≥ 3:1 */

  /* --- Les deux seules couleurs de marché. Réservées aux bougies.
         Aucun élément d'interface ne les emploie : sur un sujet où le lecteur
         apprend à lire une couleur comme une information, les réutiliser pour
         du décor est une faute de sens. ------------------------------------- */
  --hausse:          #4FBF8B;
  --baisse:          #E9695C;

  /* --- Rayons et chanfrein.
         Le logo n'a aucun arrondi : toutes ses terminaisons sont coupées en
         biseau à 45°. Le rayon reste donc à 1px — la pièce usinée — et c'est la
         coupe d'angle qui donne leur forme aux blocs. Les valeurs sont en
         PIXELS et jamais en pourcentage : un pourcentage déforme l'angle dès
         que le bloc n'est pas carré, et la coupe cesse d'être à 45°. -------- */
  --rayon:           1px;
  --chanfrein:       18px;
  --chanfrein-petit: 8px;

  /* --- Durées -------------------------------------------------------------- */
  --t1:  90ms;  --t2: 140ms;  --t3: 220ms;  --t4: 360ms;  --t5: 600ms;
  --courbe: cubic-bezier(.2, .6, .2, 1);

  /* --- Mesures ------------------------------------------------------------- */
  --gouttiere: 5.5rem;
  --colonne:   min(68ch, 100%);
  --marge:     clamp(1.1rem, 0.6rem + 2.2vw, 3.5rem);
  --pas-grille: 84px;   /* trame du plan d'atelier, en px comme le chanfrein */

  /* --- Échelle typographique. Chaque `+` porte ses deux espaces. ------------ */
  --pas-0:  clamp(0.78rem, 0.75rem + 0.14vw, 0.86rem);
  --pas-1:  clamp(0.94rem, 0.90rem + 0.20vw, 1.06rem);
  --pas-2:  clamp(1.06rem, 1.00rem + 0.30vw, 1.22rem);
  --pas-3:  clamp(1.30rem, 1.16rem + 0.70vw, 1.72rem);
  --pas-4:  clamp(1.78rem, 1.40rem + 1.90vw, 3.05rem);
  --pas-5:  clamp(2.20rem, 1.60rem + 3.00vw, 4.30rem);
  --pas-6:  clamp(2.80rem, 1.80rem + 5.00vw, 6.20rem);

  /* --- Familles : système, auto-hébergées par définition. Aucune requête
         réseau, aucune fuite vers un tiers, aucun lien qui se périme. -------- */
  --romaine:   Cambria, Georgia, "Iowan Old Style", "Times New Roman", serif;
  --grotesque: "Segoe UI", Inter, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --mono:      "Cascadia Mono", "SF Mono", "JetBrains Mono", Consolas, "Liberation Mono", monospace;
}

/* =============================================================================
   Socle
   ============================================================================= */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Les ancres ne doivent pas glisser sous l'en-tête collant. */
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--fond);
  color: var(--encre);
  font-family: var(--grotesque);
  font-size: var(--pas-2);
  line-height: 1.65;
  /* PAS de overflow-x ici — voir l'en-tête de fichier. */
}

/* La lumière vient de derrière les calques : un halo froid, fixe, très diffus,
   comme une table lumineuse vue dans une pièce sombre. Posé sur body::before
   pour rester sous tout le contenu sans créer de contexte d'empilement piégeux.
   Il est volontairement plus sourd qu'à la première version : un noir relevé
   n'est plus un noir, et c'est le noir qui porte le contraste du monogramme. */
body::before {
  content: "";
  position: fixed;
  inset: -20vmax 0 auto;
  height: 90vmax;
  background:
    radial-gradient(56vmax 38vmax at 50% 0%, #0E2429 0%, transparent 66%),
    radial-gradient(88vmax 48vmax at 18% 12%, #0A1219 0%, transparent 72%);
  opacity: .55;
  pointer-events: none;
  z-index: 0;
}

/* LE PLAN D'ATELIER. Une trame orthogonale au pas fixe, sous tout le contenu :
   la page se lit comme un plan coté, pas comme un document. Le pas est en
   PIXELS, comme le chanfrein, pour rester net à tout zoom. L'opacité est basse
   et la trame ne passe jamais sous un texte : les blocs de contenu sont opaques
   et la recouvrent. Elle est purement décorative — elle disparaît en couleurs
   forcées et à l'impression. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  background:
    repeating-linear-gradient(to right, var(--filet) 0 1px, transparent 1px var(--pas-grille)),
    repeating-linear-gradient(to bottom, var(--filet) 0 1px, transparent 1px var(--pas-grille));
  opacity: .3;
  pointer-events: none;
  z-index: 0;
}

body > * { position: relative; z-index: 1; }

img, svg { max-width: 100%; height: auto; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--rayon);
}

.evitement {
  position: absolute;
  left: var(--marge);
  top: 0;
  transform: translateY(-120%);
  z-index: 60;
  background: var(--calque-3);
  color: var(--encre);
  border: 1px solid var(--accent);
  border-radius: var(--rayon);
  padding: .8rem 1.2rem;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.evitement:focus { transform: translateY(0); }
/* Le glissement du lien d'évitement est un OPT-IN, comme les révélations plus bas :
   il ne s'ajoute que si le visiteur n'a rien demandé de contraire. Il était posé sur
   la règle de base et survivait donc à `reduce` — mesuré à 0,140 s sur les six pages
   par outils/verifier-mouvement.mjs. Le défaut était petit et particulièrement mal
   placé : la personne qui coupe les animations est souvent celle qui navigue au
   clavier, donc la seule à voir ce lien bouger. Le saut instantané reste correct ;
   c'est l'animation qui est facultative, jamais l'inverse. */
@media (prefers-reduced-motion: no-preference) {
  .evitement { transition: transform var(--t2) var(--courbe); }
}

/* =============================================================================
   Typographie

   L'écart entre un titre et son corps est volontairement brutal : le titre est
   gras, très serré, blanc franc ; le corps est régulier, plus clair, plus aéré.
   Un lecteur doit voir la hiérarchie avant de lire les mots.
   ============================================================================= */

h1, h2, h3 {
  font-family: var(--romaine);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.032em;
  text-wrap: balance;
  color: var(--encre);
  margin: 0 0 .5em;
}

h1 { font-size: var(--pas-6); letter-spacing: -0.045em; }
h2 { font-size: var(--pas-4); }
h3 { font-size: var(--pas-3); font-weight: 600; line-height: 1.14; letter-spacing: -0.012em; }

/* Le libellé de rang 4 n'est pas un titre : c'est une cote portée par un filet,
   comme une légende de plan. */
h4 {
  font-family: var(--grotesque);
  font-size: var(--pas-1);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--encre-douce);
  border-top: 1px solid var(--filet);
  padding-top: .7rem;
  margin: 2.6rem 0 .8rem;
}

p { margin: 0 0 1.15em; max-width: 68ch; text-wrap: pretty; }

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

strong { font-weight: 700; color: var(--encre); }

code, .nombre, .mono {
  font-family: var(--mono);
  font-size: .92em;
  font-variant-numeric: tabular-nums;
}

code {
  background: var(--calque-2);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
  padding: .1em .38em;
}

/* =============================================================================
   LE CHANFREIN — la forme importée du monogramme.

   Le logo coupe toutes ses terminaisons en biseau à 45°, jamais en arrondi. Un
   bloc fait donc la même chose : deux angles OPPOSÉS coupés net, dans le sens de
   la diagonale du X. Les valeurs sont en pixels et non en pourcentage — un
   pourcentage déforme l'angle dès que le bloc n'est pas carré, et la coupe
   cesse d'être à 45°.

   La coupe ne porte pas de filet, et c'est délibéré : le monogramme est une
   forme pleine, pas un contour. L'angle coupé se lit comme un changement de
   matière, exactement comme la terminaison biseautée d'un trait du logo.

   Deux contraintes qui ne se devinent pas :
     · `clip-path` rogne tout ce qui déborde de la boîte, y compris l'outline de
       focus. Aucun élément focalisable n'est donc coupé PENDANT qu'il a le
       focus : `:not(:focus-visible)` lève la coupe le temps du focus. La
       visibilité de l'indicateur prime sur la forme, toujours.
     · `clip-path` crée un contexte d'empilement. Aucun de ces blocs ne contient
       d'élément collant ou fixe — la gouttière collante est en dehors.
   ============================================================================= */

.calque,
.outil,
/* L'enveloppe de tableau porte désormais `tabindex="0"` — sans quoi son défilement
   horizontal est inatteignable au clavier (le pourquoi est dans `tableau()`,
   src/contenu/composants.mjs). Elle devient donc focalisable, et la contrainte
   écrite vingt lignes plus haut s'applique à elle comme aux boutons : `clip-path`
   rogne l'outline de focus. Sans ce `:not()`, l'anneau serait tronqué sur deux
   coins exactement sur les blocs où l'on vient d'ajouter la focalisation — et
   FRONTEND.md §6.9 exige un indicateur de focus visible à 3:1, pas un indicateur
   à moitié rogné. */
.table-enveloppe:not(:focus-visible),
.grille-chiffres,
.resultat,
.ponderation-barres,
.avertissement,
.graphique,
blockquote {
  clip-path: polygon(
    var(--chanfrein) 0,
    100% 0,
    100% calc(100% - var(--chanfrein)),
    calc(100% - var(--chanfrein)) 100%,
    0 100%,
    0 var(--chanfrein)
  );
}

.etiquette,
.bouton-lissage:not(:focus-visible),
.donnees-brutes summary:not(:focus-visible) {
  clip-path: polygon(
    var(--chanfrein-petit) 0,
    100% 0,
    100% calc(100% - var(--chanfrein-petit)),
    calc(100% - var(--chanfrein-petit)) 100%,
    0 100%,
    0 var(--chanfrein-petit)
  );
}

/* =============================================================================
   En-tête et navigation
   ============================================================================= */

.entete {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem var(--marge);
  align-items: center;
  justify-content: space-between;
  padding: .85rem var(--marge);
  /* Opaque, et sans flou : un bandeau translucide et flouté relève le noir,
     coûte une couche de composition à chaque défilement, et appartient à une
     esthétique que ce site ne pratique pas. Le noir reste noir ; c'est le filet
     qui sépare. */
  background: var(--fond);
  border-bottom: 1px solid var(--filet-fort);
}

.marque { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
.marque-nom {
  font-family: var(--romaine);
  font-size: var(--pas-2);
  font-weight: 700;
  letter-spacing: .24em;
  text-transform: uppercase;
}
.marque-suite { font-size: var(--pas-0); color: var(--encre-faible); letter-spacing: .04em; }

.nav-parcours {
  display: flex;
  flex-wrap: wrap;
  gap: .2rem;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
}
.nav-parcours a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  padding: .3rem .7rem;
  border-radius: var(--rayon);
  color: var(--encre-douce);
  text-decoration: none;
  font-size: var(--pas-1);
  transition: color var(--t2) var(--courbe), background var(--t2) var(--courbe);
}
.nav-parcours a:hover { color: var(--encre); background: var(--calque-2); }
.nav-parcours a[aria-current="page"] { color: var(--accent); background: var(--calque-2); }
.numero-nav {
  font-family: var(--mono);
  font-size: var(--pas-0);
  color: var(--encre-faible);
}
.nav-parcours a[aria-current="page"] .numero-nav { color: var(--accent); }

/* =============================================================================
   LA SIGNATURE — la gouttière de pondération.

   Elle porte la mise en page : chaque section est une grille à deux colonnes
   dont la première EST la gouttière. La retirer ne retire pas un décor, elle
   supprime une colonne et déplace tout le contenu. Sous 768 px elle bascule en
   règle horizontale et continue de fixer l'indentation.
   ============================================================================= */

.section {
  display: grid;
  grid-template-columns: var(--gouttiere) minmax(0, 1fr);
  gap: 0 clamp(1.2rem, 0.4rem + 2vw, 3rem);
  max-width: 92rem;
  margin: 0 auto;
  padding: clamp(3rem, 1.5rem + 5vw, 7rem) var(--marge);
  border-bottom: 1px solid var(--filet);
}

.gouttiere {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-top: .9rem;
  align-self: start;
  position: sticky;
  top: 6.5rem;
}

/* Chaque barre porte le poids réel alpha·(1−alpha)^i, calculé à la construction.
   La signature du site est littéralement la formule qu'il enseigne. */
.poids {
  height: 2px;
  background: var(--accent-sourd);
  border-radius: 0;
  transform-origin: left center;
}
.poids:first-child { background: var(--accent); height: 3px; }

.gouttiere-libelle {
  font-family: var(--mono);
  font-size: var(--pas-0);
  color: var(--encre-faible);
  margin-top: .7rem;
  writing-mode: horizontal-tb;
}

.corps-section > :first-child { margin-top: 0; }

/* La colonne de texte porte sa cote : un filet vertical marque le bord gauche du
   contenu, comme la ligne de rappel d'un plan — la grille cesse d'être implicite.
   Uniquement au-dessus de 768 px : en dessous, la grille passe à une colonne, la
   gouttière redevient horizontale et un filet vertical n'y désignerait plus rien.
   Le retrait est donc porté par la borne de la media query, pas par une
   surcharge à annuler plus bas. */
@media (min-width: 768px) {
  .corps-section {
    border-left: 1px solid var(--filet);
    padding-left: clamp(1rem, 0.4rem + 1.2vw, 2rem);
  }
}

/* =============================================================================
   Blocs de contenu
   ============================================================================= */

.hero { border-bottom: 1px solid var(--filet); }
.hero .corps-section { padding-block: clamp(1rem, 4vw, 4rem); }

/* Le sur-titre ne porte plus l'accent : il nomme une section, il ne signale
   aucun état et ne transporte aucune donnée. L'accent est rare, et ce qui reste
   pour tenir un libellé, c'est l'interlettrage et la casse. */
.sur-titre {
  font-family: var(--mono);
  font-size: var(--pas-0);
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--encre-faible);
  margin: 0 0 1.4rem;
}

.chapeau {
  font-size: var(--pas-3);
  line-height: 1.45;
  color: var(--encre-douce);
  max-width: 46ch;
  font-family: var(--romaine);
}

.calque {
  background: var(--calque-1);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
  padding: clamp(1.2rem, .8rem + 1.5vw, 2.1rem);
  margin: 2rem 0;
}

.calque > :last-child { margin-bottom: 0; }

.calque-accent { border-color: var(--accent-sourd); background: var(--calque-2); }

.etiquette {
  display: inline-block;
  font-family: var(--mono);
  font-size: var(--pas-0);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--encre-douce);
  background: var(--calque-2);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: .22rem .6rem;
  margin-bottom: .9rem;
}

/* Ni rouge ni vert ici : ces deux couleurs sont réservées aux bougies, et sur un
   site qui apprend à lire une couleur comme une information de marché, les
   réemployer pour une étiquette d'interface est une faute de sens. La distinction
   passe par l'encre et le filet, pas par la teinte de marché. */
.etiquette-mythe {
  color: var(--encre);
  border-color: var(--filet-fort);
  background: var(--calque-3);
}
/* Seule variante à garder l'accent : elle ne décore pas, elle tranche entre deux
   affirmations opposées. */
.etiquette-fait {
  color: var(--accent);
  border-color: var(--accent-sourd);
}

/* Le chiffre qui frappe. */
.chiffre-cle {
  display: block;
  font-family: var(--mono);
  font-size: var(--pas-5);
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.04em;
}
.chiffre-legende { display: block; font-size: var(--pas-1); color: var(--encre-douce); margin-top: .6rem; }

.grille-chiffres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 1px;
  background: var(--filet);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
  margin: 2rem 0;
}
.grille-chiffres > * { background: var(--calque-1); padding: 1.4rem; margin: 0; }

/* La source, systématiquement rattachée à l'affirmation. */
.source {
  display: block;
  font-size: var(--pas-0);
  color: var(--encre-faible);
  font-family: var(--mono);
  margin-top: .7rem;
}
.source a { color: var(--encre-douce); }

/* La citation est un bloc de matière, pas un retrait : elle reçoit donc le
   chanfrein comme les autres, et il lui faut un fond pour que la coupe se voie.
   Son filet reste neutre — une citation ne porte aucun état. */
blockquote {
  margin: 2.4rem 0;
  padding: 1.3rem 1.5rem;
  background: var(--calque-1);
  border-left: 3px solid var(--filet-fort);
  font-family: var(--romaine);
  font-size: var(--pas-3);
  line-height: 1.45;
  color: var(--encre);
}
blockquote p:last-of-type { margin-bottom: .5rem; }
blockquote cite {
  display: block;
  font-family: var(--grotesque);
  font-size: var(--pas-1);
  font-style: normal;
  color: var(--encre-faible);
}

/* =============================================================================
   Tableaux
   ============================================================================= */

.table-enveloppe { overflow-x: auto; margin: 2rem 0; border: 1px solid var(--filet); border-radius: var(--rayon); }

/* Un mot insécable très long — nom composé allemand, URL, nombre à douze
   chiffres — élargit sa colonne de grille et pousse le document entier hors du
   viewport : un élément de grille porte `min-width: auto` par défaut et refuse
   de descendre sous la largeur de son contenu, ce qui neutralise même un parent
   en `overflow-x: auto`. Mesuré : 591 px de document pour 375 px de fenêtre.
   `min-width: 0` rend la colonne compressible, `overflow-wrap` rend le mot
   cassable — il faut les deux, l'un ne suffit pas. */
.corps-section, .table-enveloppe, .figure-graphique, .outil, .calque { min-width: 0; }
th, td, .chiffre-cle, .resultat dd { overflow-wrap: anywhere; }
h1, h2, h3, h4, figcaption, p { overflow-wrap: break-word; }

table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--pas-1);
  /* Sans plancher, un tableau à trois colonnes se comprime sur téléphone au
     lieu de défiler : chaque cellule devient une pile de mots d'une syllabe.
     Constaté à 360px sur la page « Ce qui décide ». L'enveloppe porte déjà
     `overflow-x: auto` — encore faut-il lui donner quelque chose à faire défiler. */
  min-width: 32rem;
}

/* La couleur de base passe par l'HÉRITAGE sur tbody, jamais par `td { color }` :
   une déclaration directe (0,1,1) battrait toute classe de variante (0,1,0),
   quel que soit l'ordre du code. */
tbody { color: var(--encre-douce); }

th, td { padding: .72rem .9rem; text-align: left; border-bottom: 1px solid var(--filet); vertical-align: top; }
thead th {
  font-family: var(--grotesque);
  font-size: var(--pas-0);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--encre-faible);
  font-weight: 700;
  background: var(--calque-2);
  border-bottom: 1px solid var(--filet-fort);
}
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }

/* A link in a table cell is a navigation target, not a word inside a sentence, so
   WCAG 2.2's "inline" exemption to SC 2.5.8 does not cover it. Measured at 22px
   high in Chromium — under the 24px AA floor, and far under the 44px this project
   builds to (FRONTEND.md §6.10). Corrected on the COMPONENT, not on the four
   offending links: a fix aimed at named elements comes undone the next time
   someone adds a fifth. inline-flex + min-height rather than padding, so the
   height is guaranteed instead of inherited from font metrics. */
.table-enveloppe th a,
.table-enveloppe td a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
td.num, th.num { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; }

/* Le losange du tableau croisé : il marque les cases qui ressortent du bruit.
   L'accent est rare sur ce site, et c'est exactement un cas où il se mérite —
   il transporte une donnée, il ne décore pas.

   La forme n'est PAS le seul porteur : la valeur passe aussi en gras, et le
   losange porte un `title`. Un lecteur qui ne distingue pas la couleur voit la
   graisse ; un lecteur d'écran entend le titre. WCAG 1.4.1 interdit de faire
   reposer une information sur la seule couleur, et un tableau de 72 cases est
   précisément l'endroit où on l'oublie. */
.marque-sortant {
  color: var(--accent);
  font-size: .78em;
  margin-left: .3em;
  vertical-align: .08em;
}

/* =============================================================================
   Graphiques
   ============================================================================= */

.figure-graphique { margin: 2.4rem 0; }

/* Les illustrations. Même traitement que les graphiques — filet, rayon, coupe
   d'angle — parce qu'elles sont du même ordre : des objets posés sur la page, pas
   des fonds.

   `aspect-ratio` doublé des attributs width/height du HTML : les attributs
   réservent la place avant le chargement, la règle CSS la maintient quand la
   largeur est contrainte. L'une sans l'autre laisse passer un décalage de mise en
   page dans un des deux cas. */
.figure-illustration { margin: 2.4rem 0; }
.figure-illustration picture { display: block; }
.figure-illustration img {
  width: 100%;
  height: auto;
  aspect-ratio: 1376 / 768;
  display: block;
  background: var(--calque-1);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
  object-fit: cover;
}
/* Pas de règle `figcaption` ici : il en existe déjà une, globale, ligne 720. Une
   seconde qui dirait presque la même chose est une divergence programmée — c'est
   la convention du dépôt, et elle vaut pour le CSS comme pour le reste. */

.graphique { width: 100%; height: auto; display: block; background: var(--calque-1);
  border: 1px solid var(--filet); border-radius: var(--rayon); }

.grille line { stroke: var(--filet); stroke-width: 1; }
.graduation { fill: var(--encre-faible); font-family: var(--mono); font-size: 11px; }

.bougie .meche { stroke-width: 1; }
.bougie.hausse .meche, .bougie.hausse .corps { stroke: var(--hausse); fill: var(--hausse); }
.bougie.baisse .meche, .bougie.baisse .corps { stroke: var(--baisse); fill: var(--baisse); }

.courbe { stroke-width: 2; stroke-linejoin: miter; stroke-linecap: butt; }
.courbe.ema50  { stroke: var(--accent); }
.courbe.ema200 { stroke: #C9A227; }
.courbe.oscillateur { stroke: var(--accent); stroke-width: 1.6; }

.fond-panneau { fill: var(--calque-2); }
.seuil { stroke: var(--filet-fort); stroke-width: 1; stroke-dasharray: 3 3; }

.zone rect { fill: color-mix(in srgb, var(--accent) 12%, transparent); }
.zone.zone-attente rect { fill: color-mix(in srgb, var(--encre-faible) 16%, transparent); }
.repere line { stroke: var(--encre-faible); stroke-width: 1; stroke-dasharray: 2 3; }
.repere circle { fill: var(--accent); }
/* Le point posé sur le prix visé : plein mais discret, pour que l'œil aille du
   repère au sommet exact dont parle la légende. */
.repere .repere-cible { fill: var(--accent-sourd); stroke: var(--accent); stroke-width: 1; }

/* Histogrammes. Deux séries au plus, et elles se distinguent d'abord par la
   HAUTEUR : la teinte n'est jamais le seul porteur de l'information. */
.serie-barres .barre { fill: var(--accent-sourd); }
.serie-barres.serie-ema .barre { fill: var(--accent); }
.serie-barres.serie-sma .barre { fill: var(--encre-faible); }

/* Le texte d'un SVG suit l'échelle du viewBox, pas la taille de police du
   document : sur un écran étroit, 11px dans un viewBox de 1000 tombe sous 4px
   réels. On compense ici. La vérité chiffrée reste dans le tableau replié, qui
   lui est du vrai texte, à la taille du document. */
.categorie { font-size: 13px; }

/* Sans JavaScript, les trois vues du comparateur s'affichent à la suite : chacune
   a donc besoin de son titre. Avec JavaScript, le bouton pressé porte déjà
   l'information et ce titre ferait doublon. Le contenu n'est jamais masqué par
   défaut dans le HTML — c'est le script qui masque, jamais le document. */
.libelle-vue {
  font-family: var(--mono);
  font-size: var(--pas-0);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--encre-douce);
  margin: 1.4rem 0 .2rem;
}
.js .libelle-vue { display: none; }
@media (max-width: 700px) {
  .graduation { font-size: 21px; }
  .categorie { font-size: 23px; }
}

figcaption { font-size: var(--pas-1); color: var(--encre-douce); margin-top: .8rem; max-width: 68ch; }

/* La note qui explique d'où viennent les durées de lecture. Même traitement qu'une
   légende — c'est le même genre de texte : il commente une donnée au lieu de
   porter le propos. Pas de nouvelle variable de couleur, celle des légendes est
   déjà la bonne et en ajouter une seconde ferait diverger les deux. */
.note-lecture { font-size: var(--pas-1); color: var(--encre-douce); max-width: 68ch; }

.donnees-brutes { margin-top: .9rem; }
.donnees-brutes summary {
  cursor: pointer;
  font-size: var(--pas-1);
  color: var(--accent);
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: .6rem;
  background: var(--calque-1);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: 0 1rem;
  list-style: none;
  width: fit-content;
}
/* Le marqueur natif disparaît dans un `display: flex` (et sous WebKit il faut
   `::-webkit-details-marker`). On le redessine, sinon rien ne signale que le
   bloc s'ouvre — et une capture montre alors une ligne de texte inerte. */
.donnees-brutes summary::-webkit-details-marker { display: none; }
.donnees-brutes summary::before {
  content: "";
  width: .5rem; height: .5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--t2) var(--courbe);
}
.donnees-brutes[open] summary::before { transform: rotate(-135deg) translate(-2px, -2px); }
.donnees-brutes summary:hover { background: var(--calque-2); }
.donnees-brutes table { margin-top: .6rem; }

/* =============================================================================
   Outils interactifs — enrichissement seulement. Sans JavaScript, le bloc reste
   lisible et affiche sa valeur par défaut, calculée à la construction.
   ============================================================================= */

.outil {
  background: var(--calque-1);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: clamp(1.3rem, .8rem + 1.6vw, 2.2rem);
  margin: 2.4rem 0;
}

/* Le titre d'outil ne porte plus l'accent non plus : c'est un intitulé. Ce qui
   le distingue, c'est la graisse, la casse et le filet qui le souligne. */
.outil-titre {
  font-family: var(--grotesque);
  font-size: var(--pas-1);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--encre);
  border-bottom: 1px solid var(--filet);
  padding-bottom: .7rem;
  margin: 0 0 1.2rem;
}

.commandes { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-bottom: 1.4rem; }

.commande { display: flex; flex-direction: column; gap: .4rem; min-width: 12rem; flex: 1 1 12rem; }
.commande label { font-size: var(--pas-1); color: var(--encre-douce); }
.commande output { font-family: var(--mono); color: var(--accent); font-variant-numeric: tabular-nums; }

input[type="range"] { width: 100%; min-height: 44px; accent-color: var(--accent); }
input[type="number"] {
  background: var(--calque-2);
  color: var(--encre);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: .55rem .7rem;
  min-height: 44px;
  font-family: var(--mono);
  font-size: var(--pas-1);
  width: 100%;
}
input::placeholder { color: var(--encre-faible); opacity: 1; }

.resultat {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: 1px;
  background: var(--filet);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
}
.resultat > div { background: var(--calque-2); padding: 1rem 1.1rem; }
.resultat dt { font-size: var(--pas-0); color: var(--encre-faible); text-transform: uppercase; letter-spacing: .14em; }
.resultat dd {
  margin: .35rem 0 0;
  font-family: var(--mono);
  font-size: var(--pas-3);
  color: var(--encre);
  font-variant-numeric: tabular-nums;
}

.liste-sources { list-style: none; padding: 0; margin: 0; }
.liste-sources li {
  padding: 1rem 0;
  border-bottom: 1px solid var(--filet);
  max-width: 74ch;
}
.liste-sources li:last-child { border-bottom: 0; }
.liste-sources a {
  font-family: var(--mono);
  font-size: var(--pas-0);
  /* Une URL longue ne doit jamais pousser la page hors de sa largeur. */
  overflow-wrap: anywhere;
  display: inline-block;
  margin-top: .3rem;
  min-height: 24px;
}

.note-sans-js { font-size: var(--pas-0); color: var(--encre-faible); margin-top: 1rem; }
.js .note-sans-js { display: none; }

/* Boutons de bascule du comparateur. Sans JavaScript ils restent visibles mais
   inopérants, et la note explique que les trois vues sont affichées à la suite. */
.bouton-lissage {
  font-family: var(--grotesque);
  font-size: var(--pas-1);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--encre-douce);
  background: var(--calque-2);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: .5rem 1rem;
  min-height: 44px;
  cursor: pointer;
  flex: 0 1 auto;
  min-width: auto;
  transition: color var(--t2) var(--courbe), background var(--t2) var(--courbe),
              border-color var(--t2) var(--courbe);
}
.bouton-lissage:hover { color: var(--encre); background: var(--calque-3); }
.bouton-lissage[aria-pressed="true"] {
  color: var(--fond);
  background: var(--accent);
  border-color: var(--accent);
}

/* La bande de pondération du banc : mêmes barres que la signature, à
   l'horizontale et sur toute la largeur. */
.ponderation-barres {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 1.4rem;
  padding: 1rem;
  background: var(--calque-2);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
}
.ponderation-barres .poids { height: 3px; }

/* Visible pour un lecteur d'écran, hors de l'écran pour les autres. Jamais
   `display:none`, qui la retirerait aussi de l'arbre d'accessibilité. */
.visuellement-cache {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =============================================================================
   Pied de page et navigation basse
   ============================================================================= */

.suite {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: 1px;
  background: var(--filet);
  border-block: 1px solid var(--filet);
}
.suite-lien {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  background: var(--calque-1);
  padding: 1.6rem var(--marge);
  text-decoration: none;
  color: var(--encre);
  min-height: 44px;
  transition: background var(--t3) var(--courbe);
}
.suite-lien:hover { background: var(--calque-2); }
.suite-suiv { text-align: right; }
.suite-role { font-family: var(--mono); font-size: var(--pas-0); color: var(--encre-faible); letter-spacing: .16em; text-transform: uppercase; }
.suite-titre { font-family: var(--romaine); font-size: var(--pas-3); font-weight: 700; letter-spacing: -0.02em; }

.pied { padding: clamp(2.5rem, 5vw, 4rem) var(--marge); max-width: 92rem; margin: 0 auto; }
.avertissement {
  background: var(--calque-1);
  border: 1px solid var(--filet-fort);
  /* Filet d'accentuation neutre : voir la note sur .etiquette-mythe — le rouge
     de marché ne sort pas des bougies, même pour un avertissement. */
  border-left: 3px solid var(--accent-sourd);
  border-radius: var(--rayon);
  padding: 1.2rem 1.4rem;
  font-size: var(--pas-1);
  color: var(--encre-douce);
  max-width: none;
}
.pied-meta { font-size: var(--pas-0); color: var(--encre-faible); max-width: none; }

/* =============================================================================
   Révélations — le décor peut échouer, le contenu NON.

   Ce bloc a été réécrit après l'avoir vu échouer en vrai : la première version
   posait `opacity: .001` sur `.reveal`, ce qui confie au JavaScript la charge de
   re-montrer le texte. Une capture pleine page a rendu deux sections entières
   invisibles — le DOM les contenait, l'écran non. Tout ce qui peut échouer fera
   perdre du contenu, et un service de capture, un aperçu, un lecteur en mode
   lecture ou un script qui ne se charge pas suffisent à déclencher l'échec.

   Donc : AUCUNE opacité sur le contenu, jamais. La révélation ne joue que sur
   une translation, qui n'a jamais empêché personne de lire. L'opacité reste
   permise sur ce qui est purement décoratif et porte `aria-hidden`.
   ============================================================================= */

@media (prefers-reduced-motion: no-preference) {
  .js .reveal {
    transform: translateY(14px);
    transition: transform var(--t5) var(--courbe);
  }
  .js .reveal.vu { transform: none; }

  /* La gouttière n'est PAS animée depuis un état réduit, et c'est délibéré.
     Première version : `scaleX(.06)` levé à la révélation. Une capture pleine
     page l'a rendue invisible sur toutes les sections basses — le même piège que
     pour le texte, en plus discret. La signature du site ne peut pas dépendre
     d'un déclencheur : elle est là dès le premier rendu. */
}

/* =============================================================================
   Largeurs
   ============================================================================= */

@media (max-width: 1024px) {
  :root { --gouttiere: 3.5rem; }
}

@media (max-width: 767px) {
  /* La gouttière bascule en règle horizontale et garde sa fonction : elle fixe
     l'indentation du bloc et reste la première rangée de la grille. */
  .section { grid-template-columns: minmax(0, 1fr); gap: 1.2rem 0; }
  .gouttiere {
    position: static;
    flex-direction: row;
    align-items: flex-end;
    gap: 2px;
    height: 1.6rem;
    padding-top: 0;
  }
  .poids { height: auto; width: 2px; align-self: stretch; }
  .poids:first-child { width: 3px; height: auto; }
  .gouttiere-libelle { margin-top: 0; margin-left: .8rem; align-self: center; }
  .entete { position: static; }
  .suite-suiv { text-align: left; }
  /* Le chanfrein rétrécit avec les blocs : à 375 px, 18 px de coupe sur une
     carte de 300 px mangent le coin au lieu de le tailler. */
  :root { --chanfrein: 12px; --chanfrein-petit: 6px; --pas-grille: 56px; }
}

@media print {
  /* Ctrl+P n'émet ni scroll ni intersection : tout ce qui attendait d'être
     révélé sortirait en pages blanches. */
  .js .reveal, .js .reveal.vu { opacity: 1 !important; transform: none !important; }
  body::before, body::after, .entete, .suite { display: none; }
  body { background: #fff; color: #000; }
  .calque, .outil, .graphique { border: 1px solid #999; background: #fff; }
  /* Sur blanc, une coupe d'angle sans matière derrière ne se lit plus comme un
     biseau : elle se lit comme un cadre mal imprimé. */
  .calque, .outil, .table-enveloppe, .grille-chiffres, .resultat,
  .ponderation-barres, .avertissement, .graphique, blockquote,
  .etiquette, .bouton-lissage, .donnees-brutes summary { clip-path: none; }
}

/* =============================================================================
   COULEURS FORCÉES — EN FIN DE FEUILLE, impérativement.
   Une media query n'ajoute aucune spécificité : placée en tête, elle perdrait
   l'arbitrage par ordre source contre les règles équivalentes définies plus bas.
   Et `border-color` seul est un no-op sur un élément sans `border-style` :
   on écrit la forme complète.
   ============================================================================= */

@media (forced-colors: active) {
  .calque, .outil, .graphique, .table-enveloppe, .avertissement, .resultat > div {
    border: 1px solid CanvasText;
    background: Canvas;
  }
  .etiquette { border: 1px solid CanvasText; color: CanvasText; }
  .chiffre-cle, .sur-titre, .outil-titre, .commande output { color: CanvasText; }
  .poids { background: CanvasText; forced-color-adjust: none; }
  .grille line, .seuil { stroke: CanvasText; }
  .graduation { fill: CanvasText; }
  .courbe { stroke: CanvasText; }
  .bougie .corps, .bougie .meche { stroke: CanvasText; fill: Canvas; }
  .nav-parcours a[aria-current="page"] { border: 1px solid CanvasText; }
  blockquote { border-left: 2px solid CanvasText; }
  /* La trame de fond est purement décorative : en couleurs forcées elle
     deviendrait un quadrillage plein contraste par-dessus la page. */
  body::after { display: none; }
  /* Et la coupe d'angle rognerait la bordure système sur deux coins : un cadre
     ouvert se lit comme un défaut de rendu, pas comme un biseau. */
  .calque, .outil, .table-enveloppe, .grille-chiffres, .resultat,
  .ponderation-barres, .avertissement, .graphique, blockquote,
  .etiquette, .bouton-lissage, .donnees-brutes summary { clip-path: none; }
}
