/* Polices auto-hébergées (EX-10) : sous-ensemble latin + ponctuation française,
   converties depuis les fichiers variables Google Fonts. Fraunces est figée en
   SemiBold 600 (charte v3 §1, pas de faux-700) en gardant son axe de coupe
   optique ; Inter garde son axe de graisse de 400 à 700. */
@font-face {
  font-family: "Fraunces";
  src: url("fraunces-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("inter-var.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("inter-italic-400.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

:root {
  --encre: #1E2832;
  --texte: #3D4854;
  --gris: #8A929B;
  --filet: #E0D9C8;
  --ocre: #B7892D;
  --ocre-fonce: #8F6A1F;
  --ocre-clair: #D4A847;
  --blanc: #FFFFFF;
  /* Dérivés du filet clair pour les fonds encre : la palette reste fermée. */
  --filet-encre: rgba(224, 217, 200, 0.22);
  --champ-encre: rgba(224, 217, 200, 0.40);
  --champ-fond: rgba(255, 255, 255, 0.05);
  /* Fond sable très clair, pour l'encadré de la trajectoire. */
  --sable: rgba(224, 217, 200, 0.24);
  /* Corps du paragraphe d'ouverture : le premier texte sous le titre d'une
     page, accueil comprise. Une seule valeur, sinon l'accueil et les pages
     intérieures dérivent l'une de l'autre. */
  --corps-ouverture: 1.12rem;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* L'en-tête reste collé en haut : une section visée par une ancre s'arrête
   dessous, sinon son titre passerait derrière lui. Sa hauteur est mesurée par
   le script ; la valeur de repli sert le temps qu'il s'exécute, et sans lui. */
section[id], footer[id], .noeud[id] {
  scroll-margin-top: calc(var(--entete, 68px) + 18px);
}
body {
  font-family: "Inter", -apple-system, "Helvetica Neue", Arial, sans-serif;
  color: var(--texte);
  background: var(--blanc);
  line-height: 1.65;
  font-size: 16px;
}

/* ── Ossature ───────────────────────────────────────────────────────────────
   Padding et marges en propriétés longues : `.wrap` et `section` s'appliquent
   au même élément, un raccourci `padding` de l'un écraserait l'autre. */
.wrap, .wrap-large {
  margin-left: auto; margin-right: auto;
  /* Marges étroites : sur un portable, chaque pixel rendu au graphe agrandit
     ses libellés, qui sont dessinés à l'échelle du viewBox. */
  padding-left: clamp(20px, 2.4vw, 44px); padding-right: clamp(20px, 2.4vw, 44px);
}
.wrap, .wrap-large { max-width: 1560px; }
section { padding-top: clamp(52px, 6vw, 84px); padding-bottom: clamp(52px, 6vw, 84px); }

h1, h2 {
  font-family: "Fraunces", Georgia, "Times New Roman", serif;
  font-weight: 600;
  color: var(--encre);
  line-height: 1.1;
}
h1 { font-size: clamp(2rem, 4.8vw, 3.1rem); letter-spacing: -0.01em; max-width: 22ch; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.1rem); margin-bottom: 0.6em; max-width: 28ch; }
/* L'ocre se loge sur le segment-clé du titre. Le point final reste en encre
   (charte v3 §5, geste signature de ponctuation). */
.cle { color: var(--ocre); }
.chapeau { max-width: 62ch; font-size: 1.02rem; }
/* Le reset met toutes les marges à zéro : deux chapeaux qui se suivent ont
   besoin qu'on leur rende leur interligne de paragraphe. */
.chapeau + .chapeau { margin-top: 0.7rem; }

.bandeau-maquette {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gris);
  border-bottom: 1px solid var(--filet);
  padding: 0.5rem clamp(20px, 5vw, 48px);
}

/* ── En-tête ────────────────────────────────────────────────────────────── */
header { border-bottom: 1px solid var(--filet); position: sticky; top: 0; background: var(--blanc); z-index: 5; }
/* Propriétés longues : `.nav` et `.wrap` sont sur le même élément, un
   raccourci `padding` écraserait les marges latérales de la colonne. */
.nav { display: flex; align-items: baseline; justify-content: space-between;
       padding-top: 20px; padding-bottom: 20px; flex-wrap: wrap; gap: 12px; }
.marque {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600; font-size: 1.2rem;
  color: var(--encre); text-decoration: none;
}
.nav nav { display: flex; flex-wrap: wrap; gap: 0 24px; }
.nav nav a {
  font-size: 0.74rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gris); text-decoration: none;
  padding: 4px 0; border-bottom: 2px solid transparent;
}
.nav nav a:hover, .nav nav a:focus-visible { color: var(--encre); border-bottom-color: var(--ocre); }
.nav nav a[aria-current="page"] { color: var(--encre); border-bottom-color: var(--ocre); }

/* ── Ouverture de page ──────────────────────────────────────────────────── */
.hero { padding-top: clamp(40px, 4.4vw, 72px); padding-bottom: clamp(40px, 4.6vw, 68px); }
.titre-page { padding-top: clamp(48px, 6vw, 80px); padding-bottom: clamp(8px, 1vw, 16px); }
/* Les titres de page tiennent sur une ligne : la mesure serrée du h1 est faite
   pour le hero, ici elle coupait la phrase sans raison. */
.titre-page h1 { max-width: 48ch; }
/* Le rythme d'une page. Un blanc de section entier détachait les sections au
   point qu'elles se lisaient comme des diapositives, chacune finissant
   proprement au bas d'un écran. Resserré, le haut de la partie suivante
   dépasse toujours, et c'est lui qui donne envie de descendre. La règle vise
   les sections de premier rang, filles de `main` : celles qui s'emboîtent,
   les panneaux du graphe, gardent le rythme général. */
.hero ~ section, .titre-page ~ section {
  padding-top: clamp(32px, 3.2vw, 44px); padding-bottom: clamp(32px, 3.2vw, 44px);
}
/* La première section de la page se rapproche encore de ce qui l'ouvre : sans
   bouton pour la retenir, le blanc sous le hero devenait un trou plutôt qu'une
   respiration. Ces deux règles ont la même force que celle du dessus : elles
   viennent après, elles l'emportent. */
.hero + section { padding-top: clamp(16px, 2vw, 28px); }
.titre-page + section { padding-top: clamp(20px, 2.5vw, 32px); }
/* Le chapeau qui ouvre une page intérieure joue le même rôle que le « lede »
   de l'accueil : même corps. Les chapeaux qui annoncent une section en cours
   de page restent au corps de texte, ils n'ouvrent rien. */
.titre-page + section .chapeau { font-size: var(--corps-ouverture); }
/* Ouverture couplée : le titre à gauche, son chapeau à droite, aux proportions
   de la tête d'une section à sur-titre. Le titre prend alors ses deux lignes au
   lieu de barrer la page, et le chapeau n'est plus une colonne étroite posée
   sous un grand blanc. Pas de sur-titre ici à rattraper : les deux partent du
   même haut. */
.titre-couple {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 1fr);
  gap: 20px clamp(40px, 6vw, 110px); align-items: start;
  padding-bottom: clamp(10px, 1.2vw, 16px);
}
.titre-couple .chapeau { font-size: var(--corps-ouverture); max-width: 62ch; }
/* Le chapeau est monté à hauteur du titre : ce qui suit n'a plus le blanc d'un
   chapeau à laisser sous lui. La section ne garde donc aucune marge propre,
   d'autant que ce qui la suit porte presque toujours la sienne : une cellule a
   ses 26 à 38 px de rembourrage intérieur, qui suffisent à détacher la grille
   du chapeau. Après `.titre-page + section`, de même force, pour l'emporter
   sur elle. */
