/* Viordi — viordi.com · feuille unique, aucun framework, aucune ressource externe */

/* Police des titres : Barlow SemiBold (SIL OFL 1.1, github.com/jpt/barlow), hébergée ici.
   Aucune ressource externe. Licence : fonts/OFL.txt. */
@font-face {
  font-family: "Barlow";
  src: url("fonts/Barlow-SemiBold.woff") format("woff");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Barlow";
  src: url("fonts/Barlow-ExtraBold.woff") format("woff");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #1f2126;
  --muted: #6d6e73;
  --accent: #33465f;
  --paper: #ffffff;
  --rule: #e4e4e4;
  /* Le voile de l'en-tête au sommet de la page (papier à 78 %). */
  --head: rgba(255, 255, 255, 0.78);

  /* Le trait des six ronds de la page 3 : la « couleur foncée » de chaque
     module, celle de l'app (AppColors.swift : calendarDark, habitsDark,
     goalsDark, journalDark, ideasDark, visualizeDark). Les mêmes en mode nuit
     (demande du 11/10) : les pastels y sont retirés. */
  --m-cal: #00336d;
  --m-hab: #054d18;
  --m-goa: #7d0000;
  --m-jou: #d36500;
  --m-not: #3f1e82;
  --m-vis: #1c1c1e;

  /* La barre noire de l'accueil : sa distance au bord de l'écran, et la marge
     où commence le texte (le point de chapitre tient entre les deux). Les
     marges de l'accueil (celles-ci, --hpad, --hl, --hr) sont des mesures de
     cadre : en px × --zi, elles gardent leur place à l'écran quand la page est
     zoomée ; seul le contenu grossit (18/10). */
  --rail: max(calc(16px * var(--zi)), 2vw);
  --gutter: calc(var(--rail) + 16px * var(--zi));

  /* Le zoom de page du téléphone (17/10, repris le 18/10). Le réglage « aA »
     de Safari rétrécit la page en pixels CSS et grossit tout ce qui est en px.
     theme.js pose --z (largeur de l'appareil ÷ largeur de la page ; 1 sans
     zoom) et --zi (son inverse). --zi ne sert qu'au cadre : marges, barre,
     étiquettes des ronds. Le texte, lui, grossit. La classe .zoomed lâche les
     chapitres d'un écran pour qu'on puisse les lire. */
  --z: 1;
  --zi: 1;

  /* Hauteur de l'en-tête collant : --hh-base est la seule valeur (70 px, celle
     que l'en-tête a à l'écran) ; --hh, ce qu'elle occupe en pixels CSS de la
     page, est celle que lisent les écrans, le calage, le cadre des noms de
     chapitre et le script. Son trait de 2 px dessous s'ajoute (voir .rail).
     Le script relit --hh-base et --z à chaque « resize ». */
  --hh-base: 70px;
  --hh: calc(var(--hh-base) * var(--zi));

  /* Le bas de la barre (11/10) : un rond de --up avec un chevron la termine,
     --upg au-dessus du trait du pied de page (72 px de haut) ; 16 px au début,
     8 px depuis le 11/10 (« un peu fort haut » sur iPhone). La barre et les
     noms de chapitre s'arrêtent au-dessus du rond : les deux traits ne se
     croisent plus. --end : distance du bas de l'écran au bout de la barre. */
  --foot: calc(72px * var(--zi));
  --up: calc(30px * var(--zi));
  --upg: calc(8px * var(--zi));
  --end: calc(var(--foot) + var(--upg) + var(--up));

  /* Les surfaces que le navigateur dessine lui-même (barres de défilement,
     sélection) suivent le thème, clair ou sombre — celui de l'appareil, tant
     que le visiteur n'a pas choisi avec le bouton rond de l'en-tête. */
  color-scheme: light dark;

  /* Police des titres et du logotype ; le texte courant reste en police système. */
  --display: "Barlow", "Bahnschrift", "DIN Alternate", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* Le thème : le script du bouton rond (theme.js) pose toujours data-theme sur
   la racine, « light » ou « dark » — celui de l'appareil au départ, celui
   choisi ensuite. Sans script, pas de bouton : c'est le réglage de l'appareil
   qui joue. Les deux blocs sombres sont donc identiques : les garder
   ensemble. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --ink: #e9e7e2;
    --muted: #9c9da2;
    --accent: #9db3cd;
    --paper: #000000;
    --rule: #33353a;
    --head: rgba(0, 0, 0, 0.78);
  }
}

:root[data-theme="dark"] {
  --ink: #e9e7e2;
  --muted: #9c9da2;
  --accent: #9db3cd;
  --paper: #000000;
  --rule: #33353a;
  --head: rgba(0, 0, 0, 0.78);
  color-scheme: dark;
}

:root[data-theme="light"] { color-scheme: light; }

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  background: var(--paper);
  scroll-padding-top: var(--hh);
  /* Pas d'agrandissement automatique du texte (Safari iOS, au pivotement en
     paysage) : les mises en page du site sont calées sur la taille réelle du
     texte. Le réglage « aA » de Safari reste respecté (mesuré le 17/10, Safari
     iOS 26.5 : à 115 %, la page passe de 402 à 350 px de large et le texte
     suit) ; l'effet en paysage n'est pas mesuré (pas de rotation au simulateur). */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Les accueils seulement : ceux qui portent la barre noire (.progress). Les
   pages intérieures défilent librement et gardent la barre du navigateur
   (relecture du 10/10 : sur elles le pied de page était le seul cran, et
   « mandatory » rejetait toute position sur le bas de la page).
   Le « clic » : l'aimantation native du navigateur pose chaque chapitre,
   titre en haut, et arrête les grands gestes (scroll-snap-stop). Un seul
   mécanisme, sans script : le recalage par JavaScript et la coupure du snap
   en plein défilement (09/10) faisaient saccader le défilement sur
   téléphone. Depuis le 10/10 (huitième passe) : « mandatory » (la page se
   cale toujours) et tous les chapitres, pas seulement les trois premiers.
   Un chapitre plus haut que l'écran se parcourt librement à l'intérieur.
   Pas de barre de défilement du navigateur : la jauge noire est la seule à
   dire où l'on est dans la page (10/10). */
html:has(.progress) {
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
}

html:has(.progress)::-webkit-scrollbar { display: none; }

/* Page zoomée (le réglage « aA » de Safari, classe posée par theme.js) : un
   chapitre n'est plus un écran, le texte agrandi le rend plus haut. Avec
   « mandatory », Safari iOS ne laisse pas défiler à l'intérieur du dernier
   chapitre : la fin des questions et le pied de page restaient hors d'atteinte
   (mesuré le 18/10 sur Safari iOS 26.5 : à 125 %, la ligne du copyright
   cachée ; à 175 %, la dernière question et tout le pied). Zoomé, la page
   défile donc librement. */
html.zoomed:has(.progress) { scroll-snap-type: none; }

/* Même cause, sans zoom : une question ouverte (le « + » de la FAQ) rend le
   chapitre « Questions » plus haut que l'écran, et Safari iOS/iPadOS le
   replace alors au début du chapitre à chaque geste (mesuré le 25/10 dans
   Safari de l'iPad simulé : 5 questions ouvertes, deux glissés vers le haut,
   scrollY revenu et resté à 8344 ; le pied de page, à 1553-1623 pour un écran
   de 1153, hors d'atteinte). Tant qu'une question est ouverte, la page défile
   librement ; refermées, l'aimantation revient. */
