/* ==========================================================================
   Orizan IA · site vitrine, révision du 2026-09-07

   IDÉE MATÉRIELLE
   Le site est un relevé qu'on parcourt à la main : le papier est réglé, le
   texte est calé à gauche sur cette réglure, et partout où quelque chose se
   déroule dans le temps (les quatre temps de l'audit, les neuf maillons de la
   chaîne) le pointeur devient une tête de lecture qui encre ce qui est passé
   et laisse en attente ce qui ne l'est pas.

   Ce qui a changé par rapport à la version précédente :
   - la réglette graduée de la marge gauche est supprimée, avec ses cotes ;
   - le monospace recule fortement : il ne porte plus que les nombres et les
     index techniques, plus aucun texte de lecture, aucun libellé, aucun
     intertitre, aucun bouton ;
   - la tête de lecture liée à la souris remplace la réglette, sur deux
     sections seulement.

   Règles tenues ici :
   - aucune couleur en dur, tout passe par les jetons de :root
   - aucun style en ligne dans le HTML
   - angles droits, séparations au filet d'un pixel, aucune ombre portée
   - grilles asymétriques, jamais 50/50, rien n'est centré
   - aucun tiret long, y compris dans les `content` de CSS
   - zéro requête vers un domaine tiers
   ========================================================================== */

/* ---------- Polices, servies par le domaine ----------------------------- */

@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-800.woff2") format("woff2");
  font-weight: 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Plex Sans";
  src: url("../fonts/plexsans-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Plex Sans";
  src: url("../fonts/plexsans-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
/* Le monospace reste chargé : il porte encore tous les nombres du site, qui
   sont l'argument de la marque. Il ne porte plus rien d'autre. */
@font-face {
  font-family: "Plex Mono";
  src: url("../fonts/plexmono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

/* ---------- Jetons ------------------------------------------------------ */

:root {
  /* Clair : le sol par défaut */
  --paper:      #EFF3F4;
  --surface:    #FFFFFF;
  --surface-2:  #F6F8F9;
  --ink:        #0E171E;
  --ink-2:      #45555F;
  --ink-3:      #76858F;
  --rule:       #C7D2D8;
  --rule-soft:  #DFE6EA;

  /* Nuit : sections en pleine largeur, jamais la page entière */
  --night:      #0B1319;
  --night-2:    #13212A;
  --night-ink:  #DDE6EA;
  --night-ink2: #93A4AE;
  --night-rule: #24343E;

  /* Accent : un seul, décliné */
  --accent:      #0B5563;
  --accent-lift: #35A0B2;
  --accent-wash: #E4EEF0;
  --signal:      #B4531A;   /* uniquement les avertissements */

  /* Rôles locaux, recalculés dans les sections nuit.
     Aucun composant ne lit --ink ou --night-ink directement. */
  --fond:        var(--paper);
  --encre:       var(--ink);
  --encre-2:     var(--ink-2);
  /* Le jeton de charte --ink-3 (#76858F) ne fait que 3,40:1 sur --paper, sous
     le 4,5:1 que WCAG AA demande pour du texte courant. Ce rôle porte les
     légendes de photo, les index de la chaîne, les en-têtes du tableau de prix
     et ses précisions. Le jeton de charte n'est pas touché : c'est le rôle qui
     est assombri, par un mélange avec --ink. 4,64:1, et la hiérarchie tient,
     --encre-2 restant plus foncé à 6,92:1. Revue du 2026-09-07, conservé. */
  --encre-3:     color-mix(in srgb, var(--ink-3) 80%, var(--ink));
  --filet:       var(--rule);
  --filet-doux:  var(--rule-soft);
  --vif:         var(--accent);
  --carte:       var(--surface);
  /* Même raison : --signal brut fait 4,48:1 sur --paper et 4,00:1 sur le lavis
     à 9 % que .avertit et .form-etat--erreur posent derrière lui. Mélangé à
     --ink : 5,30:1 sur le papier, 4,74:1 sur le lavis. Revue du 2026-09-07. */
  --alerte:      color-mix(in srgb, var(--signal) 88%, var(--ink));

  --f-display: "Archivo", "Arial Black", system-ui, sans-serif;
  --f-body:    "Plex Sans", system-ui, sans-serif;
  --f-mono:    "Plex Mono", ui-monospace, Consolas, monospace;

  /* Échelle typographique */
  --t-index: 0.6875rem;
  --t--1:   0.8125rem;
  --t-0:    1.0625rem;
  --t-1:    1.1875rem;
  --t-2:    clamp(1.35rem, 1.05rem + 1.3vw, 2rem);
  --t-3:    clamp(1.9rem, 1.25rem + 2.6vw, 3.1rem);
  --t-4:    clamp(2.3rem, 1.1rem + 4.6vw, 4.5rem);

  /* Échelle d'espacement, base 8 */
  --e-1: 0.5rem;
  --e-2: 1rem;
  --e-3: 1.5rem;
  --e-4: 2.5rem;
  --e-5: 4rem;
  --e-6: 6rem;

  /* Structure. La marge gauche n'est plus une réglette graduée, c'est une
     simple respiration : la page reste ancrée à gauche, rien n'est centré. */
  --marge:  clamp(1.15rem, 5.5vw, 5.5rem);
  --mesure: 62ch;
  --large:  74rem;
  --entete: 3.25rem;

  --detente: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ---------- Base -------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--entete) + 2rem);
  -webkit-text-size-adjust: 100%;
  /* La chaîne de traitement sort volontairement de la colonne de texte et va
     jusqu'aux deux bords de la fenêtre. Elle est coupée au bord, elle ne crée
     jamais de défilement latéral. */
  overflow-x: clip;
}

body {
  margin: 0;
  background-color: var(--paper);
  /* La réglure de la feuille de relevé : des filets horizontaux très faibles,
     tous les 32 px. Le fond est une décision, pas un réglage par défaut. */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0 31px,
    color-mix(in srgb, var(--rule) 30%, transparent) 31px 32px
  );
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--t-0);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  text-wrap: balance;
  color: var(--encre);
}
h3, h4 { font-weight: 600; letter-spacing: -0.02em; line-height: 1.18; }
/* Les corps de h1 et h2 sont posés explicitement, et non laissés à la feuille
   par défaut du navigateur, qui fait varier la taille d'un h1 selon son
   imbrication et selon la version. */