.titre-couple + section { padding-top: 0; }
/* Le chapeau et la scène forment un seul ensemble : pas de respiration de
   section entre les deux, elle passerait pour un trou. */
section.chapeau-scene { padding-bottom: clamp(16px, 2vw, 26px); }
/* La mesure de lecture du site : deux colonnes prises dans toute la largeur de
   `.wrap`, avec une gouttière centrale large. C'est elle qui tient la mesure,
   au lieu d'un plafond de largeur qui faisait décrocher le bord droit du
   chapeau de celui du graphe qu'il annonce. Tous les chapeaux y passent, celui
   d'une page comme celui d'une section : un paragraphe seul occupe la première
   colonne et a donc la largeur exacte des autres. Sans cette grille, un chapeau
   de section restait à `62ch` et se lisait plus étroit que celui du haut de
   page, à quelques centimètres de distance. */
.chapeau-colonnes {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem clamp(32px, 6vw, 120px); align-items: start;
}
.chapeau-colonnes .chapeau { max-width: none; }
/* Côte à côte, les deux chapeaux n'ont pas d'interligne à se rendre :
   l'interligne de paragraphe ferait démarrer la colonne de droite une
   ligne plus bas que celle de gauche. */
.chapeau-colonnes .chapeau + .chapeau { margin-top: 0; }
#cas-usage { padding-top: clamp(16px, 2vw, 26px); }
.adresse {
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ocre-fonce); margin-bottom: 1.4rem;
}
/* Les deux paragraphes portent un seul propos : même corps, aucun des deux
   n'est une note de bas de page de l'autre. */
/* Le hero occupe toute la colonne : sa mesure suit, sinon le texte fait une
   bande étroite au milieu d'un blanc qui n'a plus rien à retenir. */
.hero h1 { font-size: clamp(2rem, 5.2vw, 3.5rem); max-width: 30ch; }
.hero .lede, .hero .lede-suite { font-size: var(--corps-ouverture); max-width: 74ch; }
.hero .lede { margin: 1.5rem 0 1rem; }
.hero .lede-suite { margin-bottom: 1.2rem; }
/* Le chiffre porte sa source et son millésime (EX-02), en repère discret
   plutôt qu'en grand nombre : le registre du site n'est pas celui du deck. */
.hero .repere { font-size: 0.8rem; font-style: italic; color: var(--gris);
                max-width: 74ch; border-left: 2px solid var(--filet);
                padding-left: 12px; }
/* Le bouton du premier écran : assez d'air au-dessus pour ne pas coller au
   chapeau, assez peu pour rester dans le même bloc de lecture. */
.hero .hero-actions { display: flex; flex-wrap: wrap; gap: 12px;
                      margin-top: 30px; margin-bottom: 28px; }
.btn {
  display: inline-block; background: var(--encre); color: var(--blanc);
  text-decoration: none; font-weight: 600; font-size: 0.95rem;
  padding: 14px 28px; border: 1px solid var(--encre); cursor: pointer;
}
.btn:hover, .btn:focus-visible { background: var(--ocre-fonce); border-color: var(--ocre-fonce); }
/* La flèche va au lien, pas au bouton d'envoi du formulaire : celui-ci ne mène
   nulle part, il agit sur place. */
a.btn::after { content: " \2192"; }
.btn-secondaire { background: transparent; color: var(--encre); }
.btn-secondaire:hover, .btn-secondaire:focus-visible { color: var(--blanc); }

/* ── Accueil : le titre à gauche, le portrait et le laïus à droite ──────── */
/* Pas de mesure propre : la grille tient toute la largeur de `.wrap`, si bien
   que le portrait tombe sur le même bord droit que la troisième conviction.
   Sans cela, le hero s'arrêtait ~300 px avant elle et creusait un blanc. */
.hero-grille { display: grid; grid-template-columns: minmax(0, 1fr) clamp(300px, 25vw, 400px);
               gap: 24px clamp(48px, 5vw, 88px); align-items: start; }
/* L'encadré se centre sur la hauteur du texte : il est plus haut que lui, et
   posé en haut il laissait un pied de colonne vide sous le repère. */
.hero-grille .trajectoire { align-self: center; }
/* La colonne de droite n'a pas de sur-titre à laisser passer : le portrait
   remonte au ras de la ligne d'adresse (sa hauteur de ligne + sa marge). Le
   hero raccourcit d'autant, et les convictions remontent avec lui. */
.hero-grille .signature { margin-top: calc(-1 * (0.76rem * 1.65 + 1.4rem)); }
.signature .nom { margin-top: 18px; }
.signature .laius { font-size: 0.92rem; margin-top: 6px; }
.portrait { width: 100%; aspect-ratio: 4 / 5; border: 1px solid var(--filet); overflow: hidden; }
.portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Emplacement en attente du fichier : à retirer avec le <img> réel. */
.portrait-vide {
  height: 100%;
  display: flex; align-items: center; justify-content: center; text-align: center;
  background: var(--filet); color: var(--ocre-fonce);
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; padding: 12px;
}
.signature .nom { font-family: "Fraunces", Georgia, serif; font-size: 1.05rem; font-weight: 600; color: var(--encre); line-height: 1.25; }
.signature .nom .role { color: var(--ocre-fonce); }

/* ── Trajectoire du hero ────────────────────────────────────────────────────
   Les quatre temps de l'intégration, dans la colonne où vivait le portrait.
   Un encadré posé sur un fond sable, des points d'ocre reliés par un fil : le
   chemin se lit comme un chemin, pas comme une liste de plus. */
.hero-grille .trajectoire {
  border: 1px solid var(--filet); background: var(--sable);
  padding: clamp(28px, 2.8vw, 40px) clamp(24px, 2.4vw, 34px);
}
.trajectoire-titre {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ocre-fonce); margin-bottom: 24px;
}
.trajectoire ol { list-style: none; position: relative; }
/* Le fil court d'un point à l'autre, sans dépasser le premier ni le dernier. */
.trajectoire ol::before {
  content: ""; position: absolute; left: 9px; top: 14px; bottom: 14px;
  width: 1px; background: var(--filet);
}
.trajectoire li {
  position: relative; display: grid; grid-template-columns: 19px 1fr;
  gap: 18px; align-items: start; padding-bottom: 26px;
}
.trajectoire li:last-child { padding-bottom: 0; }
/* Le liseré reprend le fond de l'encadré : le point mange le fil au lieu de se
   poser dessus. */
.trajectoire .point {
  width: 19px; height: 19px; border-radius: 50%;
  background: var(--ocre); border: 5px solid var(--filet);
  box-shadow: 0 0 0 1px var(--ocre); margin-top: 4px;
}
.trajectoire .etape-nom {
  display: block; font-family: "Fraunces", Georgia, serif; font-weight: 600;
  font-size: 1.1rem; color: var(--encre); line-height: 1.2;
}
/* La glose se lit sous le nom du temps, en corps de texte : le gris discret y
   serait trop clair pour une phrase que l'on doit vraiment lire. */
.trajectoire .etape-dit { display: block; font-size: 0.86rem; margin-top: 3px; }
/* Le sommaire mène aux sections de la page. Le lien est posé sur le nom, mais
   son aire de clic couvre toute la ligne : on vise le point et la glose aussi
   bien que le mot. */