html:has(.progress):has(#questions details[open]) { scroll-snap-type: none; }

.hero, #idee, .corps-track, .ecran, #questions { scroll-snap-align: start; scroll-snap-stop: always; }

/* Barres de Safari repliées (iPhone, dès le premier défilement), l'écran est
   plus haut que les pages, calées en svh : le haut de la page suivante, son
   titre compris, se montrait en bas de la page calée (capture de Matthieu du
   30/10 : « Download and start » sous « The app offers »). Chaque page est donc
   suivie d'un vide de lvh − svh (0 sur ordinateur) : la page suivante commence
   sous le bas de l'écran, barres déployées ou repliées. Les hauteurs et les
   crans ne bougent pas, seul l'espacement entre pages. Page zoomée (« aA ») :
   défilement libre, pas de vide. Questions est la dernière page : rien à
   cacher après elle. */
html:not(.zoomed) :is(.hero, #idee, .corps-track, .ecran) { margin-bottom: calc(100lvh - 100svh); }

/* Le pied de page n'est pas un cran : sur les accueils il est dans le chapitre
   « Questions » (voir plus bas, .q-stage) ; sur les pages intérieures, rien
   n'est aimanté. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  background: transparent;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  max-width: 700px;
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 32px);
}

.wrap.stage { max-width: 1400px; }

h1, h2, h3, .brand {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* Pas de dernière ligne réduite à un mot : les titres s'équilibrent. */
h1, h2, h3 { text-wrap: balance; }
p, li, dd { text-wrap: pretty; }

::selection { background: color-mix(in srgb, var(--accent) 26%, transparent); }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* Au survol, le lien gagne en contraste (il ne s'éteint pas). Seulement avec
   un vrai pointeur : au toucher, :hover reste collé après l'appui (11/10). */
@media (hover: hover) {
  a:hover { color: var(--ink); text-decoration-thickness: 2px; }
}

/* Appui au doigt : pas de surbrillance grise du navigateur ; le lien ou la
   question s'estompe tant que le doigt est dessus (11/10). */
a, summary { -webkit-tap-highlight-color: transparent; }
/* Pas de zoom au double appui sur les contrôles (le thème, une question) : le
   second appui est un clic. Le zoom au pincement et le défilement restent. */
a, button, summary { touch-action: manipulation; }
a:active, .faq-l summary:active { opacity: 0.6; }

/* Le focus clavier, aux couleurs du site. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Le contenu forme sa propre couche, sous l'en-tête (50) et la jauge (40). */
header.site, main, footer.site { position: relative; z-index: 1; }

/* ---------- en-tête : collant, avec un trait de 2 px dessous ---------- */

header.site {
  /* --mark : corps du mot. Hauteur fixe, --hh (70 px à l'écran : voir :root) ;
     plus de logo depuis le 10/10, le mot seul. Le retrait de côté est sur la
     rangée (.head-row), qui se réduit seule quand la page est zoomée. */
  --mark: 32px;
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--hh);
  /* Voile papier dès le sommet : le contenu qui passe dessous transparaît à peine… */
  background: var(--head);
  transition: background-color 0.35s ease;
}

/* …et plus du tout dès qu'on scrolle (ou sur les pages intérieures). */
header.site.stuck, header.site.solid { background: var(--paper); }

/* Le trait sous l'en-tête (10/10) : 2 px comme la jauge, toute la largeur, sous
   les 70 px de l'en-tête (il n'en change pas la hauteur). Noir en clair,
   clair en sombre. */
header.site::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: calc(2px * var(--zi));
  background: var(--ink);
  pointer-events: none;
}

/* Sur l'accueil (la barre noire est à gauche), le nom s'écarte d'elle. Le
   rond « retour en haut » (.up) s'est glissé entre la barre et l'en-tête au
   v68 : « + » ne trouvait plus l'en-tête et le nom retombait à 20 px, collé à
   la barre (signalé le 11/10). « ~ » ne dépend pas de ce qui est entre les
   deux. */
.progress ~ header.site .head-row { padding-left: max(clamp(20px, 4vw, 48px), calc(var(--gutter) * var(--z))); }

@media (max-width: 480px) {
  header.site { --mark: 27px; }
}

.head-row {
  box-sizing: border-box;
  display: flex;
  height: var(--hh-base);
  padding: 0 clamp(20px, 4vw, 48px);
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

/* Page zoomée (le réglage « aA » de Safari). Plus de réduction inverse :
   elle gardait les lettres à leur taille d'origine et, surtout, la rangée
   devenait plus large que l'écran (100 % × --z) : la page défilait de côté.
   La rangée passe à la ligne, le mot et les liens grossissent avec le reste,
   et --hh (relu par theme.js) suit la hauteur réelle. */
html.zoomed header.site { height: auto; min-height: var(--hh-base); }
html.zoomed .head-row {
  width: auto;
  height: auto;
  transform: none;
  flex-wrap: wrap;
  row-gap: 6px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--mark);
  /* Après la règle groupée h1, h2, h3, .brand (600) : même spécificité,
     c'est l'ordre du fichier qui donne le gras. */
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  /* Zone d'appui de 44 px de haut, mise en page inchangée (marge négative). */
  padding: 6px 0;
  margin: -6px 0;
}

nav.site a {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}

@media (hover: hover) {
  nav.site a:hover { color: var(--ink); }
}

/* Centré, pas sur la ligne de base : le rond (30 px) est plus haut que le texte
   (21 px) ; sur la ligne de base, les textes se calaient en haut de la rangée
   et paraissaient décalés vers le haut (11/10). */
nav.site { display: flex; align-items: center; gap: 20px; }

.lang { display: flex; gap: 6px; align-items: baseline; }

/* Zones de clic élargies (≥ 44 px de haut, 11/10) sans bouger la mise en page :
   le remplissage est compensé par une marge négative. En largeur, FR et EN se
   touchent déjà : pas d'élargissement. */
nav.site a { display: inline-block; padding: 12px 8px; margin: -12px -8px; }

/* iPhone (11/10, demande de Matthieu) : les écarts entre « À propos », FR | EN,
   le rond et le bord droit passent de 20 à 14 px. */
@media (max-width: 480px) {
  .head-row { padding-right: 14px; }
  nav.site { gap: 14px; }
}

/* Très petits écrans (iPhone SE 1re génération) : l'en-tête resserre son
   interlettrage pour tenir sur une ligne sans déborder. */
@media (max-width: 360px) {
  header.site { --mark: 24px; }
  .head-row { gap: 8px; padding-left: 16px; padding-right: 16px; }
  .brand { letter-spacing: 0.12em; gap: 8px; }
  nav.site { gap: 12px; }
  nav.site a { font-size: 12px; letter-spacing: 0.06em; }
}

/* Le séparateur FR | EN est un trait de 2 px comme les autres lignes du site
   (v61), pas un caractère « | » : le texte du balisage reste mais n'est plus
   dessiné (font-size 0). Hauteur = celle des capitales du lien (9 px à 13 px),
   marges de 0,5 px pour garder la largeur de l'ancien « | » (3,1 px). */
.lang span {
  align-self: center;
  width: 2px;
  height: 9px;
  margin: 0 0.5px;
  background: var(--rule);
  font-size: 0;
  line-height: 0;
}

.lang a.on { color: var(--ink); }

/* Le rond clair / sombre, tout à droite de l'en-tête (11/10) : même rond de
   30 px et même trait de 2 px que celui du bas de la barre. Il montre l'état
   de la page (précision de Matthieu, 11/10) : un soleil sur la page claire,
   une lune sur la page sombre ; un appui bascule, et le soleil se transforme
   en lune ou inversement. (L'étiquette lue par les lecteurs d'écran, elle,
   dit l'action : « Passer en mode sombre ».) Zone d'appui de 44 px (le
   pseudo-élément déborde de 7 px). Sans script (theme.js), il n'y a rien à
   faire : caché. */
.mode {
  display: none;
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.theme-js .mode { display: grid; place-items: center; }

.mode::after { content: ""; position: absolute; inset: -7px; }

.mode:active { opacity: 0.6; }

.mode:focus-visible { border-radius: 50%; }

@media (hover: hover) {
  .mode:hover { background: var(--ink); color: var(--paper); }
}

/* L'image : un noyau, un cache qui le découpe en croissant, huit rayons. Soleil
   (page claire) : noyau de 4,5, cache hors du cadre, rayons. Lune (page sombre) :
   noyau ×2,2, cache posé en haut à droite, rayons rentrés. Taille : l'encre de
   SF Symbols à 15 pt, semi-gras (sonde AppKit, rendu ×10 ; demande du 11/10,
   après 17 pt) : sun.max 16,6 × 16,7 px, moon 14,8 × 14,9 px. L'image de
   18,1 px (24 unités, 0,754 px par unité) donne 16,6 px au soleil (rayons
   compris) et 14,9 px à la lune, dans le rond de 30 px inchangé. Les deux
   sont centrés par leur encre : le croissant occupe de 2,1 à 21,9 sur les
   deux axes, soit le centre de l'image à 0,03 unité près — sans décalage. */
.mode svg {
  display: block;
  width: 18.1px;
  height: 18.1px;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.mode .m-core, .mode .m-cut, .mode .m-rays {
  transform-box: view-box;
  transform-origin: 12px 12px;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.35s ease;
}

:root[data-theme="light"] .mode svg { transform: rotate(45deg); }
:root[data-theme="light"] .mode .m-cut { transform: translate(14px, -14px); }
:root[data-theme="dark"] .mode svg { transform: rotate(0deg); }
:root[data-theme="dark"] .mode .m-core { transform: scale(2.2); }
:root[data-theme="dark"] .mode .m-rays { transform: scale(0.5); opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .mode svg, .mode .m-core, .mode .m-cut, .mode .m-rays { transition: none; }
}


/* ---------- la barre noire et ses chapitres (croquis du 10/10, repris sur
   le modèle d'ArtCraft le 10/10) ----------
   Une ligne noire de 2 px, fixe, du haut de l'écran (un peu au-dessus du nom)
   jusqu'au rond à chevron qui la termine, au-dessus du trait du pied de page
   (11/10). Les chapitres sont des points posés dessus, avec leur nom à
   côté, dans un cadre fixe (.rail) que le script anime : le chapitre en cours
   est toujours au même endroit, juste sous le trait de l'en-tête ; les
   suivants ne s'écrivent pas (11/10) : un nom n'apparaît qu'en défilant, il
   monte du bas de la barre en fondu et prend la place du titre actif quand le
   chapitre suivant arrive, partout pareil. Les passés disparaissent. Pas de
   titre sur la première page. Un voile de la couleur du papier, en haut,
   garde le nom lisible sous le trait de l'en-tête. Sans JavaScript, le cadre
   reste caché : la barre seule. */

.progress {
  position: fixed;
  left: var(--rail);
  top: calc(6px * var(--zi));
  /* Une hauteur, pas « top + bottom » : sur iPhone, les barres de Safari qui se
     replient changent la hauteur de la fenêtre, et un cadre fixe dont la
     taille en dépend se recalcule en retard sur la page (« ça ne se met pas
     très bien », 11/10). En svh (barres déployées) elle ne bouge jamais ; le
     rond, lui, suit le bas de l'écran et sa tige (.up::before) comble l'écart. */
  height: calc(100vh - 6px * var(--zi) - var(--end));
  height: calc(100svh - 6px * var(--zi) - var(--end));
  width: calc(2px * var(--zi));
  background: var(--ink);
  /* Au-dessus du cadre des noms (61) : la ligne traverse les points. */
  z-index: 62;
  pointer-events: none;
}

main section { position: relative; }

/* Le cadre : sous l'en-tête et son trait (72 px), jusqu'en bas. Il coupe ce qui
   dépasse (un nom qui monte sous l'en-tête, un autre qui entre par le bas). */
.rail {
  display: none;
  position: fixed;
  top: calc(var(--hh) + 2px * var(--zi));
  height: calc(100vh - var(--hh) - 2px * var(--zi) - var(--end));
  height: calc(100svh - var(--hh) - 2px * var(--zi) - var(--end));
  left: 0;
  width: min(100%, calc(320px * var(--zi)));
  overflow: hidden;
  z-index: 61;
  pointer-events: none;
}

.js .rail { display: block; }

/* Le voile : du papier qui s'efface en s'éloignant du coin. L'opacité est
   posée par le script (--vt). */
.rail::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(64px * var(--zi));
  background: radial-gradient(ellipse 100% 100% at 0 0, var(--paper) 45%, transparent 100%);
  opacity: var(--vt, 0);
  pointer-events: none;
}

/* Un nom : placé et dimensionné par le script (transform, opacité, --a :
   1 pour le chapitre en cours, 0 pour un suivant). Le grossissement se fait
   autour du centre du point, qui reste donc sur la ligne. */
.rail span {
  position: absolute;
  top: 0;
  left: var(--gutter);
  display: block;
  height: calc(16px * var(--zi));
  white-space: nowrap;
  transform-origin: calc(var(--rail) + 1px * var(--zi) - var(--gutter)) 50%;
  will-change: transform, opacity;
}

/* Le point : 12 px pour le chapitre en cours, la moitié environ pour un
   suivant, centré sur la ligne. */
.rail i {
  position: absolute;
  left: calc(var(--rail) - 5px * var(--zi) - var(--gutter));
  top: 50%;
  width: calc(12px * var(--zi));
  height: calc(12px * var(--zi));
  margin-top: calc(-6px * var(--zi));
  border-radius: 50%;
  background: var(--ink);
  transform: scale(calc(0.45 + 0.55 * var(--a, 1)));
}

/* Le nom : en bloc, pour que sa hauteur de ligne (16 px) soit celle du cadre.
   En ligne, c'est la ligne du texte courant (28 px) qui décidait et le nom
   tombait environ 7 px sous le point (10/10). */
.rail b {
  display: block;
  font-family: var(--display);
  font-size: calc(13px * var(--zi));
  font-weight: 600;
  line-height: calc(16px * var(--zi));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: calc(0.5 + 0.5 * var(--a, 1));
}

/* Le rond au bout de la barre : même trait de 2 px, un chevron vers le haut ;
   un appui ramène à la première page (script : d'un bond ; sans script, le
   lien « # » fait le même retour). Centré sur la barre, visible dès la
   première image (11/10 : il attendait le script et « arrivait » après la
   barre). Zone d'appui de 44 px (le pseudo-élément déborde de 7 px de chaque
   côté). Sa tige (::before) est un trait de la barre posé au-dessus du rond :
   le rond suit le bas de l'écran, la barre garde sa hauteur en svh, et quand
   les barres de Safari se replient la tige comble l'écart entre les deux ;
   barres déployées, elle se superpose à la barre (même trait, même couleur). */
.up {
  display: grid;
  place-items: center;
  position: fixed;
  left: calc(var(--rail) + 1px * var(--zi) - var(--up) / 2);
  bottom: calc(var(--foot) + var(--upg));
  width: var(--up);
  height: var(--up);
  z-index: 63;
  padding: 0;
  border: calc(2px * var(--zi)) solid var(--ink);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.up::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: calc(2px * var(--zi));
  height: calc(140px * var(--zi));
  margin-left: calc(-1px * var(--zi));
  background: var(--ink);
  pointer-events: none;
}

.up::after { content: ""; position: absolute; inset: calc(-7px * var(--zi)); }

.up svg { display: block; width: calc(16px * var(--zi)); height: calc(16px * var(--zi)); }

.up:active { opacity: 0.6; }

/* Le focus clavier dessine un contour rond, pas le coin de 4 px des autres. */
.up:focus-visible { border-radius: 50%; }

@media (hover: hover) {
  .up:hover { background: var(--ink); color: var(--paper); }
}

/* Téléphone : le texte commence à droite de la barre (à partir de 700 px, la
   marge automatique du bloc s'en charge). */
@media (max-width: 700px) {
  .progress ~ main section .wrap { padding-left: max(clamp(calc(20px * var(--zi)), 5vw, calc(32px * var(--zi))), var(--gutter)); }
}

/* ---------- héros ---------- */

/* Les mesures horizontales du héros (marges, corps du titre, décalage) sont
   aussi celles de la page 2 (#idee), des pages 4 à 6 (.ecran, #questions, dont
   le pied de page des accueils fait partie) : leur texte part du même bord
   gauche (--hl + --hshift), au même corps, que le grand titre de la page 1. */
.hero,
#idee,
.ecran,
#questions {
  --hpad: clamp(calc(16px * var(--zi)), 5vw, calc(56px * var(--zi)));
  /* Marge de droite du titre : plus large que celle de gauche (10/10, huitième
     passe : une fois et demie l'espace de la barre, soit 48 px à 390 px). Les
     photos, elles, la rognent (voir .photos). */
  --hr: max(var(--hpad), calc(var(--gutter) * 1.5));
  /* Marge de gauche du titre et des carrés : au moins 28 px d'air entre le bord
     droit de la barre noire (2 px à --rail) et eux (10/10, onzième passe ; avant,
     14 px à 390 px). La marge de droite, elle, ne bouge pas : c'est le titre et
     les carrés qui rétrécissent. */
  --hl: max(var(--hpad), calc(var(--rail) + 30px * var(--zi)));
  /* Corps du titre (voir plus bas), réutilisé pour aligner les six carrés. */
  --hs: min(calc((100vw - var(--hr) - var(--hl)) / 12.1), max(32px, 5.8vw), 48px);
  /* Décalage du titre vers la droite (et des carrés, qui le suivent) : la moitié
     de l'air disponible moins 6 vw, mais jamais plus de 120 px (10/10, dixième
     passe : sur grand écran il partait à 500 px et plus). Le 100 % se résout là
     où la variable est lue : la largeur du bloc de texte, entre --hl et --hr. */
  --hshift: clamp(0px, calc((100% - 11.8 * var(--hs)) / 2 - 6vw), 120px);
}

/* Les mesures verticales et la hauteur des écrans de l'accueil. */
.hero,
#idee,
.ecran,
#questions {
  /* svh : hauteur stable sur iPhone (la barre Safari rétractable fausse vh). */
  min-height: calc(100vh - var(--hh));
  min-height: calc(100svh - var(--hh));
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Le titre et les six carrés, centrés dans l'écran puis un peu remontés : le
     remplissage du bas, plus grand que celui du haut, les place au-dessus du
     centre. Les trois mesures verticales sont des variables parce que la
     hauteur des carrés en dépend (--hsq, ci-dessous). */
  --hpt: clamp(40px, 6vh, 72px);
  --hpb: clamp(70px, 12vh, 130px);
  --hgap: clamp(36px, 7vh, 72px);
  --pgap: clamp(8px, 2vw, 18px);
  /* Hauteur libre sous le titre : l'écran moins l'en-tête, les remplissages, les
     trois lignes du titre (3 x 1,25 em) et l'espace avant les carrés. */
  --hfree: calc(100vh - var(--hh) - var(--hpt) - var(--hpb) - 3.75 * var(--hs) - var(--hgap));
  /* Côté d'un carré : le plus petit de 180 px et de ce qui tient dans la
     hauteur (sans descendre sous 56 px : mieux vaut faire défiler que des
     carrés minuscules). La largeur, elle, borne déjà par la grille. */
  --hsq: max(56px, min(180px, var(--hfree)));
  padding: var(--hpt) 0 var(--hpb);
  overflow: hidden;
}
@supports (height: 100svh) {
  .hero, #idee { --hfree: calc(100svh - var(--hh) - var(--hpt) - var(--hpb) - 3.75 * var(--hs) - var(--hgap)); }
}