h1 { font-size: var(--t-3); }
h2 { font-size: 1.5em; }
p, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible, [tabindex]:focus-visible, input:focus-visible,
textarea:focus-visible, summary:focus-visible {
  /* --accent-lift ne fait que 2,76:1 sur --paper, or un indicateur de focus doit
     atteindre 3:1 (WCAG 2.2, critère 1.4.11). --vif suit le rôle de la section,
     donc --accent en clair (7,54:1) et --accent-lift en nuit (6,08:1), qui
     restent lisibles des deux côtés. Revue du 2026-09-07, conservé. */
  outline: 2px solid var(--vif);
  outline-offset: 3px;
}
::selection { background: var(--accent); color: var(--night-ink); }

/* Le lien d'évitement. Il ne se voit qu'au focus. Il n'est pas masqué par
   `display: none`, qui le retirerait du parcours clavier et lui ôterait tout
   son objet. Revue du 2026-09-07, conservé. */
.evitement {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t--1);
}
.evitement:focus {
  left: 0;
  padding: 0.7rem 1rem;
  background: var(--ink);
  color: var(--paper);
}
/* La cible du lien reçoit le focus par programme. Un anneau autour de tout le
   corps de la page serait un artefact, pas un repère. */
main[tabindex="-1"]:focus, main[tabindex="-1"]:focus-visible { outline: none; }
main[tabindex="-1"] { scroll-margin-top: var(--entete); }

/* ==========================================================================
   1. ENTÊTE
   ========================================================================== */