.trajectoire a { color: inherit; text-decoration: none; }
.trajectoire a::after { content: ""; position: absolute; inset: 0; }
.trajectoire li:hover .etape-nom,
.trajectoire li:focus-within .etape-nom { color: var(--ocre-fonce); }
.trajectoire li:hover .point,
.trajectoire li:focus-within .point { background: var(--ocre-fonce); box-shadow: 0 0 0 1px var(--ocre-fonce); }

/* ── Entrée en matière d'une section, quand elle porte un sur-titre ─────────
   Le titre à gauche, son chapeau à droite, alignés sur la même ligne de pied.
   Les sections sans sur-titre gardent la mise en page d'origine. */
.section-tete {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 1fr);
  gap: 20px clamp(40px, 6vw, 110px); align-items: start;
  margin-bottom: clamp(22px, 2.2vw, 32px);
}
.section-tete h2 { margin-bottom: 0; }
.section-tete .adresse { margin-bottom: 1rem; }
/* Le chapeau part du haut du titre, jamais plus haut. Aligné par le bas, un
   chapeau plus grand que le bloc titre prenait toute la hauteur de la ligne et
   commençait au-dessus du sur-titre. Il descend donc de la hauteur du
   sur-titre, ligne et marge comprises : même calcul que la signature du hero.
   Plus long que le titre, il déborde vers le bas, où c'est sans conséquence. */
/* Le contrepoint tient la moitié de la page, à la mesure de lecture près : à
   48 caractères il faisait une colonne étroite à côté d'un grand titre. */
.section-tete .chapeau {
  max-width: 62ch; padding-top: calc(0.72rem * 1.65 + 1rem);
}
/* L'introduction se lit sous la tête, dans le fil de la page, juste avant ce
   qu'elle annonce. */
.section-intro {
  max-width: 62ch; font-size: 1.02rem;
  margin-bottom: clamp(22px, 2.4vw, 34px);
}
/* La tête et l'introduction portent déjà leur respiration : ce qui les suit
   n'a pas à ajouter la sienne. */
.section-tete + .grille, .section-tete + .portes, .section-tete + .reperes,
.section-intro + .grille, .section-intro + .portes, .section-intro + .reperes { margin-top: 0; }

/* ── Portes vers les autres pages ───────────────────────────────────────── */
.portes { display: grid; gap: 36px 52px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-top: 40px; }
.portes.une { grid-template-columns: minmax(0, 420px); }
.porte { display: block; text-decoration: none; border-top: 2px solid var(--encre); padding-top: 16px; color: var(--texte); }
.porte h3 { font-family: "Fraunces", Georgia, serif; font-size: 1.2rem; font-weight: 600; color: var(--encre); margin: 10px 0; line-height: 1.25; }
.porte p { font-size: 0.95rem; max-width: 40ch; }
.porte .fleche { display: inline-block; margin-top: 14px; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ocre-fonce); }
.porte:hover, .porte:focus-visible { border-top-color: var(--ocre); }
.porte:hover h3, .porte:focus-visible h3 { color: var(--ocre-fonce); }

/* ── Convictions : même mise en forme que les portes (filet encre 2 px,
   numéro ocre, énoncé en Fraunces), mais ce ne sont pas des liens. */