/* Le titre tient en trois lignes, une par vers (vision / organisez-vous /
   visez…), chacune insécable : jamais plus de trois lignes, texte aligné à
   gauche. En Barlow ExtraBold, la ligne la plus longue (« visez un meilleur
   équilibre. ») fait 11,70 em (EN : environ 10,7 em). Le corps est la plus
   petite de trois valeurs : la largeur de l'écran (rapport 12,1, environ 3 %
   d'air), la courbe de la première version un peu agrandie (5,8 vw, plancher
   32 px) et 48 px : le titre ne prend pas tout l'écran. Sur
   téléphone, le bloc (11,8 em) est collé à la marge de gauche ; sur grand
   écran, il est centré dans la page puis décalé de 6 vw vers la gauche, et
   son décalage depuis la marge est plafonné à 120 px (--hshift). Le
   remplissage du bas, plus grand que celui du haut, remonte le titre. */
.hero .wrap,
#idee .wrap,
.progress ~ main .ecran .wrap,
#questions .wrap {
  width: 100%;
  max-width: none;
  /* À gauche : la barre noire et l'air qui la sépare du texte (--hl). */
  padding-left: var(--hl);
  padding-right: var(--hr);
}

.hero h1,
#idee h2,
.ecran h2,
#questions h2 {
  font-size: var(--hs);
  font-weight: 800;
  width: 11.8em;
  max-width: 100%;
  margin: 0 0 0 var(--hshift);
  text-align: left;
}