.entete {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.entete-barre {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  min-height: var(--entete);
  gap: var(--e-3);
  padding-inline: var(--marge);
}
.marque {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: -0.03em;
  white-space: nowrap;
}
.marque em { font-style: normal; color: var(--accent); margin-left: 0.28em; }

.sommaire {
  display: flex;
  gap: 1.25rem;
  overflow-x: auto;
  scrollbar-width: none;
  /* Affordance de défilement latéral quand le sommaire déborde, sans introduire
     de couleur : l'estompe est un masque, pas un dégradé peint. */
  mask-image: linear-gradient(to right, #000 0 90%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 0 90%, transparent 100%);
}
.sommaire::-webkit-scrollbar { display: none; }
.sommaire a {
  font-family: var(--f-body);
  font-size: var(--t--1);
  font-weight: 600;
  color: var(--ink-2);
  padding: 0.6rem 0;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: color 0.18s var(--detente), border-color 0.18s var(--detente);
}
.sommaire a:hover { color: var(--accent); border-bottom-color: var(--accent); }
/* Le sommaire défile latéralement, et `overflow-x: auto` force le navigateur à
   écrêter aussi verticalement : un anneau posé à 3 px à l'extérieur du lien
   serait coupé en haut et en bas. On le dessine à l'intérieur de sa boîte. */
.sommaire a:focus-visible {
  outline-offset: -2px;
  border-bottom-color: var(--vif);
  color: var(--accent);
}

/* ==========================================================================
   2. LA SECTION
   Plus de colonne de marge cotée : la page est ancrée à gauche par le seul
   retrait de --marge, et le corps s'arrête à --large sur grand écran.
   ========================================================================== */

.sec {
  border-top: 1px solid var(--filet);
  color: var(--encre);
}
.sec:first-of-type { border-top: 0; }
.sec--nuit {
  background-color: var(--night);
  --fond:       var(--night);
  --encre:      var(--night-ink);
  --encre-2:    var(--night-ink2);
  --encre-3:    var(--night-ink2);
  --filet:      var(--night-rule);
  --filet-doux: var(--night-rule);
  --vif:        var(--accent-lift);
  --carte:      var(--night-2);
  /* La terre brûlée est trop sombre sur fond nuit pour rester lisible.
     Elle est éclaircie vers l'encre de nuit, elle ne change pas de rôle. */
  --alerte:     color-mix(in srgb, var(--signal) 52%, var(--night-ink));
}

.corps {
  padding: var(--e-5) var(--marge);
  min-width: 0;
  max-width: var(--large);
}

/* Espacement de flux : une seule règle, pour que le rythme interne d'une
   section ne dépende jamais d'un réglage posé au cas par cas. */
.corps > * + * { margin-top: var(--e-3); }
.duo > div > * + * { margin-top: var(--e-2); }
.ligne > div > * + * { margin-top: 0.4rem; }
.corps > h2 + *, .corps > h3 + * { margin-top: var(--e-2); }
.mesure { max-width: var(--mesure); }

/* Variantes de rythme vertical. Les sections n'ont jamais la même hauteur. */
.corps--court  { padding-block: var(--e-3); }
.corps--long   { padding-block: var(--e-6); }
.corps--suite  { padding-block: var(--e-4) var(--e-6); }
/* Le bloc qui annonce la chaine : il se termine juste au-dessus d'elle. */
.corps--intro  { padding-block: var(--e-6) var(--e-3); }

/* ==========================================================================
   3. ATOMES
   ========================================================================== */

.lede {
  font-size: var(--t-1);
  line-height: 1.52;
  color: var(--encre-2);
  max-width: var(--mesure);
}
.texte { color: var(--encre-2); max-width: var(--mesure); }
.texte + .texte { margin-top: var(--e-2); }
.texte b, .lede b { color: var(--encre); font-weight: 600; }

.note {
  border-left: 2px solid var(--vif);
  padding-left: var(--e-2);
  font-size: var(--t--1);
  color: var(--encre-2);
  max-width: 64ch;
}
.note b { color: var(--encre); font-weight: 600; }
/* Un lien dans une note doit se voir comme un lien. Le cas se présente sur la
   page 404, où l'adresse de contact est le seul recours du visiteur. */
.note a { color: var(--vif); border-bottom: 1px solid var(--vif); }

.avertit {
  border: 1px solid var(--alerte);
  border-left-width: 3px;
  padding: var(--e-2);
  font-size: var(--t--1);
  color: var(--encre-2);
  max-width: 68ch;
  background: color-mix(in srgb, var(--alerte) 9%, transparent);
}
.avertit b { color: var(--alerte); font-weight: 600; }

/* Boutons : rectangulaires, plats, sans dégradé, sans rebond. Ils étaient en
   monospace capitales, ce qui donnait le caractère « terminal » rejeté en
   révision 01. Ils sont désormais en corps gras, casse normale. */
.bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t--1);
  letter-spacing: 0.005em;
  padding: 0.68rem 1.1rem;
  border: 1px solid var(--encre);
  background: var(--encre);
  color: var(--fond);
  cursor: pointer;
  transition: background 0.18s var(--detente), color 0.18s var(--detente),
              border-color 0.18s var(--detente);
}
.bouton:hover { background: var(--vif); border-color: var(--vif); }
.bouton--filet {
  background: transparent;
  color: var(--encre);
  border-color: var(--filet);
}
.bouton--filet:hover { border-color: var(--vif); color: var(--vif); background: transparent; }
.bouton .fleche { transition: transform 0.18s var(--detente); }
.bouton:hover .fleche { transform: translateX(3px); }

.actions { display: flex; flex-wrap: wrap; gap: var(--e-1); }

/* ==========================================================================
   4. LE CHIFFRE COTÉ
   Le dernier emploi du monospace, et le seul qui compte : chaque nombre
   affiché porte sa source, révélée au survol et au focus. C'est l'argument
   de la marque rendu opérable, aucun chiffre sans provenance.
   ========================================================================== */

.ch {
  position: relative;
  font-family: var(--f-mono);
  font-size: 0.94em;
  color: var(--encre);
  border-bottom: 1px solid var(--vif);
  cursor: help;
  white-space: nowrap;
}
.ch-cote {
  position: absolute;
  top: calc(100% + 9px);
  left: 0;
  z-index: 6;
  display: block;
  width: max-content;
  max-width: min(24rem, 62vw);
  white-space: normal;
  font-family: var(--f-body);
  font-size: var(--t--1);
  line-height: 1.45;
  color: var(--fond);
  background: var(--vif);
  padding: 0.3rem 0.55rem;
  /* Masqué par l'opacité seule, jamais par `visibility` ni `display` : ces
     deux-là retirent l'élément de l'arbre d'accessibilité, et un lecteur
     d'écran perdrait la provenance du chiffre, qui est tout l'argument. */
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.16s var(--detente), transform 0.16s var(--detente);
  pointer-events: none;
}
/* La ligne d'attache : le geste de la cote, pas celui de l'infobulle. */
.ch-cote::before {
  content: "";
  position: absolute;
  left: 0;
  top: -9px;
  width: 1px;
  height: 9px;
  background: var(--vif);
}
.ch:hover .ch-cote,
.ch:focus-visible .ch-cote,
.ch:focus-within .ch-cote {
  opacity: 1;
  transform: translateY(0);
}
.ch--fin .ch-cote { left: auto; right: 0; }
.ch--fin .ch-cote::before { left: auto; right: 0; }

/* ==========================================================================
   5. OUVERTURE
   ========================================================================== */