.credo {
  list-style: none; counter-reset: credo; margin-top: 40px;
  display: grid; gap: 36px 52px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.credo li { counter-increment: credo; border-top: 2px solid var(--encre); padding-top: 16px; }
.credo li::before {
  content: counter(credo, decimal-leading-zero); display: block;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.18em; color: var(--ocre-fonce);
}
.credo .enonce {
  font-family: "Fraunces", Georgia, serif; font-size: 1.2rem; font-weight: 600;
  color: var(--encre); margin: 10px 0; line-height: 1.25;
}
.credo .enonce + p { font-size: 0.95rem; max-width: 40ch; }

.suite { margin-top: 26px; }
.suite a {
  font-size: 0.88rem; font-weight: 600; color: var(--ocre-fonce);
  text-decoration: none; border-bottom: 1px solid var(--filet); padding-bottom: 3px;
}
.suite a::after { content: " \2192"; }
.suite a:hover, .suite a:focus-visible { border-bottom-color: var(--ocre); }

/* ── Cellules ───────────────────────────────────────────────────────────── */
/* Les cellules forment un tableau à filets d'un pixel : le fond de la grille
   est le filet, chaque cellule repose sur du papier. Une seule ligne les
   sépare, au lieu d'un filet par carte et d'une gouttière entre elles. */
.grille {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1px; background: var(--filet); border: 1px solid var(--filet);
  margin-top: 44px;
}
/* Les cellules d'une même rangée partagent leurs quatre étages (ADR-020) : le
   numéro, le titre, le texte et le pied occupent chacun une piste de la grille,
   dimensionnée sur le plus haut de la rangée. Un titre d'une ligne ou un texte
   plus court laisse son blanc dessous, et l'étage suivant démarre à la même
   hauteur partout. Les réserves de lignes posées étage par étage n'en venaient
   à bout que pour la longueur qu'elles avaient prévue. */
.cellule {
  display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0;
  align-content: start; background: var(--blanc);
  padding: clamp(26px, 2.6vw, 38px);
}
/* Quatre cellules en carré : deux colonnes larges plutôt que quatre étroites.
   La mesure du texte s'ouvre d'autant, et la hauteur minimale donne au carré
   son assise même quand une cellule tient en deux lignes. */
/* Quatre cellules en carré, sur toute la colonne comme tout le reste de la
   page : rétrécie puis centrée, la matrice devenait la seule chose de la page
   à ne pas tomber sur les deux mêmes bords, et se lisait comme un accident.
   Le blanc se règle donc à l'intérieur des cellules, pas à leurs dépens : des
   marges intérieures qui suivent la fenêtre, et une mesure de texte élargie.
   La cellule paraît généreusement calée, là où elle paraissait à moitié vide. */
.grille.carre { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Marges intérieures dissymétriques : larges sur les côtés, où elles règlent
   le blanc, courtes en haut et en bas, où chaque pixel se paie en défilement.
   Ce carré tenait dans un écran, tête de section comprise, et c'est justement
   ce qui le faisait lire comme une diapositive : on en voyait la totalité sans
   rien voir de ce qui suit. Les quelques dizaines de pixels rendues ici sont
   celles qui laissent monter le sur-titre de la section suivante. */
.grille.carre .cellule {
  padding: clamp(16px, 1.8vw, 24px) clamp(28px, 5vw, 84px);
}
.grille.carre .cellule h3 { max-width: 26ch; }
.grille.carre .cellule p { max-width: 58ch; }
.num { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.18em; color: var(--ocre-fonce); }
/* Le titre d'une cellule est un énoncé, pas une étiquette : il se dit en
   Fraunces, comme les titres des convictions et des portes. */
.cellule h3 {
  font-family: "Fraunces", Georgia, serif; font-size: 1.32rem; font-weight: 600;
  color: var(--encre); margin: 14px 0 12px; line-height: 1.2; max-width: 20ch;
}
.cellule p { font-size: 0.95rem; max-width: 42ch; }
/* Les chantiers qui répondent à la situation, en pied de cellule, à la place
   qu'occupent les livrables d'un volet. Roman et non italique : ce sont des
   liens, et l'italique se lit mal souligné. L'étage partagé les fait partir
   de la même hauteur d'une cellule à l'autre. */
.chantiers {
  padding-top: 16px;
  font-size: 0.85rem; color: var(--gris); max-width: none;
}
.chantiers a {
  color: var(--ocre-fonce); text-decoration: none;
  border-bottom: 1px solid var(--filet);
}
.chantiers a:hover, .chantiers a:focus-visible {
  color: var(--encre); border-bottom-color: var(--ocre);
}
/* La cellule cliquable : le lien du titre s'étend à toute la cellule par son
   `::after`, et les chantiers passent au-dessus pour rester chacun cliquable.
   Le survol se dit comme sur une porte, par le titre qui passe à l'ocre. */
.cellule.cliquable { position: relative; }
.cellule-lien { color: inherit; text-decoration: none; }
.cellule-lien::after { content: ""; position: absolute; inset: 0; }
.cellule-lien:focus-visible { outline: none; }
.cellule-lien:focus-visible::after { outline: 2px solid var(--ocre); outline-offset: -2px; }
.cellule.cliquable:hover h3, .cellule-lien:focus-visible { color: var(--ocre-fonce); }
.cellule.cliquable .chantiers { position: relative; z-index: 1; }
/* Un lien posé dans un chapeau (la 404, les mentions légales) prend la même
   marque que ceux du pied de cellule, au lieu du bleu du navigateur. Limité à
   `main` : le chapeau du pied de page repose sur la bande encre. */
main .chapeau a {
  color: var(--ocre-fonce); text-decoration: none;
  border-bottom: 1px solid var(--filet);
}
main .chapeau a:hover, main .chapeau a:focus-visible {
  color: var(--encre); border-bottom-color: var(--ocre);
}
.livrables {
  font-style: italic; color: var(--ocre-fonce); font-size: 0.85rem;
  margin-top: 18px; border-top: 1px solid var(--filet); padding-top: 12px;
}

/* ── Les deux étapes de l'intégration (reprises du deck Opia) ───────────── */
.etapes ol { list-style: none; counter-reset: pas; margin-top: 6px; }
.etapes ol li {
  counter-increment: pas; position: relative; padding-left: 26px;
  padding-top: 9px; padding-bottom: 9px; font-size: 0.95rem;
  border-bottom: 1px solid var(--filet);
}
.etapes ol li::before {
  content: counter(pas) ".";
  position: absolute; left: 0; top: 9px;
  font-size: 0.85rem; font-weight: 700; color: var(--ocre-fonce);
}
.etapes ol li:last-child { border-bottom: none; }

/* ── Bandes encre (charnières : offre, contact) ─────────────────────────── */
.bande {
  background: var(--encre); color: var(--gris);
  padding-top: clamp(56px, 7vw, 88px); padding-bottom: clamp(56px, 7vw, 88px);
}
.bande h2, .bande h3 { color: var(--blanc); }
.bande .cle { color: var(--ocre-clair); }

/* ── À propos ───────────────────────────────────────────────────────────── */
/* Même gouttière que `.chapeau-colonnes` : la colonne de texte de la bio a
   ainsi la largeur des chapeaux des sections précédentes, sans plafond de
   mesure qui la ferait décrocher. */
/* Trois colonnes sous le titre, qui les couvre toutes : le visage, la parole,
   le moyen de joindre. Elles partent du même haut, celui du texte et non du
   nom. Le texte garde la mesure de lecture du site plutôt que d'occuper ce qui
   reste : à pleine largeur, la bio tenait en huit lignes à côté d'une photo
   deux fois plus haute, et laissait entre les deux un blanc que rien
   n'occupait. Réparti en trois, ce blanc devient deux gouttières. */
.propos {
  display: grid;
  grid-template-columns: clamp(200px, 17vw, 260px) minmax(0, 66ch) minmax(180px, 240px);
  justify-content: space-between; align-items: start;
  gap: 40px clamp(32px, 5vw, 96px); margin-top: 36px;
}
.propos p { margin-bottom: 1rem; }
/* La photo prend la hauteur du texte, littéralement : pas de proportion fixe
   ici, elle s'étire sur la ligne de la grille, dont la bio décide. Le cadrage
   suit tout seul (`object-fit: cover`), et le pied des deux colonnes n'est plus
   à deviner à quelques pixels près à chaque retouche du texte. Le plancher
   couvre le cas d'une bio très courte, où la photo deviendrait une bande. */
.propos .portrait { aspect-ratio: auto; align-self: stretch; min-height: 220px; }
/* Le cadre rogne en haut et en bas quand la bio est plus haute que la photo :
   ancrée au bord haut, la coupe emporte la chemise, jamais les cheveux. */
.propos .portrait img { object-position: top; }
/* Ce n'est plus un parcours : le filet d'encre qui ouvrait la liste sert
   maintenant de ligne de départ à la colonne de contact, à hauteur du haut du
   portrait et de la première ligne de la bio. */
.propos .parcours { margin-top: 0; }
.parcours { list-style: none; border-top: 2px solid var(--encre); padding-top: 16px; }
.parcours li { font-size: 0.95rem; padding: 8px 0; border-bottom: 1px solid var(--filet); }
.parcours li strong { color: var(--encre); }

/* ── Les quatre phases, pilotées depuis le texte ───────────────────────────
   Le chapeau nomme les quatre phases : survolées ou focalisées, elles
   estompent la carte hors de leur phase et marquent l'onglet correspondant ;
   cliquées, elles ouvrent son bloc. */
.phase-lien {
  /* Un span, pas un bouton : Firefox traite le bouton comme une boîte
     insécable et la ponctuation qui suit se retrouve seule sur sa ligne. */
  border-bottom: 1px dashed var(--ocre); cursor: pointer;
}
.phase-lien:hover, .phase-lien:focus-visible, .phase-lien.actif {
  color: var(--ocre-fonce); border-bottom-style: solid; outline: none;
}
/* ── Les quatre blocs en onglets ────────────────────────────────────────────
   Le graphe et le texte vivent dans le flux normal : plus d'épinglage ni de
   défilement forcé, donc plus de contrainte de hauteur. Le panneau actif prend
   la place qu'il lui faut. */
.onglets {
  display: flex; flex-wrap: wrap; gap: 0 8px;
  margin-top: 34px;
  border-bottom: 1px solid var(--filet);
}
.onglet {
  font-family: "Fraunces", Georgia, serif; font-weight: 600;
  font-size: clamp(0.98rem, 1.5vw, 1.15rem); color: var(--gris);
  background: none; border: none; cursor: pointer;
  padding: 10px 14px 12px; margin-bottom: -1px;
  border-bottom: 2px solid transparent; line-height: 1.25;
}
.onglet .num {
  display: inline-block; margin-right: 0.45rem; color: var(--gris);
  vertical-align: 0.15em;
}
.onglet:hover, .onglet:focus-visible { color: var(--encre); outline: none; }
.onglet:hover .num, .onglet:focus-visible .num { color: var(--ocre-fonce); }
.onglet[aria-selected="true"] { color: var(--encre); border-bottom-color: var(--ocre); }
.onglet[aria-selected="true"] .num { color: var(--ocre-fonce); }
/* Survol d'une étape dans le chapeau : ses deux onglets se signalent. */
.onglet.phase-visee { color: var(--ocre-fonce); }

/* Ce que vise le bloc choisi, entre les onglets et le graphe. Les quatre
   sous-titres occupent la même case de grille : le bandeau garde la hauteur du
   plus long, et le graphe ne saute pas quand on change d'onglet. Pas de mesure
   propre : sur la largeur de la page chacun tient sur une ligne, une mesure
   plus courte en renvoyait à la ligne et réservait une seconde ligne vide aux
   trois autres. */
.sous-titres { display: grid; margin-top: 18px; }
.sous-titre {
  grid-column: 1; grid-row: 1;
  font-size: 1rem; line-height: 1.55; color: var(--encre);
  visibility: hidden;
}
.sous-titre.actif { visibility: visible; }
body:not(.js) .sous-titres { display: none; }
/* Sans JavaScript, les onglets et leur bandeau disparaissent : chaque panneau
   reprend alors son nom et son sous-titre en tête. */
body.js .arret-tete { display: none; }
.arret-tete { margin-bottom: 22px; }
.arret-nom {
  font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.3rem;
  color: var(--encre); margin-bottom: 0.3rem;
}
.arret-tete p + p { color: var(--encre); }

/* Graphe à gauche, texte à droite : la hauteur de l'ensemble devient le plus
   grand des deux au lieu de leur somme, ce qui permet de tout voir d'un coup.
   Le texte y retrouve au passage la mesure de la charte. */
.carte-et-texte {
  /* 2fr / 1fr donnait une colonne de texte si étroite que les fiches
     descendaient 250 px sous le graphe : c'est elle qui fixait la hauteur du
     bloc. Élargie, elle se rapproche du bas du graphe et l'ensemble se voit
     d'un coup. Le graphe perd un peu de largeur, donc ses libellés un peu de
     corps : c'est ce nombre qu'il faut remonter s'ils deviennent trop petits. */
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 0 40px; align-items: start; margin-top: 26px;
}
/* Le sous-titre annonce ce que montre le graphe : il lui reste attaché. */
.sous-titres + .carte-et-texte { margin-top: 8px; }
/* Le renvoi occupe la case libre de la grille, sous la légende du graphe : la
   colonne de gauche s'arrête plus haut que le texte, et c'est là que le lien se
   lit, plutôt que loin en dessous à attendre la fin des fiches. La colonne de
   texte enjambe les deux rangées, le lien reste calé en haut de la seconde. */
.carte-et-texte > .panneaux { grid-column: 2; grid-row: 1 / span 2; }
/* Pas de marge propre : le renvoi garde les 36 px de `.suite`, ceux qui le
   séparent du contenu sur l'accueil. Une page se termine du même geste. */
.carte-et-texte > .suite { grid-column: 1; grid-row: 2; align-self: start; }

.arret { padding-top: 0; }
body.js .arret { display: none; }
/* Pas de `fill-mode` : avec `both`, le panneau reste à opacité zéro tant que
   l'animation n'a pas démarré, et un rendu capturé trop tôt le montre vide. */
body.js .arret.actif { display: block; animation: apparait 0.35s ease; }
@keyframes apparait { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  body.js .arret.actif { animation: none; }
  /* Les liens du sommaire sont des ancres ordinaires : le défilement doux du
     document doit, lui aussi, céder à la préférence du lecteur. */
  html { scroll-behavior: auto; }
}
body:not(.js) .onglets { display: none; }

.fiches { display: block; }
.recits .noeud + .noeud, .fiches .noeud + .noeud { margin-top: 22px; }
.recits .noeud h3, .fiches .noeud h3 {
  font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 1.1rem;
  color: var(--encre); margin-bottom: 0.5rem; line-height: 1.3;
  border-top: 2px solid var(--encre); padding-top: 0.55rem;
}
/* Fiches et paragraphes prennent toute la largeur du bloc, celle du graphe :
   filets et texte s'arrêtent au même endroit, sans vide à droite. */
.fiches .noeud p { font-size: 0.95rem; margin-bottom: 0.55rem; }
.fiches .noeud p:last-child { margin-bottom: 0; }
/* Le chantier dont la fiche est ouverte sur la carte se repère dans le texte. */
.fiches .noeud.vedette h3 { border-top-color: var(--ocre); color: var(--ocre-fonce); }
/* Une démonstration existe pour ce chantier. Les fiches ayant été resserrées à
   une phrase, la mention « (démo) » posée contre le titre ne se voyait plus :
   elle devient un appel, qui mène au contact puisque les démonstrations se
   jouent en rendez-vous. Bouton bordé et non plein : six fiches sur dix en
   portent un, et autant d'aplats d'encre écraseraient les fiches. */
.fiche-demo { margin-top: 14px; }
.fiche-demo a {
  display: inline-flex; align-items: baseline; gap: 7px;
  text-decoration: none; font-size: 0.82rem; font-weight: 600;
  color: var(--encre); border: 1px solid var(--filet); padding: 7px 14px;
}
.fiche-demo .lettre { color: var(--ocre-fonce); }
.fiche-demo a:hover, .fiche-demo a:focus-visible {
  background: var(--encre); border-color: var(--encre); color: var(--blanc);
}
/* Sur l'encre, l'ocre foncé n'a plus de contraste : c'est l'ocre clair que la
   charte réserve à ce fond. */
.fiche-demo a:hover .lettre, .fiche-demo a:focus-visible .lettre {
  color: var(--ocre-clair);
}

/* La section de la carte se passe du rythme vertical des sections de texte :
   le bloc est déjà haut, et ses 84 px de padding haut et bas s'ajoutaient à
   ceux des sections voisines. C'est ce clamp qu'il faut rouvrir pour lui rendre
   de l'air. */
#cas-usage { padding-top: clamp(24px, 2.6vw, 36px); padding-bottom: clamp(24px, 2.6vw, 36px); }

/* ── Carte des cas d'usage ──────────────────────────────────────────────── */
.carte-conteneur { display: none; }
body.js .carte-conteneur { display: block; }
svg.carte { display: block; width: 100%; height: auto; }
.axe { stroke: var(--gris); stroke-width: 1; }
.tendance { stroke: var(--filet); stroke-width: 2; fill: none; }
.axe-label {
  font-family: "Inter", sans-serif; font-size: 13px; fill: var(--gris);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.lien { stroke: var(--filet); stroke-width: 1.5; visibility: hidden; }
.lien.actif { stroke: var(--ocre); stroke-width: 2; visibility: visible; }
.boite { cursor: pointer; }
.boite:focus { outline: none; }
.boite text { font-family: "Inter", sans-serif; font-size: 13.5px; fill: var(--encre); }
.boite circle { fill: var(--blanc); stroke: var(--encre); stroke-width: 1.5; }
.boite.point circle { fill: var(--ocre); stroke: none; }
.boite.point .fond { fill: var(--blanc); stroke: none; opacity: 0.85; }
.boite.point:hover circle, .boite.point:focus circle { stroke: var(--encre); stroke-width: 2; }
.boite.point.selection circle { fill: var(--ocre-fonce); stroke: var(--encre); stroke-width: 2; }
.boite.point.selection text { font-weight: 600; }
.boite.point.dependance circle { fill: var(--blanc); stroke: var(--ocre); stroke-width: 2; stroke-dasharray: 4 3; }
.boite.point.estompe circle { fill: var(--filet); stroke: none; }
.boite.dependance text { fill: var(--ocre-fonce); }
.boite.estompe text { fill: var(--gris); }
/* Double chevron : la valeur du cas croît dans le temps. */
.chevrons { fill: none; stroke: var(--ocre-fonce); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.boite.estompe .chevrons { stroke: var(--filet); }
/* « (d) » à la suite du libellé du nœud : une démonstration existe pour ce
   chantier. */
.marque-demo { font-size: 12px; font-weight: 600; fill: var(--ocre-fonce); }
.boite.estompe .marque-demo { fill: var(--filet); }

/* Légende des deux signes de la carte : sans elle, deux glyphes muets. */
/* Comment lire la carte, posé contre elle plutôt que dans le chapeau. Italique
   et petit corps, comme les autres mentions secondaires du site (`.livrables`,
   le repère du hero) : elle annonce le dispositif, elle ne poursuit pas le
   propos. Elle prend la largeur de ce qu'elle annonce, bien au-delà de la
   colonne où le chapeau l'enfermait. */
.legende-lecture {
  font-style: italic; font-size: 0.92rem; color: var(--texte);
  margin-bottom: clamp(20px, 2.2vw, 30px);
}
/* Elle ne parle que du graphe : là où il ne se rend pas, elle promet une carte
   qui ne viendra pas. C'est le cas sans JavaScript, et sous 900 px. */
body:not(.js) .legende-lecture { display: none; }

.legende-carte {
  display: flex; flex-wrap: wrap; gap: 4px 26px; margin-top: 8px;
  font-size: 0.78rem; color: var(--gris);
}
.legende-carte .item { display: inline-flex; align-items: center; gap: 7px; }
.legende-carte .glyphe { width: 15px; flex: none; text-align: center; }
.legende-carte svg.glyphe { height: 15px; }
.legende-carte .lettre { font-weight: 600; color: var(--ocre-fonce); }


@media (max-width: 900px) {
  /* Le graphe ne se rend pas sur mobile (ADR-006) : réduit à des pastilles
     numérotées, il coûtait un aller-retour puce ↔ liste pour une lecture en
     position que l'écran ne permet plus. Les onglets et les fiches portent
     seuls le contenu, la légende n'a plus de signes à expliquer. */
  body.js .carte-conteneur { display: none; }
  .legende-lecture { display: none; }

  /* Sans le graphe, les quatre blocs deviennent le seul pilote de la page :
     ils passent d'une rangée d'entrées de menu à un pavé de quatre boutons,
     deux par ligne, et restent en haut de l'écran quand on descend dans les
     fiches. Sans cela le lecteur ne peut changer de bloc qu'en remontant
     jusqu'en haut de la page, et rien ne lui dit plus lequel il lit. La place
     est libre : sous ce seuil l'en-tête ne colle plus (ADR-014). */
  .onglets {
    position: sticky; top: 0; z-index: 4;
    display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
    /* Le fond de filet fait les séparateurs et rend la barre opaque : les
       fiches passent dessous sans transparaître. */
    background: var(--filet);
    border-top: 1px solid var(--filet); border-bottom: 1px solid var(--filet);
    margin-top: 24px;
    /* Jusqu'aux bords de l'écran : sinon le texte défilerait dans les marges
       de la colonne, de part et d'autre de la barre collée. */
    margin-left: calc(-1 * clamp(20px, 2.4vw, 44px));
    margin-right: calc(-1 * clamp(20px, 2.4vw, 44px));
  }
  /* L'en-tête ne colle plus ici : ce qui masque le haut
     de l'écran est la barre d'onglets, et elle seule. Sans cette marge, une
     fiche visée par un lien de l'accueil se rangeait derrière elle. */
  .noeud[id] { scroll-margin-top: calc(var(--onglets, 0px) + 14px); }

  .onglet {
    background: var(--blanc); margin-bottom: 0; text-align: left;
    font-size: clamp(0.92rem, 3.4vw, 1.08rem);
    padding: 11px 12px 12px;
  }
}

/* ── Contact ────────────────────────────────────────────────────────────── */
/* Deux voies hiérarchisées (ADR-012) : les coordonnées d'abord, c'est par là
   que le visiteur écrit depuis sa propre messagerie ; le formulaire ensuite,
   replié, pour le cas où aucune messagerie ne s'ouvre. Elles se tiennent à
   droite du titre, sur les colonnes des têtes de section : empilées sous le
   chapeau, elles ajoutaient une rangée entière à la hauteur du bloc. */
.contact-grille {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 1fr);
  gap: 28px 56px;
}
.contact-tete .chapeau { max-width: 52ch; }
/* Les voies tiennent la hauteur du titre et de son chapeau : le bouton part
   du haut des lettres de « Parlons-en. », le lien de secours finit sur la
   dernière ligne du chapeau. Le titre a au-dessus de ses capitales un blanc
   de 0,2 fois sa taille (Fraunces, interligne 1.1, mesuré le 14/09) : sans ce
   retrait, le bouton dépassait le titre de ce blanc. */
.contact-voies {
  display: flex; flex-direction: column; justify-content: space-between;
  padding-top: calc(clamp(1.5rem, 3.2vw, 2.1rem) * 0.2);
}
.coordonnees .ligne:first-child { margin-top: 0; }
.coordonnees a { color: var(--ocre-clair); font-weight: 600; text-decoration: none; }
.coordonnees a:hover, .coordonnees a:focus-visible { text-decoration: underline; }
.coordonnees .ligne { margin: 8px 0; font-size: 1rem; }
/* Le geste principal se voit : un bouton, pas une ligne de liste. */
.coordonnees .btn-mail {
  display: inline-block; margin-bottom: 8px; padding: 11px 22px;
  background: var(--ocre-clair); color: var(--encre);
  border: 1px solid var(--ocre-clair); font-weight: 600;
}
.coordonnees .btn-mail:hover, .coordonnees .btn-mail:focus-visible {
  background: var(--blanc); border-color: var(--blanc); text-decoration: none;
}

/* Le formulaire de recours. `details` natif : il s'ouvre sans JavaScript, et
   il poste pour de bon, donc il fonctionne sans lui. */
/* Pas de marge au-dessus : c'est la colonne étirée qui écarte le lien des
   coordonnées. Une marge fixe rendait la colonne plus haute que le chapeau. */
.secours { margin-top: 0; }
.secours > summary {
  cursor: pointer; color: var(--ocre-clair); font-weight: 600; font-size: 0.95rem;
  list-style: none;
}
.secours > summary::-webkit-details-marker { display: none; }
.secours > summary::before { content: "+ "; font-weight: 700; }
.secours[open] > summary::before { content: "– "; }
.secours > summary:hover, .secours > summary:focus-visible { color: var(--blanc); }
.secours-chapeau { font-size: 0.88rem; margin: 12px 0 18px; max-width: 46ch; }
.prise-contact label {
  display: block; font-size: 0.74rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gris); margin-bottom: 6px;
}
.prise-contact .requis { color: var(--ocre-clair); letter-spacing: 0.14em; }
.prise-contact input, .prise-contact textarea {
  width: 100%; font-family: "Inter", -apple-system, sans-serif; font-size: 0.95rem;
  color: var(--blanc); background: var(--champ-fond);
  border: 1px solid var(--champ-encre); padding: 11px 13px; line-height: 1.5;
}
.prise-contact textarea { resize: vertical; min-height: 108px; }
.prise-contact input:focus, .prise-contact textarea:focus { outline: none; border-color: var(--ocre-clair); }
.prise-contact input:invalid:not(:placeholder-shown) { border-color: var(--ocre); }
.prise-contact input::placeholder, .prise-contact textarea::placeholder { color: var(--gris); }
.prise-contact .champ + .champ { margin-top: 16px; }
.prise-contact .btn {
  margin-top: 18px; background: var(--ocre-clair); color: var(--encre);
  border-color: var(--ocre-clair); font-family: "Inter", -apple-system, sans-serif;
}
.prise-contact .btn:hover, .prise-contact .btn:focus-visible { background: var(--blanc); border-color: var(--blanc); }
.prise-contact .btn[disabled] { opacity: 0.6; cursor: default; }
/* Le champ leurre (EX-27). Sorti du flux plutôt que `display: none` : certains
   automates ignorent ce qui est caché de la façon la plus visible. */
.leurre {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}
/* Le retour d'envoi. Il survit à la disparition du formulaire : c'est le seul
   signal du visiteur, il ne doit pas partir avec lui. */
.accuse {
  margin-top: 18px; font-size: 0.95rem; font-weight: 600; color: var(--blanc);
  border-left: 3px solid var(--ocre-clair); padding-left: 14px;
}
.accuse.en-echec { border-left-color: var(--ocre); }
/* Aussi large que les champs au-dessus : bridé à 46 caractères, le texte
   revenait à la ligne bien avant le bord du champ de message. */
.repli { font-size: 0.82rem; margin-top: 14px; }
.mentions { color: var(--gris); font-size: 0.78rem; margin-top: 56px; border-top: 1px solid var(--filet-encre); padding-top: 20px; }
/* Sur la bande encre, un lien du texte courant garde la couleur de sa ligne et
   se signale par son soulignement : le bleu du navigateur n'y serait ni dans la
   palette ni lisible. */
.mentions a, .repli a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

@media (max-width: 1080px) {
  /* Trop étroit pour deux colonnes : le texte repasse sous le graphe. */
  .carte-et-texte { grid-template-columns: 1fr; gap: 30px; }
  .carte-et-texte > .panneaux, .carte-et-texte > .suite {
    grid-column: auto; grid-row: auto;
  }
  /* Le graphe reprend la pleine largeur : le chapeau n'a plus de largeur à
     tenir, ses deux paragraphes se relisent à la suite. */
  .chapeau-colonnes { grid-template-columns: 1fr; }
  /* Empilés : le portrait garde sa taille, il ne devient pas une affiche. */
  .propos { grid-template-columns: 1fr; gap: 28px; }
  /* Empilée, la photo n'a plus de colonne voisine dont prendre la hauteur :
     elle retrouve sa proportion et sa taille. */
  .propos .portrait { max-width: 260px; aspect-ratio: 4 / 5; align-self: start; }
  /* Trop étroit pour lire un chapeau à côté d'un titre : il repasse dessous,
     et n'a plus de sur-titre à rattraper. */
  .section-tete { grid-template-columns: 1fr; }
  .section-tete .chapeau { padding-top: 0; }
  /* Empilées sous le chapeau, les voies n'ont plus de titre à rejoindre. */
  .contact-grille { grid-template-columns: 1fr; }
  .contact-voies { padding-top: 0; }
  /* Même raison pour l'ouverture de page : le chapeau repasse sous le titre. */
  .titre-couple { grid-template-columns: 1fr; }
  /* Empilés de nouveau : l'interligne de paragraphe reprend son rôle. */
  .chapeau-colonnes .chapeau + .chapeau { margin-top: 0.7rem; }
}

@media (max-width: 900px) {
  header { position: static; }
  /* Le cartouche de trajectoire du hero devient du bruit sur un écran qu'on
     parcourt au pouce, et s'efface : il dit où aller dans une page qu'on
     descend d'un geste, et occupe un écran entier avant que la lecture
     commence. Rien n'est perdu, ses ancres mènent aux sections que le lecteur
     traverse de toute façon. Le menu de l'en-tête reste : c'est le seul chemin
     vers les autres pages. */
  .hero-grille .trajectoire { display: none; }
  /* Une colonne : le carré n'a plus la place de se tenir. */
  .grille.carre { grid-template-columns: 1fr; }
  .grille.carre .cellule { min-height: 0; }
  /* La bio d'abord, le visage ensuite. Un portrait de 260 px ouvrait la
     section par une affiche et repoussait le propos sous la ligne de
     flottaison, alors que c'est le propos qu'on vient lire et le visage qui
     l'accompagne. Il revient donc après le texte, en vignette, et les
     coordonnées se posent à côté de lui plutôt que dessous : la rangée porte
     ainsi tout ce qui dit qui est la personne, en un coup d'œil. */
  .propos { grid-template-columns: 112px minmax(0, 1fr); gap: 26px 18px; }
  .propos > .portrait { grid-column: 1; grid-row: 2; }
  .propos > .portrait + div { grid-column: 1 / -1; grid-row: 1; }
  .propos > .parcours { grid-column: 2; grid-row: 2; }
  /* La vignette reprend la proportion du portrait : plus de colonne dont
     prendre la hauteur, plus de plancher à tenir. */
  .propos .portrait {
    max-width: none; aspect-ratio: 4 / 5; min-height: 0; align-self: start;
  }
  /* Ce qui reste de largeur doit porter une adresse de trente-trois signes :
     corps réduit, lignes resserrées, et la coupure autorisée là où elle
     déborderait. */
  .propos .parcours li { font-size: 0.84rem; padding: 6px 0; }
  .propos .parcours a { overflow-wrap: anywhere; }

  /* Le portrait passe sous le titre, à sa taille naturelle. */
  .hero-grille { grid-template-columns: 1fr; gap: 36px; }
  /* Empilé, le portrait vient après le titre : plus rien à remonter. */
  .hero-grille .signature { margin-top: 0; max-width: 200px; }
}

/* ── Carrousel des pages sur téléphone ───────────────────────────────────────
   En dessous de ~470px les quatre entrées ne tiennent plus sur une ligne :
   « Contact » tombait seul en dessous et l'en-tête gagnait une troisième
   rangée. Elles se sont d'abord repliées derrière un bouton à trois barres,
   mais un menu fermé ne dit rien du site : il fallait l'ouvrir pour découvrir
   qu'il existe une page de cas d'usage et une page d'accompagnement (ADR-015).

   Elles prennent maintenant la rangée entière sous la marque, sur un rail qui
   se parcourt au pouce. La page lue est calée à gauche, les suivantes
   débordent du bord de l'écran, et ce débordement est l'annonce : on voit
   qu'il y a une suite avant même d'y toucher.

   Rien n'est conditionné au script, contrairement au menu qu'il remplace : un
   débordement horizontal se parcourt sans JavaScript, et les quatre entrées
   sont écrites en clair dans la page. Le script n'ajoute que deux finitions,
   amener la page lue au bord gauche et allumer les fondus. */
@media (max-width: 520px) {
  /* La marque se retrouve seule sur sa rangée : plus de bouton à aligner sur
     sa ligne de base, et le rail tient son propre écart en marge haute. */
  .nav { row-gap: 0; padding-top: 16px; padding-bottom: 10px; }
  /* Le rail va d'un bord à l'autre de l'écran, hors de la colonne de texte :
     ses entrées se coupent alors sur le bord de la fenêtre, ce qui se lit
     comme « ça continue », là où une coupe dans la marge se lirait comme une
     ligne tronquée. Le retrait rendu en `padding` garde la première entrée
     alignée sur la marque, et `scroll-padding` fait que le calage à gauche le
     respecte aussi. */
  .nav nav {
    /* Le retrait de la colonne, rendu d'un côté et repris de l'autre. Nommé
       une fois : les quatre longueurs qui suivent doivent rester égales, sans
       quoi le rail se décale de la marque ou déborde de travers. */
    --debord: clamp(20px, 2.4vw, 44px);
    /* Une base plus large que le parent : le rail passe forcément à la ligne
       suivante, et les marges négatives le posent bord à bord de l'écran. */
    flex-basis: calc(100% + 2 * var(--debord));
    flex-wrap: nowrap;
    gap: 0 22px;
    margin-top: 8px;
    margin-left: calc(-1 * var(--debord));
    margin-right: calc(-1 * var(--debord));
    padding-left: var(--debord);
    padding-right: var(--debord);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-left: var(--debord);
    scrollbar-width: none;
  }
  .nav nav::-webkit-scrollbar { display: none; }
  /* Chaque entrée reste d'un seul tenant : repliée sur deux lignes, elle ne se
     reconnaîtrait plus du coin de l'œil au bord de l'écran. Le calage par
     `proximity` plutôt que `mandatory` : le rail est court, un aimant ferme
     interdirait de s'arrêter entre deux entrées pour lire la suivante. */
  .nav nav a { white-space: nowrap; scroll-snap-align: start; }
  /* Fondus de bord, allumés par le script du seul côté où il reste quelque
     chose. En masque et non en dégradé peint par-dessus : l'en-tête n'a pas
     toujours un fond uni à imiter, la page défile dessous une fois passé le
     palier où il cesse de coller.

     Les deux côtés ne se valent pas. À gauche le fondu s'arrête au retrait,
     là où commence la page calée : elle se lit nette, seul ce qui la précède
     s'efface. À droite il mord plus loin, sur la fin du dernier libellé
     atteint : c'est cette lettre pâlie qui dit qu'il y a une suite.

     Le `black` des dégradés n'est pas une couleur de la charte et n'est pas
     peint : un masque ne lit que l'opacité de ce qu'on lui donne, opaque ici
     et transparent aux bords. */
  .nav nav[data-bords="gauche"] {
    -webkit-mask-image: linear-gradient(to right, transparent, black var(--debord));
    mask-image: linear-gradient(to right, transparent, black var(--debord));
  }
  .nav nav[data-bords="droite"] {
    -webkit-mask-image: linear-gradient(to left, transparent, black 30px);
    mask-image: linear-gradient(to left, transparent, black 30px);
  }
  .nav nav[data-bords="deux"] {
    -webkit-mask-image: linear-gradient(to right, transparent, black var(--debord), black calc(100% - 30px), transparent);
    mask-image: linear-gradient(to right, transparent, black var(--debord), black calc(100% - 30px), transparent);
  }
}

/* ── Cellules en carrousel sur téléphone ────────────────────────────────────
   Empilés, trois ou quatre pavés font autant d'écrans à faire défiler avant la
   suite de la page, et le dernier n'est jamais atteint. Posés côte à côte sur
   un rail horizontal, ils se parcourent d'un balayage du pouce et ne coûtent
   plus qu'un écran. Le rail seul ne dirait pas combien il y en a : la barre de
   repères, construite par le script depuis les numéros des cellules, les
   montre tous d'emblée et laisse aller droit au sien.

   Le carrousel est le seul endroit du site où le doigt défile latéralement, et
   c'est délibéré (ADR-014) : la page, elle, ne défile jamais de côté (EX-09).
   Sans JavaScript il n'y a ni barre ni rail, les pavés restent empilés, ce qui
   se lit parfaitement.

   Même palier que le reste de l'affichage étroit, celui où le graphe de la
   carte disparaît et où les grilles s'empilent : le rail se substitue à cet
   empilement, il n'a pas de seuil à lui. */
.reperes { display: none; }

@media (max-width: 900px) {
  /* Autant de colonnes que de pavés, toutes égales : trois volets ou quatre
     moments, la barre n'a pas à savoir combien elle en porte. */
  .reperes {
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
    gap: 1px; background: var(--filet);
    border: 1px solid var(--filet); border-bottom: 0;
    /* La barre prend la place de la grille : elle en reprend l'espacement,
       celui d'origine comme celui que lui laisse une tête de section. */
    margin-top: 44px;
  }
  /* Les repères reprennent la matière des cellules : du papier sur un fond de
     filet, l'ocre pour dire celui qu'on lit. Ils ne portent pas la classe
     `onglets` de la carte, qui est un tout autre objet : un vrai jeu d'onglets,
     dont un seul panneau est visible à la fois. */
  .reperes button {
    font: inherit; color: var(--gris); background: var(--blanc);
    border: 0; border-bottom: 2px solid transparent;
    padding: 9px 4px 7px; cursor: pointer; text-align: center;
    display: flex; flex-direction: column; align-items: center; gap: 1px;
  }
  .reperes .repere-num {
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.12em;
    color: var(--ocre-fonce);
  }
  /* Le nom suit la largeur de la fenêtre : à quatre colonnes sur un écran de
     360 px, « Industrialisation » n'a que quelques dizaines de pixels, et la
     césure vaut mieux qu'un mot coupé net. */
  .reperes .repere-nom {
    font-size: clamp(0.52rem, 2.3vw, 0.76rem); line-height: 1.25;
    hyphens: auto; overflow-wrap: break-word;
  }
  .reperes button[aria-current="true"] { color: var(--encre); border-bottom-color: var(--ocre); }
  .reperes button:focus-visible { outline: 2px solid var(--ocre); outline-offset: -2px; }

  /* Le filet d'un pixel qui séparait les cellules devient l'espace entre deux
     pavés du rail : on le voit passer pendant le balayage. */
  .grille.defile {
    display: flex; margin-top: 0;
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scrollbar-width: none;
  }
  .grille.defile::-webkit-scrollbar { display: none; }
  .grille.defile .cellule {
    flex: 0 0 100%; scroll-snap-align: start;
    padding: clamp(18px, 4vw, 26px) clamp(20px, 5vw, 32px);
  }
}

/* ── Changement de page au balayage ─────────────────────────────────────────
   Le rail des pages quitte l'écran dès qu'on descend, l'en-tête ne collant pas
   sous 900 px. Un balayage horizontal sur le contenu mène alors à la page
   suivante ou à la précédente (ADR-015). La page, elle, ne bouge pas d'un
   pixel pendant le geste : rien n'est translaté, EX-09 tient, et le bandeau
   collé de la page des cas d'usage ne perd pas son ancrage, ce qu'une
   transformation posée sur un de ses ancêtres lui aurait coûté.

   Tout le retour visuel tient donc dans cette pastille, qui entre par le bord
   d'où viendrait la page visée, à la vitesse du doigt. Elle porte le nom de la
   destination : le geste dit toujours où il mène avant d'être relâché. Passé
   le seuil, elle s'arme et prend le trait ocre, le même que la page courante
   dans le rail de l'en-tête. */
.saut-page {
  position: fixed;
  top: 50%;
  z-index: 20;
  --avancee: 0;
  pointer-events: none;
  background: var(--blanc);
  border: 1px solid var(--filet);
  border-bottom: 2px solid var(--filet);
  padding: 11px 16px 10px;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gris);
  white-space: nowrap;
}
/* Sortie de l'écran à zéro, posée contre son bord à un. */
.saut-page[data-cote="droite"] { right: 0; transform: translate(calc((1 - var(--avancee)) * 100%), -50%); }
.saut-page[data-cote="gauche"] { left: 0; transform: translate(calc((var(--avancee) - 1) * 100%), -50%); }
.saut-page.arme { color: var(--encre); border-bottom-color: var(--ocre); }
/* Geste abandonné : la pastille s'efface au lieu de disparaître d'un coup.
   C'est l'opacité qui s'anime et non la position, celle-ci étant tenue par une
   variable que le doigt écrivait image par image. */
.saut-page.rentre { opacity: 0; transition: opacity 0.18s ease; }

@media (prefers-reduced-motion: reduce) {
  .saut-page.rentre { transition: none; }
}