/* Pages 4 à 6 : le titre peut être plus long que la page 1 (« Télécharger et
   commencer ») ; il prend la largeur dont il a besoin, marge de droite
   reprise comme celle des carrés. */
.ecran h2,
#questions h2 {
  width: auto;
  margin-right: calc(var(--hpad) - var(--hr));
}
.hero h1 span { display: block; white-space: nowrap; }

/* Pages 2, 4, 5 et 6 : le contenu démarre 32 px plus haut que la page 1, tous
   au même endroit (11/10). Décalage de peinture seulement (position relative) :
   hauteurs de pages, crans d'aimantation et calcul des chapitres inchangés. */
#idee .wrap,
.ecran .wrap,
#questions .q-stage > .wrap {
  position: relative;
  top: -32px;
}

/* Six photos (croquis du 10/10 ; photos de Matthieu depuis le 12/10, sans
   contour) : six carrés sous le titre, en une rangée. Ils partent du même bord
   gauche que le titre et s'étirent vers la droite : plus la page est large,
   plus ils sont grands, jusqu'à --hsq (180 px, ou moins si la hauteur de
   l'écran ne suffit pas : ils tiennent toujours dans l'écran avec le titre).
   À droite ils rognent la marge du titre (margin-right négatif : ils
   s'arrêtent à la marge ordinaire de la page, pas à celle, plus large, du
   titre). Sur téléphone : deux rangées de trois, aussi grands que la largeur
   et la hauteur le permettent. */
.photos {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--pgap);
  max-width: calc(6 * var(--hsq) + 5 * var(--pgap));
  margin: var(--hgap) calc(var(--hpad) - var(--hr)) 0 var(--hshift);
}

/* Carré : la hauteur vient d'un remplissage en pourcentage de la largeur
   (::before) et non de aspect-ratio, que WebKit laisse parfois à l'ancienne
   dimension quand la fenêtre est redimensionnée (10/10). Le pourcentage se
   résout sur la largeur du carré, sans contour : la hauteur égale la largeur.
   La photo remplit le carré. */
.photos span {
  display: block;
  position: relative;
  overflow: hidden;
}
.photos img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.photos span::before {
  content: "";
  display: block;
  padding-top: 100%;
}

@media (max-width: 700px) {
  /* Deux rangées : la hauteur libre se partage entre deux carrés et leur écart. */
  .hero, #idee { --hsq: max(56px, min(180px, calc((var(--hfree) - var(--pgap)) / 2))); }
  .photos {
    grid-template-columns: repeat(3, 1fr);
    max-width: calc(3 * var(--hsq) + 2 * var(--pgap));
  }
}

/* ---------- sections ---------- */

section { padding: clamp(48px, 8vh, 76px) 0; }

/* ---------- l'idée (page 2) ----------
   Un écran construit comme le héros (mesures partagées plus haut) : le titre
   « Un espace central » au même endroit et au même corps que le grand titre de
   la page 1, aligné à gauche, puis la phrase qui dit ce qu'est Viordi (en
   gris) et l'état de la sortie. La boîte du titre a la hauteur des trois
   lignes du titre de la page 1 ; la phrase et la pastille en débordent vers le
   bas, dans la place des six carrés de la page 1, qui restent là, invisibles :
   le centrage vertical est le même qu'en page 1. */

#idee .titre { height: calc(3.75 * var(--hs)); }

#idee .photos { visibility: hidden; }

#idee .lead {
  font-size: clamp(16px, 2.2vw, 19px);
  color: var(--muted);
  max-width: 540px;
  margin: calc(0.5 * var(--hs)) 0 0 var(--hshift);
}

@media (min-width: 1200px) {
  #idee .lead { font-size: 20px; max-width: 580px; }
}

/* Téléphone : pas de retour à la ligne forcé après « but sincère : » — la phrase
   passait à la ligne toute seule, laissant un mot (« goal: ») seul et un grand
   blanc après lui (retour de Matthieu du 30/10). Le texte coule jusqu'au bout. */
@media (max-width: 700px) {
  #idee .lead br.pc { display: none; }
}

/* Une pastille d'état, pas un faux bouton : sans fond, juste le contour d'un
   trait noir de 2 px, comme la barre noire et le trait de l'en-tête. Le
   remplissage perd 1 px par côté : la pastille garde sa taille. Rien
   n'invite à cliquer. Alignée sur le bord gauche du titre. */
#idee .cta {
  display: inline-block;
  margin: 34px 0 0 var(--hshift);
  padding: 10px 21px;
  border-radius: 999px;
  border: 2px solid var(--ink);
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: default;
}

/* Aucun trait entre les pages : chacune n'a, au plus, que celui qui sépare son
   titre de ses points ou de ses questions. */

section h2 { font-size: clamp(24px, 3.4vw, 28px); margin-bottom: 14px; }

section p { margin-bottom: 14px; }

section p:last-child { margin-bottom: 0; }

/* ---------- apparitions douces au scroll ---------- */

.js .reveal { opacity: 0; transform: translateY(10px); transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1), transform 0.6s cubic-bezier(0.22, 1, 0.36, 1); }
.js .reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   LE CORPS — la constellation des six piliers : six ronds, une seule ligne
   noire chacun ; au fil du défilement, celui du module en cours se met en
   évidence ; à côté (dessous sur téléphone), le texte du module.
   (Les halos de couleur de la V1 ont disparu : mécanisme conservé, couleurs
   retirées, un cercle noir à la place.)
   ============================================================ */

#corps { padding: 0; border-top: none; }

.corps-track { position: relative; }

/* Calage au début de la page : le haut de la piste au ras de l'écran (et non
   sous l'en-tête) — la scène collante (top: 0) est alors à sa place, ronds et
   texte centrés ; calée 70 px plus bas, elle les décalait vers le bas
   jusqu'au premier défilement (neuvième passe, 10/10). */
.corps-track { scroll-margin-top: calc(-1 * var(--hh)); }

/* Course du parcours des sept modules : 636svh de piste − 100svh de scène =
   536svh de défilement, soit 75svh par module (≈ 535 px sur un iPhone, 680 px
   sur un Mac de 900 px). Avant le 30/10 : 400svh, 42svh par module (≈ 300 px) ;
   un grand geste en traversait deux ou trois, parce que Safari ne s'arrête pas
   à chaque cran sur l'élan d'un geste (scroll-snap-stop: always ignoré,
   mesuré au simulateur dans une page d'essai : une tuile de 300 px sautée par
   geste vif). Le cran est maintenant plus long qu'un grand geste. La course
   ne dépend pas de la barre Safari (svh). Les paliers (MOD_AT, MOD_STEP, en
   fractions de la course) sont dans le script des deux accueils. */
.js.scrub .corps-track { height: 636vh; height: 636svh; }

/* Un cran par module (30/10) : un petit balayage et un grand balayage doivent
   passer d'un module au suivant, pas en sauter deux ou trois (la piste se
   parcourait librement, l'élan du geste décidait). Huit repères invisibles
   (.sn) aimantés comme les pages : le premier au début de la piste, les sept
   autres au milieu de la tranche de chaque module. Position de la tranche k
   (de 0 à 6) : 536svh × (MOD_AT + MOD_STEP × (k + 0,5)), avec MOD_AT = 0,04
   et MOD_STEP = 0,14 (script des deux accueils) : 59, 134, 209, 284, 359, 434,
   509 svh. Le même décalage que la piste (scroll-margin-top) les met au ras de
   l'écran, comme la scène collante. Une vraie hauteur (75svh, moins que
   l'écran) : à 1 px, le navigateur ignorait les repères (mesuré le 30/10).
   Seulement quand le parcours est animé (.scrub) : sans lui, ni piste haute
   ni repères. */