.corps--ouverture {
  min-height: min(calc(100svh - var(--entete)), 46rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--e-3);
  padding-block: var(--e-5) var(--e-3);
}
.corps--ouverture > * + * { margin-top: 0; }
.titre-ouverture + .lede { margin-top: var(--e-3); }
.lede + .actions { margin-top: var(--e-4); }
.titre-ouverture {
  font-size: var(--t-4);
  max-width: 15ch;
  letter-spacing: -0.045em;
}
.titre-ouverture em { font-style: normal; color: var(--accent); }
.ouverture-bas {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--e-3);
  align-items: end;
  border-top: 1px solid var(--rule);
  padding-top: var(--e-2);
  font-size: var(--t--1);
  color: var(--encre-3);
}

/* ==========================================================================
   6. LA LISTE COTÉE
   Jamais des cartes égales : des lignes, indexées à gauche, de hauteur libre.
   Sert aux deux modalités de cadrage, aux quatre temps de l'audit, aux trois
   contreparties, et aux trois étapes de merci.html.
   ========================================================================== */

.lignes { border-top: 1px solid var(--filet); }
.ligne {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 9fr);
  gap: var(--e-1) var(--e-3);
  padding: var(--e-2) 0;
  border-bottom: 1px solid var(--filet-doux);
  align-items: baseline;
}
/* L'index de ligne portait un monospace en capitales espacées, qui se lisait
   comme une étiquette. Corps gras, casse normale, couleur d'accent : il se lit
   maintenant comme une durée, ce qu'il est. */
.ligne-cote {
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t--1);
  color: var(--vif);
}
/* Un h2 est accepté ici autant qu'un h3 : sur `merci.html`, les trois étapes
   suivent directement le h1 et doivent rester au niveau 2 pour que la
   hiérarchie des titres ne saute pas un cran. */
.ligne h2, .ligne h3, .ligne h4 {
  font-size: var(--t-1);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.18;
  margin-bottom: 0.35rem;
}
.ligne p { color: var(--encre-2); font-size: 0.9375rem; max-width: 58ch; }

/* ==========================================================================
   6bis. L'ÉCHELLE DES TROIS NIVEAUX
   Trois colonnes, mais pas trois cartes égales : le corps de texte reste posé
   sur le papier, sans boîte, et seule la tête change de masse d'un niveau au
   suivant. Papier nu, puis lavis, puis nuit. La progression est donc lisible
   avant même d'être lue, et elle est achromatique avant d'être colorée : ce qui
   décide de la lecture à distance est la quantité d'encre, pas la teinte.
   Procédé repris de la planche du post 01, validée le 2026-08-14.

   ⚠ L'index de niveau est en --encre-2 et non en --encre-3. Mesuré : sur un
   lavis d'accent, --encre-3 tombe sous le minimum de 4,5:1 exigé pour du petit
   texte, 4,39:1 sur --accent-wash. C'est exactement l'erreur relevée sur la
   première version de la planche. --encre-2 donne 6,92:1 sur le papier et
   5,20:1 sur le lavis retenu, --night-ink2 donne 7,28:1 sur la nuit.
   ========================================================================== */

.echelle {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--filet);
  border-bottom: 1px solid var(--filet);
}
.barreau { border-left: 1px solid var(--filet-doux); }
.barreau:first-child { border-left: 0; }
.barreau-tete {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: var(--e-2);
  border-bottom: 1px solid var(--filet-doux);
}
.barreau-num {
  font-family: var(--f-mono);
  font-size: var(--t-index);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.barreau-nom {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: var(--t-2);
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--encre);
}
.barreau-corps { padding: var(--e-2); }
.barreau-corps p { color: var(--encre-2); font-size: 0.9375rem; }
.barreau-corps p + p { margin-top: var(--e-2); }
.barreau-plafond b { color: var(--encre); font-weight: 600; }

/* Premier essai regardé à la capture : --accent-wash pur donne 1,06 de rapport
   avec le papier, c'est-à-dire rien. La marche 1 vers 2 n'existait pas et seule
   la marche 2 vers 3 se voyait. Le lavis est donc appuyé à 18 % d'accent, ce qui
   donne 1,33 avec le papier, une marche visible. Contrastes revérifiés sur ce
   fond : 12,18:1 pour le nom du niveau, 5,20:1 pour son index. */
.barreau--2 .barreau-tete { background: color-mix(in srgb, var(--accent) 18%, var(--paper)); }
.barreau--3 .barreau-tete { background: var(--night); border-bottom-color: var(--night); }
.barreau--3 .barreau-num { color: var(--night-ink2); }
.barreau--3 .barreau-nom { color: var(--night-ink); }

/* ==========================================================================
   7. LA PISTE VERTICALE
   Première des deux têtes de lecture. Elle court le long des quatre temps de
   l'audit : le pointeur descend la semaine, et ce qui est passé s'encre.
   Motivée par le propos, un audit est un parcours dans le temps.
   ========================================================================== */

.piste { position: relative; padding-left: var(--e-4); }
.piste::before {
  content: "";
  position: absolute;
  left: 5px; top: 0; bottom: 0;
  width: 1px;
  background: var(--filet);
}
.piste-encre {
  position: absolute;
  left: 4px; top: 0;
  width: 3px;
  height: var(--tete, 0px);
  background: var(--vif);
  transition: height 0.12s linear;
}
.piste-tete {
  position: absolute;
  left: 0; top: 0;
  width: 11px; height: 1px;
  background: var(--vif);
  opacity: 0;
  transform: translateY(var(--tete, 0px));
  transition: opacity 0.2s var(--detente);
}
.piste:hover .piste-tete { opacity: 1; }
.piste .lignes { border-top: 0; }
.piste .ligne { position: relative; }
.piste .ligne::before {
  content: "";
  position: absolute;
  left: calc(var(--e-4) * -1 + 2px);
  top: calc(var(--e-2) + 0.5rem);
  width: 7px; height: 7px;
  background: var(--fond);
  border: 1px solid var(--filet);
  transition: background 0.2s var(--detente), border-color 0.2s var(--detente);
}
.piste .ligne.est-atteint::before { background: var(--vif); border-color: var(--vif); }
.piste .ligne.est-atteint p { color: var(--encre); }

/* ==========================================================================
   8. LA CHAÎNE
   Seconde tête de lecture, et la rupture de grille de la page. Les neuf
   maillons sortent de la colonne de texte et vont d'un bord à l'autre de la
   fenêtre : une chaîne ne tient pas dans une colonne. Le pointeur la parcourt
   de gauche à droite, c'est le flux d'une demande, du mail reçu au plan de
   charge.
   ========================================================================== */

.chaine {
  position: relative;
  border-top: 1px solid var(--filet);
  border-bottom: 1px solid var(--filet);
}
.chaine-piste {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
}
.maillon {
  padding: var(--e-2) 0.55rem var(--e-2) 0.7rem;
  border-left: 1px solid var(--filet-doux);
  min-width: 0;
  cursor: default;
  transition: background 0.2s var(--detente);
}
.maillon:first-child { border-left: 0; padding-left: var(--marge); }
.maillon:last-child { padding-right: var(--marge); }
.maillon-num {
  display: block;
  font-family: var(--f-mono);
  font-size: var(--t-index);
  color: var(--encre-3);
  transition: color 0.2s var(--detente);
}
.maillon-nom {
  display: block;
  font-family: var(--f-body);
  font-weight: 600;
  font-size: 0.875rem;
  line-height: 1.25;
  color: var(--encre-2);
  margin-top: 0.3rem;
  transition: color 0.2s var(--detente);
}
.maillon.est-atteint .maillon-num { color: var(--vif); }
.maillon.est-atteint .maillon-nom { color: var(--encre); }
.maillon.est-courant { background: color-mix(in srgb, var(--vif) 12%, transparent); }
.chaine-tete {
  position: absolute;
  top: 0; left: 0;
  width: 1px;
  height: 100%;
  background: var(--vif);
  opacity: 0;
  transform: translateX(var(--tete, 0px));
  transition: opacity 0.2s var(--detente);
  pointer-events: none;
}
.chaine:hover .chaine-tete { opacity: 1; }
.chaine-dit {
  border-top: 1px solid var(--filet-doux);
  padding: 0.7rem var(--marge);
  font-size: var(--t--1);
  color: var(--encre-2);
  min-height: 3.1rem;
}
.chaine-dit b { color: var(--encre); font-weight: 600; }

/* La chaîne est devenue le dernier élément de la section exemple : les trois
   blocs qui la suivaient sont retirés (révision 02, point 5.3). Sans ce pied,
   son filet inférieur viendrait buter contre la bascule vers la section claire
   et la masse nuit se terminerait au ras du texte. */
#exemple { padding-bottom: var(--e-5); }

/* ==========================================================================
   9. LA VUE (photographie)
   Traitement unique : luminosité de l'image posée sur un aplat pétrole, puis
   trame horizontale. Aucun outil d'image n'étant disponible, tout est en CSS,
   et la trame rend la définition d'origine indifférente. C'est aussi le
   traitement prévu pour le portrait : un rectangle du même système,
   surtout pas une vignette ronde détourée avec une ombre portée.
   ========================================================================== */

.vue {
  position: relative;
  overflow: hidden;
  background: var(--accent);
  border: 1px solid var(--filet);
}
.vue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.22) brightness(0.96);
  mix-blend-mode: luminosity;
  opacity: 0.92;
}
.vue::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0 2px,
    color-mix(in srgb, var(--night) 45%, transparent) 2px 3px
  );
  pointer-events: none;
}
.vue--bande { aspect-ratio: 16 / 5; }
.vue--haute { aspect-ratio: 4 / 5; }

/* Le portrait s'affiche en clair, et il est la seule vue du site à échapper
   entièrement au traitement.

   Révision 02, point 4.1 : le filtre posé par-dessus est rejeté. Sont
   donc retirés le virage pétrole, qui était cuit dans le fichier, ET la trame
   posée en CSS par-dessus : la trame est précisément ce qui était « par-dessus »
   et elle tombe sous le même verdict. Le fichier servi est le recadrage 4:5
   brut, sans aucune retouche chromatique.

   Ce qui ne bouge pas, parce que c'est de la mise en page et non du traitement :
   le rectangle à angles droits, le filet d'un pixel, le format 4:5, le calage à
   gauche sur la réglure, la légende factuelle en dessous. Toujours aucune
   vignette ronde détourée, aucune ombre portée, aucune lueur.

   Le fond n'est plus la nuit mais la surface claire : l'image est opaque et
   couvre tout le cadre, ce fond n'est visible qu'avant son chargement, et une
   plaque sombre qui clignote une fraction de seconde dans une page claire se
   remarque plus que le gain qu'elle apporte. */