.sn { display: none; }
.js.scrub .sn {
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  height: 75svh;
  pointer-events: none;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  scroll-margin-top: calc(-1 * var(--hh));
}
/* La piste elle-même ne s'aimante plus (.scrub) : plus haute que l'écran, elle le
   couvre à toute position, et le navigateur laisse alors s'arrêter n'importe où
   à l'intérieur (mesuré le 30/10 : arrêt à 142 px d'un cran de 236). Les huit
   repères font office de crans, le premier au ras de la piste (la page des
   ronds). */
.js.scrub .corps-track { scroll-snap-align: none; }
.js.scrub .sn:nth-of-type(1) { top: 0; }
.js.scrub .sn:nth-of-type(2) { top: 59svh; }
.js.scrub .sn:nth-of-type(3) { top: 134svh; }
.js.scrub .sn:nth-of-type(4) { top: 209svh; }
.js.scrub .sn:nth-of-type(5) { top: 284svh; }
.js.scrub .sn:nth-of-type(6) { top: 359svh; }
.js.scrub .sn:nth-of-type(7) { top: 434svh; }
.js.scrub .sn:nth-of-type(8) { top: 509svh; }

.corps-stage {
  display: flex;
  align-items: center;
  padding: clamp(40px, 7vh, 72px) 0;
}

.js.scrub .corps-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  /* svh, pas dvh : la hauteur de la scène ne bouge plus quand la barre Safari
     se rétracte en plein défilement (dvh la faisait changer, donc sauter). */
  height: 100svh;
  overflow: hidden;
  /* Le header collant occupe le haut : le centrage en tient compte. En bas,
     44 px : le titre du module suivant déborde sous le texte d'environ 44 px,
     que le centrage ne comptait pas ; le bloc entier (ronds, texte, titre
     suivant) est maintenant centré dans la place libre (11/10, « trop collé au
     bas »). */
  padding: 74px 0 44px;
}

.corps-inner { width: 100%; }

.corps-grid {
  display: grid;
  grid-template-columns: minmax(240px, 5fr) minmax(0, 6fr);
  gap: clamp(32px, 7vw, 120px);
  align-items: center;
  width: 100%;
}

/* -- la constellation : six ronds, le nom seul dedans --
   Six cercles d'une seule ligne de 2 px (couleur foncée du module), SANS fond : quand le rond en
   cours grossit et passe par-dessus ses voisins, on voit l'intersection des
   traits. Dimensions et positions en part de la largeur du cadre (bureau :
   carré ; téléphone : 100 × 68), calculées pour que, au repos, deux cercles
   ne se touchent jamais (écart ≥ 3 % de la largeur) et que les ronds soient
   aussi grands que le cadre le permet. --o : le point fixe du grossissement
   — pour un rond proche d'un bord du cadre, ce bord : le rond grossit vers
   l'intérieur et ne sort jamais du cadre. */

.story-visual {
  /* Le noir un peu grisé des ronds dont on ne parle pas. */
  --dim: color-mix(in srgb, var(--ink) 72%, var(--paper));
  /* Grossissement du rond en cours, et de tous les ronds sur Concentration
     (grand écran ; réglé plus bas pour le texte sous les ronds). */
  --zoom: 1.4;
  --zoom-foc: 1.11;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* En parcours piloté, le cadre se borne par la hauteur de la scène (carré). */
.cluster {
  position: relative;
  width: min(100%, 44vw, 620px);
  aspect-ratio: 1;
}

.js.scrub .cluster { width: min(100%, calc(100svh - 170px), 640px); }

.orb {
  position: absolute;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  transform-origin: var(--o, 50% 50%);
  /* 0,25 s : un rond qui quitte l'évidence (gris, ×0,9) ; ceux qui y entrent
     gardent 0,6 s (règles « jamais deux ronds en évidence », plus bas). */
  transition: transform 0.25s ease;
}

/* Le cercle : une seule ligne de 2 px (comme la barre noire), de la couleur
   foncée du module (--oc, posée ci-dessous) ; l'intérieur reste vide. */
.orb::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--oc, var(--ink));
  transition: border-color 0.25s ease;
}

/* Le nom vit au centre du cercle et grossit avec lui. */
.orb span {
  position: relative;
  z-index: 1;
  font-family: var(--display);
  font-weight: 600;
  /* Les plancher et plafond suivent --zi : le rond a la même taille à l'écran
     quel que soit le zoom de page (il se dessine en largeur d'écran), son
     étiquette aussi, sinon « Visualisation » déborde de son rond. */
  font-size: clamp(calc(12.5px * var(--zi)), 1.35vw, calc(16px * var(--zi)));
  letter-spacing: -0.01em;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--ink);
  transition: color 0.25s ease;
}

.orb.cal { width: 40.90%; left: 10.55%; top: 0.05%; --o: 50% 0%; }
.orb.hab { width: 31.60%; left: 68.40%; top: 0.00%; --o: 100% 0%; }
.orb.goa { width: 35.30%; left: 0.05%; top: 41.65%; --o: 0% 50%; }
.orb.jou { width: 42.80%; left: 42.80%; top: 29.20%; --o: 50% 50%; }
.orb.not { width: 29.80%; left: 27.20%; top: 70.20%; --o: 50% 100%; }
.orb.vis { width: 26.00%; left: 60.00%; top: 74.00%; --o: 50% 100%; }

.orb.cal { --oc: var(--m-cal); }
.orb.hab { --oc: var(--m-hab); }
.orb.goa { --oc: var(--m-goa); }
.orb.jou { --oc: var(--m-jou); }
.orb.not { --oc: var(--m-not); }
.orb.vis { --oc: var(--m-vis); }

/* États pilotés par le scroll (attribut data-active, posé par le script) :
   « all » avant le premier module ; sinon, le rond en cours grossit (×1,4 en
   grand écran, ×1,3 avec le texte dessous), garde le trait de la couleur de
   son module et passe par-dessus les autres ; les autres rétrécissent un peu
   et prennent le noir grisé (--dim). « foc » (Concentration,
   le septième pas : un outil, il n'a pas de rond) : les six ronds grossissent
   ensemble (×1,11 ; ×1,07 avec le texte dessous) et prennent le gris des
   ronds éteints. */
.story-visual[data-active] .orb { transform: scale(0.9); }
.story-visual[data-active] .orb::before { border-color: var(--dim); }
.story-visual[data-active] .orb span { color: var(--dim); }

.story-visual[data-active="all"] .orb { transform: none; }
.story-visual[data-active="all"] .orb::before { border-color: var(--oc, var(--ink)); }
.story-visual[data-active="all"] .orb span { color: var(--ink); }

.story-visual[data-active="foc"] .orb { transform: scale(var(--zoom-foc)); }

.story-visual[data-active="cal"] .orb.cal,
.story-visual[data-active="hab"] .orb.hab,
.story-visual[data-active="goa"] .orb.goa,
.story-visual[data-active="jou"] .orb.jou,
.story-visual[data-active="not"] .orb.not,
.story-visual[data-active="vis"] .orb.vis {
  transform: scale(var(--zoom));
  z-index: 2;
}

.story-visual[data-active="cal"] .orb.cal::before,
.story-visual[data-active="hab"] .orb.hab::before,
.story-visual[data-active="goa"] .orb.goa::before,
.story-visual[data-active="jou"] .orb.jou::before,
.story-visual[data-active="not"] .orb.not::before,
.story-visual[data-active="vis"] .orb.vis::before { border-color: var(--oc, var(--ink)); }

.story-visual[data-active="cal"] .orb.cal span,
.story-visual[data-active="hab"] .orb.hab span,
.story-visual[data-active="goa"] .orb.goa span,
.story-visual[data-active="jou"] .orb.jou span,
.story-visual[data-active="not"] .orb.not span,
.story-visual[data-active="vis"] .orb.vis span { color: var(--ink); }

/* Jamais deux ronds en évidence à la fois (13/10, retour de Matthieu : « titres
   et ronds ») : au changement de module, le rond qui s'éteint le fait en 0,25 s
   (règles de base), celui qui s'allume en 0,6 s ; de même les états « all » et
   « foc », où tous les ronds changent ensemble. La durée utilisée est celle de
   l'état d'arrivée. */
.story-visual[data-active="all"] .orb,
.story-visual[data-active="foc"] .orb,
.story-visual[data-active="cal"] .orb.cal,
.story-visual[data-active="hab"] .orb.hab,
.story-visual[data-active="goa"] .orb.goa,
.story-visual[data-active="jou"] .orb.jou,
.story-visual[data-active="not"] .orb.not,
.story-visual[data-active="vis"] .orb.vis { transition: transform 0.6s ease; }

.story-visual[data-active="all"] .orb::before,
.story-visual[data-active="foc"] .orb::before,
.story-visual[data-active="cal"] .orb.cal::before,
.story-visual[data-active="hab"] .orb.hab::before,
.story-visual[data-active="goa"] .orb.goa::before,
.story-visual[data-active="jou"] .orb.jou::before,
.story-visual[data-active="not"] .orb.not::before,
.story-visual[data-active="vis"] .orb.vis::before { transition: border-color 0.6s ease; }

.story-visual[data-active="all"] .orb span,
.story-visual[data-active="foc"] .orb span,
.story-visual[data-active="cal"] .orb.cal span,
.story-visual[data-active="hab"] .orb.hab span,
.story-visual[data-active="goa"] .orb.goa span,
.story-visual[data-active="jou"] .orb.jou span,
.story-visual[data-active="not"] .orb.not span,
.story-visual[data-active="vis"] .orb.vis span { transition: color 0.6s ease; }

@media (prefers-reduced-motion: reduce) {
  .orb, .orb::before, .orb span,
  .story-visual .orb, .story-visual .orb::before, .story-visual .orb span { transition: none !important; }
}

/* -- le texte du module en cours : nom, phrase clé, description --
   En parcours piloté, la colonne montre trois choses : le texte complet du
   module en cours (noir, au centre), le TITRE du module précédent au-dessus et
   celui du module suivant en dessous, en gris. Au fil du défilement, le suivant
   prend la place centrale (le texte se déploie), l'en-cours recule en haut. */

.mod + .mod { margin-top: 36px; }

.mod h3 { font-size: var(--h3s, clamp(26px, 3.2vw, 36px)); margin-bottom: 8px; }

.mod .c-promise {
  font-size: 12.5px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.mod .c-txt {
  font-size: clamp(16px, 1.5vw, 18px);
  line-height: 1.55;
  max-width: 30em;
  margin: 14px 0 0;
}

/* Les sept textes se superposent dans la même case (la hauteur ne saute jamais :
   celle du plus long) ; ils sont posés par rapport à cette case. Hauteur d'un
   titre voisin : 0,6 fois celle du titre en cours, × 1,25 de interligne ;
   --ng : l'air entre le texte en cours et chaque titre voisin (10/10 : élargi,
   les textes étaient trop proches). */
.js.scrub .panel {
  --h3s: clamp(26px, 3.2vw, 36px);
  --ng: 32px;
  /* Décalage du titre précédent : sa hauteur + l'écart. */
  --nb: calc(var(--h3s) * 0.75 + var(--ng));
  display: grid;
}

.js.scrub .mod {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  pointer-events: none;
  /* Par défaut (modules à venir, plus loin que le suivant) : sous la case. */
  transform: translateY(calc(100% + var(--nb) * 2));
  /* Jamais quatre titres à la fois (13/10, retour de Matthieu) : un titre qui
     SORT du trio (« .before », ou retour sous la case) s'efface en 0,12 s ; ceux
     qui restent ou ARRIVENT (.prev, .on, .next) gardent 0,5 s. Avant, celui qui
     partait mettait 0,5 s à s'effacer pendant que le nouveau apparaissait : un
     quatrième titre pendant un instant. */
  transition: opacity 0.12s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.js.scrub .mod.prev, .js.scrub .mod.on, .js.scrub .mod.next {
  transition: opacity 0.5s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Passés, plus loin que le précédent : au-dessus de la case. */
.js.scrub .mod.before { transform: translateY(calc(var(--nb) * -2)); }

.js.scrub .mod.prev { opacity: 0.3; transform: translateY(calc(var(--nb) * -1)); }
.js.scrub .mod.next { opacity: 0.3; transform: translateY(calc(100% + var(--ng))); }

.js.scrub .mod.on { opacity: 1; transform: none; pointer-events: auto; }

/* Un titre voisin est plus petit ; seul le module en cours montre sa phrase
   clé et sa description. Réduit par l'échelle, pas par la taille de police
   (12/10, mesuré dans Safari iOS) : changer la taille de police change la
   hauteur de la case (celle du texte le plus long), donc le « 100 % » du
   décalage du titre suivant ; Safari calcule ce décalage au début de la
   transition et le recalcule à la fin : « Concentration » restait 13 px trop
   bas puis remontait d'un coup. L'échelle ne touche pas à la mise en page : la
   case garde la hauteur du texte le plus long, partout pareil. */
.js.scrub .mod h3 { transform-origin: 0 0; transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1); }
.js.scrub .mod.prev h3, .js.scrub .mod.next h3 { transform: scale(0.6); }

.js.scrub .mod .c-promise, .js.scrub .mod .c-txt { transition: opacity 0.45s ease; }
.js.scrub .mod:not(.on) .c-promise, .js.scrub .mod:not(.on) .c-txt { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .js.scrub .mod, .js.scrub .mod.prev, .js.scrub .mod.on, .js.scrub .mod.next,
  .js.scrub .mod h3, .js.scrub .mod .c-promise, .js.scrub .mod .c-txt { transition: none; }
}

/* Bureau : la constellation est à gauche (colonne un peu plus large que celle
   du texte), le texte à droite ; marge latérale qui grandit à mesure que
   l'écran rétrécit (≈36px à 1400, ~70px à 821). Concentration est le septième
   texte de la colonne : plus de note à part. */
@media (min-width: 1001px) {
  .corps-inner {
    padding-left: max(32px, calc(120px - 6vw));
    padding-right: max(32px, calc(120px - 6vw));
  }
  .corps-grid { grid-template-columns: minmax(240px, 6fr) minmax(0, 5fr); }
}

/* Téléphone, tablette : la constellation devient un bandeau (croquis de
   Matthieu du 03/08), le texte du module dessous avec les titres voisins en
   gris ; le bloc de texte est centré sur l'écran (10/10), texte aligné à
   gauche. Bascule à 1000px : en dessous, la vue à deux colonnes écrasait les
   ronds.
   Bandeau de 100 × 68. En parcours piloté il se borne par la hauteur de la
   scène : bandeau + écart (--cg, le titre précédent y loge) + texte (≈ 150) +
   titre suivant (≈ 44).
   Exception (12/10) : un téléphone en paysage (largeur de 600 à 1000 px, hauteur
   d'au plus 430 px) garde les deux colonnes de l'ordinateur : empilés, bandeau
   et texte ne tiennent pas dans la scène (voir les deux blocs « écran bas »
   plus bas). */
@media (max-width: 1000px) and (min-height: 431px), (max-width: 599.98px) {
  /* Écart entre les ronds et le texte (--cg) : 58 px avant le 11/10, jusqu'à
     98 px sur deux demandes de Matthieu. Il suit la hauteur de l'écran : 98 px
     à 664 px de haut (iPhone, barres de Safari déployées) et au-dessus, 58 px
     à 553 px (iPhone SE), où le titre suivant n'a déjà presque plus de place.
     La grille est centrée dans la scène : les ronds montent de la moitié de
     l'écart gagné et le texte descend d'autant. */
  .corps-grid {
    --cg: clamp(58px, calc(58px + (100svh - 553px) * 0.36), 98px);
    /* Place prise hors du bandeau : 74 px sous l'en-tête, texte (≈ 150),
       titre suivant et marge du bas (le bloc « écran bas » la ramène à 280). */
    --res: 337px;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cg);
  }

  /* Texte sous les ronds : ×1,3 pour le rond en cours, ×1,07 sur Concentration. */
  .story-visual { --zoom: 1.3; --zoom-foc: 1.07; }

  .panel { width: min(100%, clamp(300px, 56vw, 460px)); margin-inline: auto; }

  .cluster { width: min(100%, 540px); aspect-ratio: 100 / 68; }
  .js.scrub .cluster { width: min(100%, 540px, max(240px, calc((100svh - var(--res) - var(--cg)) / 0.68))); }

  .orb.cal { width: 34.70%; left: 0.05%; top: 1.99%; --o: 0% 0%; }
  .orb.hab { width: 26.80%; left: 10.40%; top: 55.88%; --o: 50% 100%; }
  .orb.goa { width: 30.00%; left: 37.00%; top: 0.00%; --o: 50% 0%; }
  .orb.jou { width: 36.30%; left: 41.45%; top: 46.54%; --o: 50% 100%; }
  .orb.not { width: 25.30%; left: 69.45%; top: -0.07%; --o: 100% 0%; }
  .orb.vis { width: 22.10%; left: 77.85%; top: 39.49%; --o: 100% 50%; }

  .orb span { font-size: calc(11px * var(--zi)); letter-spacing: 0; }

  .mod .c-txt { font-size: 15.5px; }

  .js.scrub .panel { --ng: 24px; }
}

/* ---------- téléphone et écran bas : seul le texte du rond montré ----------
   Demande de Matthieu, 12/10 puis 14/10 : « un seul titre, toujours » sur
   téléphone, y compris en portrait ; et sur tout écran où la scène n'a pas la
   place d'afficher les ronds avec les titres voisins (paysage, texte ou page
   agrandis). Seuls le titre et le texte du rond montré restent : les titres du
   module précédent et du suivant n'existent plus (opacité 0, sans durée à
   rattraper : le texte qui sort s'efface en 0,15 s avant que le suivant
   s'allume) ; l'écart sous les ronds (--cg), la marge du bas et la place
   réservée (--res) se resserrent, le bandeau garde toute la largeur.
   Condition : largeur ≤ 700 px (le « téléphone » du script, voir updateRail),
   ou largeur ≤ 1000 px et hauteur ≤ 540 px. Les tablettes et les ordinateurs
   gardent les trois titres tant que la scène a la hauteur.
   Mesuré (Chromium, FR et EN, sans transition) : à 375 px de large, le texte
   seul tient jusqu'à ≈ 460 px de haut (au-dessous, les ronds montent sous le
   nom du chapitre ; rien n'est coupé jusqu'à ≈ 430 px). En paysage (600 à
   1000 px de large, 430 px de haut ou moins) : deux colonnes, ronds à gauche et
   texte à droite, comme sur ordinateur (voir le bloc téléphone plus haut).
   Reste hors de portée : un écran étroit ET plus bas que ≈ 430 px (zoom de
   300 % et plus) : la scène y coupe, sans issue de défilement ; il y faudrait
   la liste statique des sept textes (celle des animations réduites). */
@media (max-width: 700px), (max-width: 1000px) and (max-height: 540px) {
  .js.scrub .mod.prev, .js.scrub .mod.next {
    opacity: 0;
    transition: opacity 0.15s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* 104 px en haut : le nom du chapitre de la barre noire (« Les 6 piliers »)
     s'écrit sous l'en-tête, jusqu'à ≈ 100 px ; les ronds ne le recouvrent pas.
     20 px en bas : plus de titre suivant à loger. */
  .js.scrub .corps-stage { padding-top: 104px; padding-bottom: 20px; }
  /* Écart ronds-texte : 28 px sur écran bas, jusqu'à 56 px sur grand téléphone
     (il n'a plus de titre précédent à loger). */
  .js.scrub .corps-grid {
    --cg: clamp(28px, calc(28px + (100svh - 540px) * 0.2), 56px);
    --res: 280px;
  }
}

/* Paysage bas : la colonne de gauche prend la hauteur libre (scène − 104 px du
   haut − 20 px du bas, soit 100svh − 124 px ; 16 px de réserve). */
@media (min-width: 600px) and (max-width: 1000px) and (max-height: 430.98px) {
  .js.scrub .cluster { width: min(100%, calc(100svh - 140px), 640px); }
  .orb span { font-size: calc(11px * var(--zi)); letter-spacing: 0; }
}

/* ---------- pages 4 et 5 : trois points ----------
   Un écran chacune : le titre (le nom du chapitre de la barre, au corps et à
   la place du titre de la page 1), puis trois points, chacun un titre marqué
   et une courte description en gris. Le titre part de la hauteur de celui de
   la page 1 (--ty, mesurée par le script ; sans script : le remplissage du
   héros), le reste suit, aligné sur son bord gauche. */

.ecran {
  min-height: calc(100vh - var(--hh));
  min-height: calc(100svh - var(--hh));
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: var(--ty, var(--hpt)) 0 clamp(16px, 3vh, 32px);
  overflow: visible;
}

.ecran h2 { margin-bottom: 8px; }

/* Le trait sous le titre (pages 4 à 6, ici et sous .faq-l) : 2 px comme la
   barre noire, en gris clair. Le trait gagne 1 px : la marge ou le remplissage
   en perd 1, rien d'autre ne bouge. */
.points {
  margin: 18px calc(var(--hpad) - var(--hr)) 0 var(--hshift);
  max-width: 620px;
  padding-top: 9px;
  list-style: none;
  border-top: 2px solid var(--rule);
}

.points li { padding: 16px 0; }

.points strong {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(20px, 2.6vw, 24px);
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.points span {
  display: block;
  margin-top: 6px;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.55;
}

/* ---------- FAQ ---------- */

/* La dernière page est une piste, comme celle des piliers : le chapitre
   « Questions » et le pied de page sont ensemble dans une scène collante
   (.q-stage), posée sous l'en-tête. Un chapitre comme les autres : au moins un
   écran, calé titre en haut par l'aimantation (huitième passe, 10/10), le
   titre à la hauteur de celui de la page 1 (--ty, comme pour les pages 4 et
   5) ; le pied de page (72 px) tient dans le même écran, il est donc visible
   dès que la page est calée (neuvième passe).
   Pourquoi une scène collante (12/10, mesuré dans Safari iOS 26.5, journal des
   problèmes iPhone, faits F1 à F3) : sur iPhone, le navigateur borne l'élan
   vers un cran à « hauteur du document − 812 pt », 58 pt avant le cran de la
   dernière page ; le document doit donc se prolonger sous le cran (voir la
   fin du fichier). Ce prolongement ne doit rien montrer : la scène collante
   reste en place pendant tout ce prolongement, la page ne bouge pas et aucun
   blanc n'apparaît (v77 à v80 le laissaient défiler : « un énorme blanc en
   dessous et le contenu trop haut », retour de Matthieu). Marge du bas
   réduite pour que le tout tienne sur un téléphone.
   lvh : la page et le pied de page remplissent l'écran barres de Safari
   repliées (l'état de l'iPhone dès le premier défilement) ; en svh, le
   document finissait avant et la page, calée en bas, restait plus bas que
   les autres de la hauteur des barres (≈ 90 px). */
#questions {
  min-height: calc(100vh - var(--hh));
  min-height: calc(100svh - var(--hh));
  min-height: calc(100lvh - var(--hh));
  display: block;
  padding: 0;
  overflow: visible;
}

.q-stage {
  position: sticky;
  top: var(--hh);
  min-height: calc(100vh - var(--hh));
  min-height: calc(100svh - var(--hh));
  min-height: calc(100lvh - var(--hh));
  /* Hauteur fixe (27/10) : le titre et le pied de page ne bougent pas, la liste
     des questions prend la place restante et défile si elle ne suffit pas. */
  height: calc(100vh - var(--hh));
  height: calc(100svh - var(--hh));
  height: calc(100lvh - var(--hh));
  display: flex;
  flex-direction: column;
}

/* Le contenu prend la place libre ; le pied de page est tout en bas de la
   scène. Les remplissages sont ceux qui étaient sur le chapitre. */
.q-stage > .wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding-top: var(--ty, var(--hpt));
  padding-bottom: clamp(16px, 3vh, 32px);
}

.q-stage > .wrap > h2 { flex: none; }

.faq-l {
  margin: 9px calc(var(--hpad) - var(--hr)) 0 var(--hshift);
  max-width: 620px;
  border-top: 2px solid var(--rule);
  /* La liste défile dans la place laissée par le titre et le pied de page ; un
     fondu (--ft, --fb, posés par le script) masque ce qui est coupé. */
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Pas de glissement de côté : « overflow-y: auto » laisse overflow-x à auto, et
     sur iPhone la liste se laissait tirer vers la gauche sans rien à voir
     (retour de Matthieu du 30/10 ; aucun débordement mesuré, 310 = 310 px). */
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--ft, 0px), #000 calc(100% - var(--fb, 0px)), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--ft, 0px), #000 calc(100% - var(--fb, 0px)), transparent 100%);
}
.faq-l::-webkit-scrollbar { display: none; }