.vue--portrait { background: var(--surface-2); }
.vue--portrait img {
  filter: none;
  mix-blend-mode: normal;
  opacity: 1;
}
.vue--portrait::after { content: none; }
.vue-legende {
  font-family: var(--f-body);
  font-size: var(--t--1);
  color: var(--encre-3);
  padding-top: 0.5rem;
  border-top: 1px solid var(--filet-doux);
  margin-top: 0.5rem;
  max-width: 44ch;
}

/* ==========================================================================
   10. GRILLES ASYMÉTRIQUES
   ========================================================================== */

.duo { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--e-4); align-items: start; }
.duo--inverse { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }

/* ==========================================================================
   11. LA GRILLE DE PRIX
   Un tableau, pas trois cartes égales : une grille tarifaire se lit en
   colonnes alignées, et c'est aussi la structure la plus lisible pour un
   lecteur d'écran.
   ========================================================================== */

.prix { width: 100%; border-collapse: collapse; text-align: left; }
.prix caption { text-align: left; }
.prix th, .prix td {
  border-bottom: 1px solid var(--filet-doux);
  padding: var(--e-2) var(--e-2) var(--e-2) 0;
  vertical-align: top;
}
.prix thead th {
  font-family: var(--f-body);
  font-size: var(--t--1);
  font-weight: 600;
  color: var(--encre-3);
  border-bottom-color: var(--filet);
  padding-bottom: 0.5rem;
}
.prix tbody th {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-1);
  letter-spacing: -0.02em;
  width: 22%;
}
.prix td:first-of-type { color: var(--encre-2); font-size: var(--t--1); width: 46%; }
.prix .montant {
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t-0);
  color: var(--encre);
  white-space: nowrap;
}
/* La précision est une classe nommée, pas un `span` attrapé au vol : un
   sélecteur large écraserait le composant .ch imbriqué et les chiffres
   retomberaient à la taille de la légende. Erreur rencontrée deux fois. */
.prix .precision {
  display: block;
  font-family: var(--f-body);
  font-size: var(--t--1);
  line-height: 1.5;
  color: var(--encre-3);
  white-space: normal;
  margin-top: 0.3rem;
}

/* ==========================================================================
   12. LE FORMULAIRE
   ========================================================================== */

.contact-grille { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--e-4); align-items: start; }
.garanties { border-top: 1px solid var(--filet); }
.garanties li {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--filet-doux);
  font-size: var(--t--1);
  color: var(--encre-2);
  display: grid;
  grid-template-columns: 1.25rem 1fr;
  gap: 0.5rem;
}
/* Le marqueur était un tiret long. La charte l'interdit dans tout texte
   affiché, et un ::before est du texte affiché. Point médian, qui est déjà le
   séparateur du site. Revue du 2026-09-07, conservé. */
.garanties li::before { content: "\00B7"; color: var(--vif); }

.form { display: grid; gap: var(--e-2); }
.champ { display: grid; gap: 0.3rem; }
/* Les libellés étaient en monospace capitales : c'est exactement le style
   rejeté en révision 01. Corps gras, casse normale. */
.champ label {
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t--1);
  color: var(--encre-2);
}
.champ input, .champ textarea {
  font-family: var(--f-body);
  font-size: var(--t-0);
  color: var(--encre);
  background: var(--carte);
  border: 1px solid var(--filet);
  border-radius: 0;
  padding: 0.65rem 0.7rem;
  width: 100%;
  transition: border-color 0.18s var(--detente);
}
.champ input:focus, .champ textarea:focus { border-color: var(--vif); }
.champ textarea { resize: vertical; }
.pot { position: absolute; left: -9999px; }
.form-pied { font-size: var(--t--1); color: var(--encre-2); }
.form-pied a { color: var(--vif); border-bottom: 1px solid var(--vif); }

/* ==========================================================================
   13. PIED DE PAGE
   ========================================================================== */

.pied {
  --fond:    var(--night);
  --encre:   var(--night-ink);
  --encre-2: var(--night-ink2);
  --encre-3: var(--night-ink2);
  --filet:   var(--night-rule);
  --vif:     var(--accent-lift);
  background: var(--night);
  color: var(--night-ink);
}
.pied-corps { padding: var(--e-4) var(--marge); max-width: var(--large); }
.pied-grille {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 3fr) minmax(0, 4fr);
  gap: var(--e-3);
  padding-bottom: var(--e-3);
  border-bottom: 1px solid var(--night-rule);
  font-size: var(--t--1);
  color: var(--night-ink2);
}
.pied-grille b { color: var(--night-ink); font-weight: 600; display: block; }
.pied-grille a { color: var(--accent-lift); border-bottom: 1px solid var(--accent-lift); }
.pied-bas {
  padding-top: var(--e-2);
  font-size: var(--t--1);
  color: var(--night-ink2);
  max-width: 78ch;
}