.faq-l summary {
  cursor: pointer;
  list-style: none;
  padding: 16px 28px 16px 0;
  font-weight: 650;
  font-size: 16.5px;
  position: relative;
}

.faq-l summary::-webkit-details-marker { display: none; }

.faq-l summary::after {
  content: "+";
  content: "+" / "";
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--display);
  font-size: 20px;
  color: var(--accent);
  transition: transform 0.2s ease;
}

.faq-l details[open] summary::after { transform: translateY(-50%) rotate(45deg); }

@media (prefers-reduced-motion: reduce) {
  .faq-l summary::after { transition: none; }
}

.faq-l .answer { padding: 0 0 18px; color: var(--ink); font-size: 15.5px; max-width: 620px; }

/* Téléphone : questions un peu plus serrées, pour que la dernière page, pied
   de page compris, tienne dans l'écran. */
@media (max-width: 700px) {
  .faq-l summary { padding: 13px 28px 13px 0; }
}

/* Écran bas (iPhone SE, 667 px) : les titres des pages 4 à 6 restent à la
   hauteur de celui de la page 1 ; les rangées se resserrent pour que chaque
   page tienne dans l'écran. */
@media (max-height: 499px) {
  .q-stage { height: auto; }
  .q-stage > .wrap { flex: 1 0 auto; }
  .faq-l { overflow: visible; -webkit-mask-image: none; mask-image: none; }
}

@media (max-height: 700px) {
  .points li { padding: 11px 0; }
  .faq-l summary { padding-top: 10px; padding-bottom: 10px; }
}

/* ---------- pages intérieures ---------- */

main.page { padding: 56px 0 72px; }

main.page h1 { font-size: 32px; margin-bottom: 8px; }

.updated { font-size: 14px; color: var(--muted); margin-bottom: 34px; }

main.page h2 { font-size: 21px; margin: 34px 0 10px; }

main.page ul { margin: 0 0 14px 22px; }

main.page li { margin-bottom: 6px; }

main.page p { margin-bottom: 14px; }

.faq dt { font-weight: 650; margin-top: 24px; }

.faq dd { margin: 6px 0 0; color: var(--ink); }

/* ---------- pied ---------- */

/* Le pied de page reprend le trait noir de 2 px de l'en-tête et sa hauteur :
   70 px sous le trait, comme l'en-tête fait 70 px au-dessus du sien (10/10). */