/* ==========================================================================
   14. RÉVÉLATION AU DÉFILEMENT
   Discrète : un déplacement de 10 px. Pas de fondu vers le haut générique.
   ========================================================================== */

.js .revele { opacity: 0; transform: translateY(10px); }
.js .revele.est-vu {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s var(--detente), transform 0.5s var(--detente);
}

/* ==========================================================================
   15. BASCULE 60rem
   ========================================================================== */

@media (max-width: 60rem) {
  :root { --entete: 3rem; }
  html { scroll-padding-top: 7rem; }

  .entete-barre {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto auto;
    gap: var(--e-2);
  }
  .marque { grid-row: 1; }
  .entete .bouton { grid-row: 1; grid-column: 2; justify-self: end; }
  .sommaire {
    grid-row: 2;
    grid-column: 1 / -1;
    border-top: 1px solid var(--rule-soft);
    gap: 1rem;
  }
  .sommaire a { padding-block: 0.45rem; }

  .corps { padding-inline: var(--marge); }
  .corps--long { padding-block: var(--e-5); }
  .corps--suite { padding-block: var(--e-3) var(--e-5); }

  .duo, .duo--inverse, .contact-grille, .ouverture-bas, .pied-grille {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Quand la grille se replie, le portrait hérite de toute la largeur de la
     colonne et devient une affiche de 750 px de haut qui repousse le titre de
     la section hors de l'écran. On le borne : il reste un portrait, calé à
     gauche sur la réglure comme le reste, et il coûte trois fois moins de
     hauteur sur une page qu'on cherche justement à raccourcir. */
  .vue--portrait { max-width: 19rem; }
  #profil .vue-legende { max-width: 19rem; }
  .ligne { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
  /* L'échelle tient encore sur trois colonnes à 768 px : les trois textes sont
     courts et le nom du niveau, le plus long étant « Connecter », entre dans la
     colonne. Elle ne se replie donc qu'à 46rem, dans le bloc suivant. */

  /* La chaîne ne tient pas sur neuf colonnes à 390 px. Elle se replie en trois
     rangées de trois : le flux se lit alors de gauche à droite puis de haut en
     bas, comme un texte. La tête de lecture, elle, n'a plus de sens sans
     pointeur : elle est retirée, et chaque maillon reste atteignable au doigt. */
  .chaine-piste { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .maillon { border-top: 1px solid var(--filet-doux); padding-inline: 0.6rem; }
  .maillon:first-child, .maillon:last-child { padding-inline: 0.6rem; }
  .maillon:nth-child(3n+1) { border-left: 0; }
  .maillon:nth-child(-n+3) { border-top: 0; }
  .chaine-tete { display: none; }
  .chaine-dit { padding-inline: var(--marge); }

  .titre-ouverture { max-width: none; }
  .corps--ouverture { min-height: 0; padding-block: var(--e-4); gap: var(--e-3); }

  /* Le tableau se déplie en blocs. Les largeurs en pourcentage portées par
     `.prix tbody th` et `.prix td:first-of-type` sont plus spécifiques que la
     règle générique : il faut les annuler nommément, sinon le libellé
     s'étrangle sur 22 % de la largeur. */
  .prix, .prix thead, .prix tbody, .prix tr, .prix th, .prix td { display: block; }
  .prix thead { display: none; }
  .prix tbody tr { border-bottom: 1px solid var(--filet); padding-block: var(--e-2); }
  .prix tbody th, .prix td, .prix td:first-of-type, .prix .montant {
    border-bottom: 0;
    padding: 0 0 0.5rem 0;
    width: auto;
  }
  .prix tbody th { font-size: var(--t-2); line-height: 1.1; }

  /* Les cotes longues ne tiennent pas sur une ligne étroite. Elles se coupent,
     mais jamais entre un nombre et son unité : c'est l'espace insécable étroit
     du HTML qui s'en charge. */
  .ch { white-space: normal; box-decoration-break: clone; -webkit-box-decoration-break: clone; }

  /* Une cote accrochée à un chiffre situé en fin de ligne s'ouvrait au-delà du
     bord droit et se coupait en plein mot. Sur écran étroit, elle quitte donc
     son ancrage et vient se poser en bas de la fenêtre, sur toute la largeur.
     Le masquage reste porté par la seule opacité, donc la source demeure dans
     l'arbre d'accessibilité. */
  .ch-cote {
    position: fixed;
    top: auto;
    left: var(--marge);
    right: var(--marge);
    bottom: var(--marge);
    width: auto;
    max-width: none;
    transform: translateY(4px);
    z-index: 20;
  }
  .ch:hover .ch-cote,
  .ch:focus-visible .ch-cote,
  .ch:focus-within .ch-cote { transform: translateY(0); }
  /* Détachée du chiffre, la ligne d'attache ne relie plus rien. */
  .ch-cote::before { content: none; }
  .ch--fin .ch-cote { left: var(--marge); right: var(--marge); }
}

/* ==========================================================================
   15bis. BASCULE 46rem
   Seule l'échelle des trois niveaux a besoin de ce palier. À 390 px, trois
   colonnes donneraient dix-huit caractères par ligne. Elle se replie donc en
   trois rangées : la progression se lit alors de haut en bas, et la masse
   monte toujours dans le sens de la lecture.
   ========================================================================== */

@media (max-width: 46rem) {
  .echelle { grid-template-columns: minmax(0, 1fr); }
  .barreau { border-left: 0; border-top: 1px solid var(--filet-doux); }
  .barreau:first-child { border-top: 0; }
}

/* ==========================================================================
   16. MOUVEMENT NEUTRALISÉ
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .js .revele { opacity: 1; transform: none; }
  /* Les deux têtes de lecture disparaissent, et tout ce qu'elles auraient
     révélé est montré d'emblée : les quatre temps sont encrés, les neuf
     maillons sont dans leur état atteint. Rien n'est perdu, seul le geste
     de parcours est retiré. */
  .piste-tete, .piste-encre, .chaine-tete { display: none; }
  .piste .ligne::before { background: var(--vif); border-color: var(--vif); }
  .maillon .maillon-num { color: var(--vif); }
  .maillon .maillon-nom { color: var(--encre); }
  .maillon.est-courant { background: transparent; }
}

/* ==========================================================================
   17. LES ÉTATS DU FORMULAIRE
   Composés avec les jetons existants : confirmation en --vif, échec en
   --alerte, filet d'un pixel, angles droits, aucune ombre. L'état est une
   zone `role="status"` pour qu'un lecteur d'écran l'annonce sans voler le
   focus au visiteur.
   ========================================================================== */

.form-etat {
  font-size: var(--t--1);
  line-height: 1.6;
  color: var(--encre-2);
  border: 1px solid var(--vif);
  border-left-width: 3px;
  background: color-mix(in srgb, var(--vif) 7%, transparent);
  padding: var(--e-2);
  max-width: 62ch;
}
.form-etat b { color: var(--encre); font-weight: 600; }
.form-etat a { color: var(--vif); border-bottom: 1px solid var(--vif); }
.form-etat--erreur {
  border-color: var(--alerte);
  background: color-mix(in srgb, var(--alerte) 9%, transparent);
}
.form-etat--erreur b { color: var(--alerte); }
.form-etat--erreur a { color: var(--alerte); border-bottom-color: var(--alerte); }
.form-etat ul { margin-top: 0.4rem; }
.form-etat li { padding-left: 1.1rem; text-indent: -1.1rem; }
.form-etat li::before { content: "\00B7\00A0"; color: var(--alerte); }

/* Le champ fautif se signale lui-même, en plus du message. */
.champ input[aria-invalid="true"], .champ textarea[aria-invalid="true"] { border-color: var(--alerte); }
/* Pendant l'envoi : le formulaire s'estompe, le bouton refuse le double clic. */
.form[aria-busy="true"] { opacity: 0.6; }
.form[aria-busy="true"] .bouton { cursor: progress; }

/* ==========================================================================
   18. LE REGISTRE (mentions légales)
   ========================================================================== */

.registre { width: 100%; max-width: 58rem; border-collapse: collapse; text-align: left; }
.registre th, .registre td {
  border-bottom: 1px solid var(--filet-doux);
  padding: 0.7rem var(--e-2) 0.7rem 0;
  vertical-align: top;
}
.registre th {
  font-family: var(--f-body);
  font-size: var(--t--1);
  font-weight: 600;
  color: var(--encre-3);
  width: 32%;
}
.registre td { font-size: var(--t--1); color: var(--encre-2); }
.registre td a { color: var(--vif); border-bottom: 1px solid var(--vif); }

/* Le marqueur des mentions non renseignées. Il doit rester visible et se lire
   comme un trou dans le document, pas comme une valeur. Rien n'est inventé
   tant que la structure n'est pas immatriculée. C'est un marqueur technique,
   donc l'un des rares emplois de monospace qui subsiste. */
.acompleter {
  font-family: var(--f-mono);
  font-size: var(--t-index);
  letter-spacing: 0.02em;
  color: var(--alerte);
  border: 1px dashed var(--alerte);
  padding: 0.1rem 0.4rem;
  overflow-wrap: anywhere;
}

/* Le corps rédigé des pages secondaires : des paragraphes qui se suivent sans
   composant, à la mesure du texte courant. */
.redac { max-width: var(--mesure); color: var(--encre-2); }
.redac > * + * { margin-top: var(--e-2); }
.redac h3 { color: var(--encre); font-size: var(--t-1); margin-top: var(--e-3); }
.redac b { color: var(--encre); font-weight: 600; }
.redac a { color: var(--vif); border-bottom: 1px solid var(--vif); }
.redac ul li { padding-left: 1.15rem; text-indent: -1.15rem; }
.redac ul li::before { content: "\00B7\00A0"; color: var(--vif); }

@media (max-width: 60rem) {
  .registre, .registre tbody, .registre tr, .registre th, .registre td { display: block; }
  .registre tr { border-bottom: 1px solid var(--filet); padding-block: 0.6rem; }
  .registre th, .registre td { border-bottom: 0; width: auto; padding: 0 0 0.25rem 0; }
}