footer.site {
  border-top: calc(2px * var(--zi)) solid var(--ink);
  /* La hauteur suit le texte (13/10, demande de Matthieu : sur une ligne, le
     pied rend sa place au reste de la page). Deux lignes : 12 + 12 px d'air
     autour de 46 px de texte, soit ≈ 72 px comme avant (70 px sous le trait,
     comme l'en-tête au-dessus du sien) ; une ligne : ≈ 45 px. Sur les accueils,
     le script recopie la hauteur réelle dans --foot (le rond « retour en haut »
     et le bas de la barre se posent au-dessus du trait). */
  padding: calc(12px * var(--zi)) 0;
  display: flex;
  align-items: center;
  font-size: calc(13px * var(--zi));
  line-height: 1.45;
  color: var(--muted);
}

/* Le texte du pied est aligné à gauche, au même bord que tous les autres textes
   du site (10/10, v60 ; avant, centré). Pages intérieures : le bloc
   `.wrap` ordinaire, donc le bord du texte de la page. Accueils (le pied est
   dans #questions) : le bord du titre (--hl + --hshift, variables héritées du
   chapitre), avec la marge de droite étroite des carrés et des listes
   (--hpad), pour que les liens et le copyright tiennent sur peu de lignes.
   Pages intérieures (12/10) : le bord gauche reste celui du texte (colonne de
   700 px centrée), mais le pied n'est plus borné par cette colonne : il se
   prolonge vers la droite, où la place est libre, pour que les liens et le
   copyright tiennent sur une ligne sur grand écran. */
footer.site .wrap {
  flex: 1 1 auto;
  min-width: 0;
  max-width: none;
  margin: 0 0 0 max(0px, calc((100% - 700px) / 2));
}

#questions footer.site .wrap {
  margin: 0;
  padding-left: var(--hl);
  padding-right: var(--hr);
}

#questions footer.site .row {
  margin: 0 calc(var(--hpad) - var(--hr)) 0 var(--hshift);
}

footer.site .row {
  display: flex;
  /* Les liens et le copyright sur une seule ligne quand la place le permet
     (12/10, demande de Matthieu ; avant, le copyright était toujours dessous,
     neuvième passe du 10/10). Sinon le copyright passe dessous, au même bord
     gauche, 8 px plus bas : le retour à la ligne est celui de flex-wrap, il
     suit la largeur réelle du texte, pas un seuil d'écran. */
  flex-wrap: wrap;
  align-items: baseline;
  text-align: left;
  column-gap: calc(36px * var(--zi));
  row-gap: calc(8px * var(--zi));
}

/* Zone d'appui : 12 px au-dessus et au-dessous du texte (≈ 43 px de haut), pas
   plus que le remplissage du pied (12 px) : sur une ligne, les liens sont au
   bord bas du pied, et 14 px dépassaient de 2 px sous lui, donc 2 px de défilement
   en trop (mesuré le 13/10). */
footer.site a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; display: inline-block; padding: calc(12px * var(--zi)) 0; margin: calc(-12px * var(--zi)) 0; }

/* Point médian entre les liens : hors du soulignement (inline-block),
   couleur stable, un peu d'air de chaque côté. */
footer.site a + a::before {
  content: "·";
  content: "·" / "";
  display: inline-block;
  text-decoration: none;
  color: var(--muted);
  margin: 0 calc(10px * var(--zi)) 0 calc(6px * var(--zi));
}

@media (hover: hover) {
  footer.site a:hover { color: var(--accent); }
}

/* Sur téléphone les liens se rangent sur plusieurs lignes : un écart franc
   remplace les points médians, qui se retrouveraient en tête de ligne. */
@media (max-width: 560px) {
  /* Liens, 8 px d'air, puis le copyright sur deux lignes : ≈ 72 px avec cet
     interligne (17 + 8 + 34 + 12 de remplissage + 2 de trait). */
  footer.site { font-size: calc(12.5px * var(--zi)); line-height: 1.35; padding-top: calc(6px * var(--zi)); padding-bottom: calc(6px * var(--zi)); }
  /* Écart entre les liens : 16 px quand la place le permet, 8 px à 375 px (les
     quatre liens font 284 px, la place à gauche du texte en laisse 310 à 375 px :
     sur deux lignes, le pied dépasserait ses 70 px). */
  footer.site .row > div:first-child {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    column-gap: calc(clamp(8px, calc(8px + (100vw * var(--z) - 375px) * 0.3), 16px) * var(--zi));
  }
  footer.site a + a::before { display: none; }
}

/* Écrans tactiles : la dernière page suit la hauteur visible (12/10, mesuré
   dans Safari iOS 26.5). Le navigateur borne l'élan vers un cran à
   « hauteur du document − 812 pt » (l'écran moins la barre d'état), barre du
   bas repliée ou non ; le cran de la dernière page est 58 pt plus bas : l'élan
   s'arrêtait 58 pt trop tôt, puis la page sautait d'un coup à sa place (v74).
   Le document doit donc se prolonger d'au moins 58 pt sous ce cran : la piste
   (#questions) est plus haute que la scène (.q-stage) de 100lvh − 100dvh + 80 px,
   et la scène, collante, ne bouge pas pendant ce prolongement. La scène suit
   la hauteur visible (100dvh : barre déployée ou repliée, le pied de page
   reste entier au bas de l'écran, le titre ne bouge pas) ; la piste, elle,
   garde la même hauteur à toute position de la barre (100lvh + 10 px).
   Écran bas (paysage) : inchangé, F1 y joue encore. */
@media (hover: none) and (pointer: coarse) and (min-height: 500px) {
  @supports (height: 100dvh) {
    #questions { min-height: calc(100lvh - var(--hh) + 80px); }
    .q-stage { min-height: calc(100dvh - var(--hh)); height: calc(100dvh - var(--hh)); }
  }
}

/* ---------- texte agrandi (Safari « aA », classe .zoomed de theme.js) ----------
   Le zoom de page grossit déjà chaque longueur en px. Ces règles ne font
   qu'empêcher la page de se coincer : titres forcés sur une ligne, chapitres
   coupés à un écran, scène collante, dernière page hors d'atteinte. À la
   taille normale (pas de classe) rien ici ne s'applique. */

html.zoomed .hero,
html.zoomed #idee,
html.zoomed .ecran,
html.zoomed #questions {
  overflow: visible;
  justify-content: flex-start;
}

/* Le titre de l'accueil est calculé pour tenir sur une ligne de la largeur
   courante : comme cette largeur rétrécit avec le zoom, le titre ne grossissait
   pas. On le cale sur la largeur de l'appareil (vw × --z) et on le laisse
   revenir à la ligne. */
html.zoomed .hero h1,
html.zoomed #idee h2,
html.zoomed .ecran h2,
html.zoomed #questions h2 {
  font-size: clamp(26px, calc(7.4vw * var(--z)), 44px);
  width: auto;
  max-width: 100%;
}

html.zoomed .hero h1 span { white-space: normal; }

html.zoomed #idee .titre { height: auto; }

/* Le rond « retour en haut » est fixe, sur la barre. Le texte des piliers
   partait au ras de cette barre et passait sous le rond. */
html.zoomed .progress ~ main section .wrap {
  padding-left: calc(var(--rail) + var(--up) / 2 + 22px);
}

/* « Visualisation » sortait de son rond : le rond rétrécit avec la page,
   l'étiquette gardait une taille de plancher. Elle se cale sur le rond
   et peut revenir à la ligne. */
html.zoomed .orb { container-type: inline-size; }
html.zoomed .orb span {
  font-size: 13cqw;
  line-height: 1.05;
  letter-spacing: 0;
  white-space: normal;
  max-width: 84%;
  overflow-wrap: anywhere;
}

/* Les noms de chapitre sont calés sur un écran : dès que les chapitres
   s'allongent, ils se chevauchent. La barre noire et le rond restent. */
html.zoomed .rail { display: none; }

/* Filet, si la classe .scrub est encore là : les sept textes à la suite,
   plus de scène d'un écran qui les coupe. */
html.zoomed.scrub .corps-track { height: auto; }
html.zoomed.scrub .corps-stage {
  position: static;
  height: auto;
  overflow: visible;
}
html.zoomed.scrub .mod,
html.zoomed.scrub .mod.prev,
html.zoomed.scrub .mod.on,
html.zoomed.scrub .mod.next,
html.zoomed.scrub .mod.before {
  grid-area: auto;
  margin-top: 36px;
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
html.zoomed.scrub .mod h3,
html.zoomed.scrub .mod.prev h3,
html.zoomed.scrub .mod.next h3 { transform: none; }
html.zoomed.js.scrub .mod:not(.on) .c-promise,
html.zoomed.js.scrub .mod:not(.on) .c-txt { opacity: 1; }

html.zoomed .q-stage,
html.zoomed #questions {
  position: static;
  min-height: 0;
  height: auto;
}

html.zoomed .faq-l {
  overflow: visible;
  -webkit-mask-image: none;
  mask-image: none;
}

/* Le pied était en px × --zi : il gardait sa taille d'écran et n'obéissait
   pas au réglage. */
html.zoomed footer.site { font-size: 15px; }
