/* ══════════════════════════════════════════════════════════════════════════
   Les polices, hébergées ici.

   Aucune requête vers un tiers : une page qui promet que rien ne sort de
   l'appareil n'a pas à aller chercher son alphabet ailleurs. Trois familles,
   trois rôles, et rien de plus.

     Instrument Serif  les titres. Un display à fort contraste : c'est lui,
                       et rien d'autre, qui donne au site sa voix.
     Geist             le texte courant. Une grotesque neutre, variable de
                       300 à 700 — un seul fichier pour toutes les graisses.
     Geist Mono        les étiquettes techniques, les chiffres, le timecode.
                       Chasse fixe : les nombres s'alignent d'une ligne à
                       l'autre sans qu'on ait à le demander.

   `font-display: swap` : le texte s'affiche tout de suite dans la pile
   système, puis se recompose. Jamais de page blanche en attendant.
   ══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/InstrumentSerif-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/InstrumentSerif-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/Geist-300-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/Geist-300-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/GeistMono-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/GeistMono-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ══════════════════════════════════════════════════════════════════════════
   Cutter — le site.

   Direction : vol de nuit. Un poste de pilotage éteint, une seule lampe
   ambre, et beaucoup de noir autour. La richesse vient de la profondeur, de
   la lumière et du vide — jamais de la couleur ni de la décoration.

   Trois principes tenus dans tout ce fichier :

   1. PAS DE BOÎTES. Une carte à bord arrondi est un aveu : on ne sait pas
      où poser l'information, alors on l'enferme. Ici l'information est tenue
      par la typographie, des filets d'un pixel, des chiffres et du vide.
   2. UN SEUL ACCENT. L'ambre ne sert qu'à ce qui est vivant : la position de
      lecture, le lien survolé, le chiffre du chapitre en cours. Partout
      ailleurs, des gris.
   3. LE MOUVEMENT A DU POIDS. Une seule courbe d'accélération pour tout le
      site, des durées longues, et rien qui démarre ou s'arrête sec.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Encres ──────────────────────────────────────────────────────────── */
  --ink:     #080A0E;
  --ink-2:   #0B0E14;
  --paper:   #E9EDF3;
  --soft:    #B4BCC9;
  --dim:     #848D9E;
  --dimmer:  #5A6373;
  --amber:   #FFB020;

  --line:    rgba(233, 237, 243, .095);
  --line-2:  rgba(233, 237, 243, .19);
  --amber-a: rgba(255, 176, 32, .16);

  /* ── Fontes ──────────────────────────────────────────────────────────── */
  /* Trois familles, trois rôles, et la pile système en secours derrière
     chacune — si un fichier manque, la hiérarchie tient encore.
       display : la voix du site, un serif de titrage à fort contraste ;
       sans    : le texte, une grotesque neutre qui ne demande rien ;
       mono    : la couche technique — étiquettes, chiffres, timecode. */
  --display: "Instrument Serif", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* ── Échelle typographique ───────────────────────────────────────────── */
  --t-display: clamp(3.2rem, 6.7vw, 6.6rem);
  --t-h1:      clamp(2.5rem, 6.2vw, 5.0rem);
  --t-h2:      clamp(2.0rem, 3.8vw, 3.3rem);
  --t-h3:      clamp(1.15rem, 1.6vw, 1.45rem);
  --t-lede:    clamp(1.1rem, 1.65vw, 1.42rem);
  --t-body:    1.0625rem;
  --t-small:   .9375rem;
  --t-label:   .6875rem;

  /* ── Trame ───────────────────────────────────────────────────────────── */
  --gut:   clamp(22px, 5vw, 76px);
  --shell: 1320px;
  --measure: 62ch;
  --rail:  clamp(0px, 7vw, 116px);   /* colonne des chiffres de chapitre */

  /* ── Rythme vertical ─────────────────────────────────────────────────── */
  --v-xs: clamp(14px, 2vh, 22px);
  --v-s:  clamp(24px, 4vh, 44px);
  --v-m:  clamp(44px, 8vh, 88px);
  --v-l:  clamp(72px, 14vh, 168px);
  --v-xl: clamp(110px, 22vh, 260px);

  /* ── Mouvement ───────────────────────────────────────────────────────── */
  /* Une seule sortie (expo out) et une seule courbe symétrique. Tout le site
     accélère et freine de la même façon : c'est ce qui donne l'impression
     d'un seul geste plutôt que de vingt animations empilées. */
  --ease:     cubic-bezier(.22, 1, .36, 1);
  --ease-io:  cubic-bezier(.65, .02, .28, 1);
  --slow:     820ms;
  --med:      620ms;
  --fast:     280ms;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--ink);
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.66;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  overflow-x: hidden;
}

/* Tant que le script d'entrée n'a pas rendu la main, le contenu attend. Le
   garde-fou est dans le <head> : si le script ne vient jamais, la page
   s'affiche quand même au bout de deux secondes et demie. */
.js body > *:not(.loader):not(.skip) { opacity: 0; }
.js.is-ready body > *:not(.loader):not(.skip) { opacity: 1; transition: opacity 620ms var(--ease); }

::selection { background: var(--amber); color: var(--ink); }

/* ══ La scène ═════════════════════════════════════════════════════════════
   Un canevas fixe derrière tout. Il n'est ajouté que si WebGL répond ; sans
   lui le fond reste l'encre, et le schéma CSS du repli prend le relais. */

#scene {
  position: fixed;
  inset: 0;
  width: 100%; height: 100%;
  z-index: 0;
  display: block;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1600ms var(--ease);
}
.scene-on #scene { opacity: 1; }

/* ── Les deux distances ──────────────────────────────────────────────────
   1. LE VOILE : une nappe d'encre entre la scène et le texte, jamais
      par-dessus le texte. Elle referme les bords et laisse respirer la
      bande basse où l'empilement des pistes se tient.
   2. L'OMBRE DE BLOC (plus bas) : là où il y a du texte, la scène recule
      encore. C'est la seule qui suit réellement les zones lisibles.
   Les sections marquées `data-stage` renoncent à la seconde : ce sont les
   plans où la scène est le sujet, et où le texte se réduit à une ligne. */

body::after {
  content: "";
  position: fixed; inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      rgba(8, 10, 14, .58) 0%,
      rgba(8, 10, 14, .26) 26%,
      rgba(8, 10, 14, .12) 52%,
      rgba(8, 10, 14, .20) 74%,
      rgba(8, 10, 14, .62) 100%),
    radial-gradient(160% 96% at 50% 60%, rgba(8, 10, 14, 0) 34%, rgba(8, 10, 14, .44) 100%);
}

/* ══ Trame ════════════════════════════════════════════════════════════════ */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 var(--gut);
}
.prose { max-width: var(--measure); }
.prose p + p { margin-top: 1.1em; }

main { position: relative; z-index: 2; }

/* L'ombre de bloc : la distance locale. Sous une colonne de lecture, une
   tache d'encre sans bord, débordant largement, qui se dissout dans les
   marges — où la profondeur, elle, reste visible. Elle est peinte SOUS le
   texte (z-index négatif dans le contexte de `main`), donc au-dessus de la
   scène et jamais par-dessus une lettre.

   Seules les sections marquées `data-shade` en reçoivent une. Les plans où
   la scène est le sujet n'ont rien à céder. */
[data-shade] > .shell { position: relative; }
[data-shade] > .shell::after {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  top: -6%; bottom: -6%;
  left: calc(var(--gut) * -1.2);
  right: calc(var(--gut) * -1.2);
  background: radial-gradient(112% 78% at 50% 50%,
    rgba(8, 10, 14, .58) 0%,
    rgba(8, 10, 14, .50) 40%,
    rgba(8, 10, 14, .26) 72%,
    rgba(8, 10, 14, 0) 100%);
}

/* ══ Typographie ══════════════════════════════════════════════════════════ */

h1, h2, h3 { margin: 0; text-wrap: balance; }

/* Le display et les titres de chapitre : serif, graisse normale. Un serif de
   titrage n'a pas besoin d'être gras pour tenir une page — il a besoin
   d'être GRAND, et qu'on lui rende son interlettrage. Le tracking très
   négatif d'une grotesque le détruirait. */
.display, .h1, .h2 {
  font-family: var(--display);
  font-weight: 400;
  font-feature-settings: "kern" 1, "liga" 1;
}
.display { font-size: var(--t-display); line-height: .92;  letter-spacing: -.014em; }
.h1      { font-size: var(--t-h1);      line-height: .98;  letter-spacing: -.012em; }
.h2      { font-size: var(--t-h2);      line-height: 1.05; letter-spacing: -.010em; }
/* Les sous-titres restent en grotesque : c'est la couche de lecture, pas la
   couche de voix. */
.h3 {
  font-family: var(--sans);
  font-size: var(--t-h3); line-height: 1.32;
  letter-spacing: -.008em; font-weight: 560;
}

.lede {
  font-size: var(--t-lede);
  line-height: 1.46;
  letter-spacing: -.006em;
  font-weight: 350;
  color: var(--soft);
  max-width: 34ch;
}
p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }
.dim { color: var(--dim); }

.mono { font-family: var(--mono); }
.num  { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: .005em; }

.label {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dimmer);
}
.label b { color: var(--amber); font-weight: 500; }

/* ── Liens ───────────────────────────────────────────────────────────────
   Aucun soulignement statique : un filet qui se trace de la gauche vers la
   droite au survol. C'est le seul mouvement d'un lien de texte. */
a { color: inherit; text-decoration: none; }

.lnk {
  position: relative;
  color: var(--paper);
  padding-bottom: .12em;
  transition: color var(--fast) var(--ease);
}
.lnk::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(var(--sx, 1));
  transform-origin: right;
  opacity: .32;
  transition: transform 520ms var(--ease), opacity var(--fast) linear;
}
.lnk:hover, .lnk:focus-visible { color: var(--amber); }
.lnk:hover::after, .lnk:focus-visible::after {
  transform-origin: left;
  transform: scaleX(1);
  opacity: 1;
}
/* Le trait part de zéro puis se déploie : deux temps, une seule origine. */
.lnk:hover::after { animation: trace 620ms var(--ease); }
@keyframes trace { from { transform: scaleX(0); transform-origin: left; } }

:focus-visible { outline: 1px solid var(--amber); outline-offset: 4px; }

.skip {
  position: fixed; left: -9999px; top: 0; z-index: 120;
  background: var(--amber); color: var(--ink);
  padding: 12px 18px; font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

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

/* ══ Révélations ══════════════════════════════════════════════════════════
   Deux primitives, pas davantage. Un bloc qui monte, et une ligne qui sort
   de son masque. Le décalage se donne en CSS par `--d`, jamais en JS. */

.js [data-rise] {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
  transition-delay: var(--d, 0ms);
}
.js [data-rise].is-in { opacity: 1; transform: none; }

/* Le masque doit laisser passer les descendantes : sans cette marge, le
   « g » d'un titre en 0.88 d'interligne est coupé net par l'overflow. */
.line { display: block; overflow: hidden; padding-bottom: .14em; margin-bottom: -.14em; }
.line > i {
  display: block;
  font-style: inherit;
  transform: translate3d(0, 108%, 0);
  transition: transform 950ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.js .is-in .line > i, .js .line.is-in > i { transform: none; }
/* Sans JS, rien n'est masqué : le texte est simplement là. */
html:not(.js) .line > i { transform: none; }

/* Le mot par mot : chaque mot est une petite fenêtre, et son contenu monte
   à son tour. Le décalage est posé sur le mot par le script ; la mécanique
   reste ici. Sans le script, il n'y a ni fenêtre ni décalage. */
.w { display: inline-block; overflow: hidden; vertical-align: top;
     padding-bottom: .14em; margin-bottom: -.14em; }
.w > i {
  display: inline-block;
  font-style: inherit;
  transform: translate3d(0, 108%, 0);
  transition: transform 880ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.js .is-in .w > i { transform: none; }
/* Quand les mots ont été empaquetés, la ligne cesse d'être un masque : sinon
   le texte parcourt deux fois la même distance et l'entrée traîne. */
.is-split .line > i { transform: none; transition: none; }

.js [data-fade] { opacity: 0; transition: opacity var(--slow) var(--ease); transition-delay: var(--d, 0ms); }
.js [data-fade].is-in { opacity: 1; }

/* ══ Le chargement ════════════════════════════════════════════════════════
   Pas de pourcentage qui compte pour rien : un filet qui se remplit pendant
   que la scène se compile, puis un rideau qui s'ouvre par le haut. */

.loader {
  position: fixed; inset: 0; z-index: 100;
  background: var(--ink);
  display: grid;
  place-content: center;
  gap: 26px;
  transition: opacity 520ms var(--ease), visibility 0s linear 520ms;
}
.is-ready .loader { opacity: 0; visibility: hidden; pointer-events: none; }
.loader__mark { display: flex; align-items: center; gap: 12px; }
.loader__name {
  font-size: var(--t-label);
  letter-spacing: .34em;
  text-transform: uppercase;
  font-family: var(--mono);
  color: var(--dim);
}
.loader__bar {
  width: min(320px, 46vw); height: 1px;
  background: var(--line-2);
  position: relative; overflow: hidden;
}
.loader__bar i {
  position: absolute; inset: 0 auto 0 0;
  width: var(--p, 0%);
  background: var(--amber);
  transition: width 420ms var(--ease);
}

/* ══ L'en-tête ════════════════════════════════════════════════════════════
   Un filet, un nom, cinq mots, un chiffre. Rien à cliquer par erreur. */

.head {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 60;
  padding: clamp(16px, 2.4vh, 26px) 0;
  pointer-events: none;
  transition: transform 620ms var(--ease), opacity 420ms linear;
}
.head__in {
  display: flex; align-items: center; gap: clamp(16px, 3vw, 40px);
}
.head a, .head button { pointer-events: auto; }

/* Elle se retire quand on descend, revient dès qu'on remonte. */
.is-hidden .head { transform: translate3d(0, -120%, 0); opacity: 0; }

.brand {
  display: inline-flex; align-items: center; gap: 11px;
  font-size: .95rem; font-weight: 560; letter-spacing: -.004em;
  color: var(--paper);
}
.brand__mark {
  display: block; width: 24px; height: 13px;
  background-image:
    linear-gradient(var(--amber), var(--amber)),
    linear-gradient(var(--dim), var(--dim)),
    linear-gradient(var(--dim), var(--dim)),
    linear-gradient(var(--dim), var(--dim));
  background-size: 3px 13px, 3px 8px, 3px 13px, 3px 6px;
  background-position: 0 0, 7px 3px, 14px 0, 21px 4px;
  background-repeat: no-repeat;
  transition: background-position 700ms var(--ease);
}
.brand:hover .brand__mark { background-position: 0 0, 7px 5px, 14px 0, 21px 2px; }

.nav {
  display: flex; gap: clamp(14px, 2vw, 30px);
  margin-left: auto;
  font-size: .85rem;
  color: var(--dim);
}
/* Sous 900 px, la barre de liens ne tient pas : plutôt que de la laisser
   déborder ou de la faire défiler latéralement — les deux se voient —, on
   la retire. Le pied de page porte la navigation complète, et l'index de
   l'accueil aussi. Ne reste en haut que la marque et l'essai. */
@media (max-width: 899px) {
  .nav { display: none; }
  .head__cta { margin-left: auto; }
}
.nav a { position: relative; transition: color var(--fast) linear; }
.nav a:hover { color: var(--paper); }
.nav a::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -6px; height: 1px;
  background: var(--amber);
  transform: scaleX(0); transform-origin: right;
  transition: transform 460ms var(--ease);
}
.nav a:hover::after, .nav a[aria-current]::after { transform: scaleX(1); transform-origin: left; }
.nav a[aria-current] { color: var(--paper); }

.head__cta {
  font-size: .85rem; font-weight: 560;
  color: var(--amber);
  display: inline-flex; align-items: center; gap: 9px;
}
.head__cta i {
  display: block; width: 18px; height: 1px; background: currentColor;
  transition: width 460ms var(--ease);
}
.head__cta:hover i { width: 30px; }

/* Le filet de progression, collé sous l'en-tête, sur toute la largeur. */
.head__rule {
  position: fixed; top: 0; left: 0; right: 0; height: 1px;
  z-index: 61;
  background: var(--line);
  transform-origin: left;
}
.head__rule i {
  display: block; height: 100%; width: 100%;
  background: var(--amber);
  transform: scaleX(var(--p, 0)); transform-origin: left;
  opacity: .55;
}

/* ══ Le bandeau de transport ══════════════════════════════════════════════
   Fixe en bas : timecode, position, nom du plan en cours. C'est l'interface
   qui relie la page à la scène — et le seul endroit où le site s'autorise
   à parler comme un banc de montage. */

.hud {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  padding: 0 var(--gut) clamp(14px, 2.4vh, 22px);
  pointer-events: none;
  display: flex; align-items: baseline; gap: clamp(12px, 2vw, 26px);
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--dimmer);
  transition: opacity 620ms var(--ease);
}
.is-hidden .hud { opacity: 0; }
.hud__tc { color: var(--dim); font-variant-numeric: tabular-nums; letter-spacing: .1em; }
.hud__clip {
  color: var(--dim);
  margin-left: auto;
  max-width: 46vw; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.hud__clip b { color: var(--amber); font-weight: 500; }
.hud__bar {
  flex: 1 1 120px; max-width: 320px;
  height: 1px; background: var(--line-2); position: relative;
}
.hud__bar i {
  position: absolute; inset: 0 auto 0 0;
  width: var(--p, 0%);
  background: var(--amber);
}
@media (max-width: 700px) { .hud__clip { display: none; } }

/* ══ Le curseur ═══════════════════════════════════════════════════════════
   Un anneau qui suit avec du retard, un point qui suit sans retard. Le
   décalage entre les deux est tout l'effet. Souris fine uniquement. */

.cur, .cur-dot {
  position: fixed; top: 0; left: 0;
  z-index: 95;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 300ms linear;
}
.cur {
  width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border: 1px solid var(--line-2);
  transition: opacity 300ms linear, width 460ms var(--ease), height 460ms var(--ease),
              margin 460ms var(--ease), border-color 300ms linear, background 300ms linear;
}
.cur-dot { width: 4px; height: 4px; margin: -2px 0 0 -2px; background: var(--paper); }
.cur-on .cur, .cur-on .cur-dot { opacity: 1; }
.cur-link .cur {
  width: 62px; height: 62px; margin: -31px 0 0 -31px;
  border-color: var(--amber);
  background: var(--amber-a);
}
.cur-link .cur-dot { opacity: 0; }

/* ══ L'ouverture ══════════════════════════════════════════════════════════ */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-content: center;
  padding: clamp(96px, 15vh, 160px) 0 clamp(88px, 14vh, 140px);
}
/* Deux colonnes : le texte, et le vide où se tient l'appareil. La seconde
   colonne ne contient rien — c'est une réservation d'espace, pas un oubli.
   Une composition se décide avant d'être remplie. */
.hero__grid { display: grid; gap: var(--v-m) clamp(30px, 5vw, 80px); }
@media (min-width: 1000px) {
  .hero__grid { grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr); align-items: center; }
}
.hero__text { max-width: 34rem; }
/* La colonne réservée à l'appareil. Vide par construction : la scène est
   derrière le contenu, et c'est cette cellule qui lui garde sa place dans
   la grille au lieu de la laisser au hasard du texte. */
.hero__void { display: none; }
@media (min-width: 1000px) { .hero__void { display: block; min-height: 46vh; } }
.hero__eyebrow { margin: 0 0 var(--v-s); }
.hero .display { margin: 0 0 var(--v-s); max-width: 11ch; }
.hero .lede { margin-bottom: var(--v-m); }
.hero__note { color: var(--dimmer); font-size: var(--t-small); max-width: 40ch; margin-top: var(--v-s); }

/* L'ombre de bloc du hero ne couvre que la colonne de texte : à droite, la
   scène est le sujet et ne doit rien céder. Un dégradé LATÉRAL, pas un
   rectangle rogné — une ombre qui s'arrête net dessine une boîte, et on
   passe une heure à se demander d'où sort ce rectangle gris. */
@media (min-width: 1000px) {
  .hero > .shell::after {
    background: linear-gradient(96deg,
      rgba(8, 10, 14, .80) 0%,
      rgba(8, 10, 14, .74) 26%,
      rgba(8, 10, 14, .42) 42%,
      rgba(8, 10, 14, .12) 54%,
      rgba(8, 10, 14, 0) 64%);
  }
}

/* Les actions : pas de bouton-boîte. Un mot, un filet, une flèche. */
.acts { display: flex; flex-wrap: wrap; gap: clamp(20px, 3vw, 42px); align-items: center; }

.act {
  position: relative;
  display: inline-flex; align-items: center; gap: 12px;
  font-size: 1rem; font-weight: 500; letter-spacing: -.004em;
  padding: 10px 0;
  color: var(--paper);
}
.act__line {
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--line-2);
  overflow: hidden;
}
.act__line::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--amber);
  transform: scaleX(0); transform-origin: right;
  transition: transform 560ms var(--ease);
}
.act:hover .act__line::after, .act:focus-visible .act__line::after {
  transform: scaleX(1); transform-origin: left;
}
.act__arw {
  display: block; width: 22px; height: 1px; background: currentColor;
  position: relative;
  transition: width 460ms var(--ease), background 300ms linear;
}
.act__arw::after {
  content: "";
  position: absolute; right: 0; top: -3px;
  width: 7px; height: 7px;
  border-top: 1px solid currentColor; border-right: 1px solid currentColor;
  transform: rotate(45deg);
}
.act:hover .act__arw { width: 38px; }
.act--key { color: var(--amber); }
.act--key .act__line { background: var(--amber-a); }


/* ══ LES MISES EN PAGE DE SÉQUENCE ═══════════════════════════════════════
   La scène dicte la composition, pas l'inverse. Chaque section déclare la
   sienne par `data-lay`, et deux sections voisines ne se ressemblent pas :
   c'est le contraste qui fait le rythme, pas l'accumulation d'effets.

     bas      une ligne, posée bas à gauche, le cadre appartient à la scène
     droite   le texte bascule à droite — la seule fois du site
     colonne  une colonne étroite, très à gauche, le reste est vide
     ecart    deux blocs éloignés, le vide entre eux fait la composition
     plan     le calme : mesuré, aligné, presque un tableau               */

[data-lay] > .shell { position: relative; }

[data-lay="bas"] { min-height: 100svh; display: grid; align-content: end; padding: var(--v-l) 0 var(--v-xl); }
[data-lay="bas"] .seq__t { max-width: 16ch; }

[data-lay="droite"] { min-height: 100svh; display: grid; align-content: center; padding: var(--v-l) 0; }
[data-lay="droite"] .shell { display: flex; justify-content: flex-end; }
[data-lay="droite"] .seq { max-width: 30rem; text-align: right; }
[data-lay="droite"] .seq__t { max-width: none; }
[data-lay="droite"] .label { display: block; }

[data-lay="colonne"] { min-height: 100svh; display: grid; align-content: center; padding: var(--v-l) 0; }
[data-lay="colonne"] .seq { max-width: 21rem; }

[data-lay="ecart"] .shell { display: grid; gap: var(--v-l) clamp(30px, 6vw, 110px); }
@media (min-width: 1000px) {
  [data-lay="ecart"] .shell { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start; }
  [data-lay="ecart"] .seq { position: sticky; top: 22vh; }
}

[data-lay="plan"] .shell { max-width: 1120px; }

/* Dans les séquences où la scène est le sujet, le texte ne reçoit pas
   d'ombre de section — mais il en reçoit une, très douce, SOUS LUI SEUL.
   Sinon une phrase tombe sur une dalle éclairée et devient illisible, et
   c'est la scène qu'on accuse. */
.seq { position: relative; }
.seq::before {
  content: "";
  position: absolute;
  inset: -8% -14% -14%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(78% 72% at 50% 50%,
    rgba(8, 10, 14, .82) 0%,
    rgba(8, 10, 14, .66) 46%,
    rgba(8, 10, 14, .22) 74%,
    rgba(8, 10, 14, 0) 100%);
}

/* Le titre de séquence : très grand, et un chiffre minuscule à côté. C'est
   le contraste d'échelle qui donne la mesure, pas la taille seule. */
.seq__t {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.4rem, 6.4vw, 5.4rem);
  line-height: .98;
  letter-spacing: -.014em;
  margin: 0;
}
.seq__k { margin-bottom: var(--v-s); }
.seq__d { color: var(--dim); max-width: 40ch; margin-top: var(--v-s); font-size: var(--t-small); }
[data-lay="droite"] .seq__d { margin-left: auto; }

/* ── Le dévoilement par masque ───────────────────────────────────────────
   Pas un fondu : un balayage. L'élément est entier dès le départ, c'est la
   fenêtre qui s'ouvre. Un filet, un libellé, une image se révèlent ainsi. */
/* Le déclencheur est porté par le BLOC, pas par l'élément masqué : un
   élément dont le `clip-path` est réduit à zéro n'est plus considéré comme
   intersectant, et l'observateur qui doit le révéler ne le voit jamais. Le
   masque se dévorait lui-même. */
.js [data-wipe] {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 900ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.js .is-in [data-wipe], .js [data-wipe].is-in { clip-path: inset(0 0 0 0); }
html:not(.js) [data-wipe] { clip-path: none; }

/* ── Le compteur qui roule ───────────────────────────────────────────────
   Le numéro de séquence ne change pas : il DÉFILE. Une fenêtre d'une ligne,
   une colonne de chiffres, et un décalage piloté par le script. */
.roll {
  display: inline-block;
  height: 1em; overflow: hidden;
  vertical-align: -0.12em;
}
.roll b {
  display: block; font-weight: inherit;
  transform: translateY(calc(var(--i, 0) * -1em));
  transition: transform 720ms var(--ease);
}

/* ── Le libellé accroché à la scène ──────────────────────────────────────
   Il suit la tête de lecture dans l'espace 3D. Sa position vient du moteur,
   pas d'une approximation en CSS : c'est le seul endroit du site où la page
   et la scène partagent des coordonnées. */
.pin {
  position: fixed;
  z-index: 3;
  transform: translate3d(var(--px, 50vw), var(--py, 50vh), 0) translate(14px, -50%);
  opacity: var(--pv, 0);
  transition: opacity 420ms linear;
  pointer-events: none;
  display: flex; align-items: center; gap: 9px;
  font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .18em; text-transform: uppercase; color: var(--dim);
  white-space: nowrap;
}
.pin::before { content: ""; width: 22px; height: 1px; background: var(--amber); }
@media (max-width: 899px) { .pin { display: none; } }

/* ══ Chapitres ════════════════════════════════════════════════════════════
   Chaque section porte son chiffre dans une colonne à gauche, alignée sur
   la même verticale d'un bout à l'autre du site. C'est cette colonne, et
   non des cadres, qui tient la page. */

.chap {
  position: relative;
  padding: var(--v-l) 0;
}
.chap__in {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--v-s);
}
@media (min-width: 900px) {
  .chap__in { grid-template-columns: var(--rail) minmax(0, 1fr); gap: 0 clamp(24px, 3vw, 56px); }
}
.chap__no {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: .18em;
  color: var(--dimmer);
  display: flex; align-items: baseline; gap: 10px;
}
.chap__no b { color: var(--amber); font-weight: 500; }
@media (min-width: 900px) {
  .chap__no {
    position: sticky; top: clamp(78px, 12vh, 118px);
    align-self: start;
    display: block;
  }
  .chap__no b { display: block; margin-bottom: 8px; }
}
.chap__body { min-width: 0; }

.chap__title { margin: 0 0 var(--v-s); max-width: 20ch; }
.chap__intro { color: var(--dim); max-width: 52ch; margin: 0 0 var(--v-m); font-size: 1.0625rem; }

/* Un filet qui ouvre le chapitre et se trace quand il entre dans le cadre. */
.rule {
  height: 1px; background: var(--line);
  transform: scaleX(0); transform-origin: left;
  transition: transform 1100ms var(--ease);
  margin-bottom: var(--v-s);
}
.js .is-in .rule, .js .rule.is-in { transform: scaleX(1); }
html:not(.js) .rule { transform: none; }

/* ══ Faits ════════════════════════════════════════════════════════════════
   Ce qui était six cartes bordées. Devenu six lignes d'un relevé : un
   numéro, un intitulé, une explication. Les filets font le travail. */

.facts { display: grid; gap: 0; }
.fact {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px clamp(20px, 3vw, 48px);
  padding: clamp(22px, 3vh, 34px) 0;
  border-top: 1px solid var(--line);
  position: relative;
}
.fact:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 760px) {
  .fact { grid-template-columns: 3.5rem minmax(0, 15rem) minmax(0, 1fr); align-items: baseline; }
}
.fact__k { font-family: var(--mono); font-size: var(--t-label); color: var(--amber); letter-spacing: .16em; }
.fact__t { font-size: 1.0625rem; font-weight: 520; letter-spacing: -.008em; }
.fact__d { color: var(--dim); font-size: var(--t-small); }
/* Le survol n'agrandit rien : il éclaire la ligne et avance le titre. */
.fact::before {
  content: "";
  position: absolute; left: 0; top: -1px; height: 1px; right: 0;
  background: var(--amber);
  transform: scaleX(0); transform-origin: left;
  transition: transform 700ms var(--ease);
}
.fact:hover::before { transform: scaleX(1); }
.fact__t, .fact__k { transition: transform 560ms var(--ease); }
.fact:hover .fact__t, .fact:hover .fact__k { transform: translateX(6px); }

/* ══ Deux colonnes ════════════════════════════════════════════════════════ */

.split { display: grid; gap: var(--v-m) clamp(30px, 5vw, 90px); align-items: start; }
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .split--wide { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
  .split--rev > *:first-child { order: 2; }
}
.split p { color: var(--dim); }
.split .h3 { color: var(--paper); margin-bottom: var(--v-xs); max-width: 24ch; }

/* Les pages de détail écrivent des `<h3>` nus dans leur prose : ils prennent
   la même valeur que `.h3` sans avoir à porter la classe. Le style suit le
   rôle, pas le nom. */
.prose h3, .point__body h3, .fact h3, .card h3 {
  font-size: var(--t-h3);
  line-height: 1.3;
  letter-spacing: -.015em;
  font-weight: 600;
  color: var(--paper);
  margin: 0 0 var(--v-xs);
  max-width: 26ch;
}
.fact h3 { font-size: 1.0625rem; margin: 0; max-width: none; }
.fact p { color: var(--dim); font-size: var(--t-small); margin: 0; }
.card p { color: var(--dim); font-size: var(--t-small); }
.point__body p { color: var(--dim); }

/* ── Relevé clé / valeur ─────────────────────────────────────────────────*/
.kv { margin: 0; }
.kv > div {
  display: flex; justify-content: space-between; align-items: baseline; gap: 20px;
  padding: 13px 0;
  border-top: 1px solid var(--line);
}
.kv > div:last-child { border-bottom: 1px solid var(--line); }
.kv dt { color: var(--dim); font-size: var(--t-small); }
.kv dd {
  margin: 0; font-family: var(--mono); font-size: .84rem;
  color: var(--paper); font-variant-numeric: tabular-nums; text-align: right;
}
.kv dd b { color: var(--amber); font-weight: 500; }

/* ── Schéma ASCII ────────────────────────────────────────────────────────*/
.diag {
  margin: 0; padding: clamp(18px, 3vh, 28px) 0;
  overflow-x: auto;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  /* Le schéma tient en une seule ligne de 74 signes : à .8rem il
     débordait de sa colonne et se coupait au milieu d'un mot. */
  color: var(--dim); font-size: .72rem; line-height: 1.9;
  font-family: var(--mono);
}
.diag b { color: var(--amber); font-weight: 400; }
.diag i { color: var(--dimmer); font-style: normal; }

/* ── Phrases citées ──────────────────────────────────────────────────────*/
.says { margin: 0; padding: 0; list-style: none; }
.says li {
  padding: 15px 0 15px 30px;
  border-top: 1px solid var(--line);
  color: var(--paper); font-size: 1rem; position: relative;
  transition: color var(--fast) linear;
}
.says li:last-child { border-bottom: 1px solid var(--line); }
.says li::before {
  content: "»"; position: absolute; left: 0; top: 15px;
  color: var(--amber); font-family: var(--mono);
  transition: transform 460ms var(--ease);
}
.says li:hover::before { transform: translateX(4px); }

.note { color: var(--dimmer); font-size: var(--t-small); }

/* ══ Plans pleine page ════════════════════════════════════════════════════
   Les respirations. Ici la scène est le sujet : une ligne de texte au
   maximum, posée bas, et surtout du vide. `data-stage` coupe l'ombre de
   bloc — le fond n'a rien à céder à personne dans ces sections. */

.stage {
  position: relative;
  min-height: 92svh;
  display: grid; align-content: end;
  padding: var(--v-l) 0 var(--v-l);
}
.stage__line {
  font-family: var(--display);
  font-size: clamp(1.6rem, 3.6vw, 3.0rem);
  line-height: 1.14; letter-spacing: -.010em;
  font-weight: 400;
  max-width: 22ch;
}
.stage__meta { margin-top: var(--v-s); }

/* ══ Emplacements de capture ══════════════════════════════════════════════
   Les captures n'existent pas encore. Plutôt que de faire semblant, on
   montre un cadre de repérage : quatre équerres, un nom de fichier, des
   dimensions. C'est un choix assumé, pas un trou. */

.shot { margin: 0; }
.shot__frame {
  position: relative;
  display: grid; place-content: center; gap: 8px;
  aspect-ratio: 16 / 10;
  background:
    repeating-linear-gradient(135deg, rgba(233, 237, 243, .022) 0 1px, transparent 1px 9px);
  color: var(--dimmer);
  text-align: center;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: .16em;
}
.shot--tall .shot__frame { aspect-ratio: 1080 / 2340; max-width: 290px; margin-inline: auto; }
.shot__frame::before, .shot__frame::after,
.shot__frame > i::before, .shot__frame > i::after {
  content: "";
  position: absolute; width: 14px; height: 14px;
  border: 0 solid var(--line-2);
}
.shot__frame::before { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.shot__frame::after { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.shot__frame > i::before { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.shot__frame > i::after { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
.shot figcaption { margin-top: 14px; font-size: var(--t-small); color: var(--dimmer); }

/* ══ Index des pages ══════════════════════════════════════════════════════
   Ce qui était trois cartes. Devenu une liste : le titre en grand, le
   numéro en petit, un filet qui s'allume, et le tout qui avance. */

.index { border-top: 1px solid var(--line); }
.idx {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 6px 24px;
  padding: clamp(26px, 4.4vh, 46px) 0;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.idx__no { grid-column: 1; font-family: var(--mono); font-size: var(--t-label); color: var(--dimmer); letter-spacing: .2em; }
.idx__t {
  grid-column: 1; grid-row: 2;
  font-family: var(--display);
  font-size: clamp(1.75rem, 3.9vw, 2.9rem);
  letter-spacing: -.010em; font-weight: 400; line-height: 1.06;
  transition: transform 700ms var(--ease), color var(--fast) linear;
}
.idx__d {
  grid-column: 1; grid-row: 3;
  color: var(--dim); font-size: var(--t-small); max-width: 46ch; margin-top: 8px;
  transition: transform 700ms var(--ease);
}
.idx__arw {
  grid-column: 2; grid-row: 1 / 4;
  width: 34px; height: 1px; background: var(--line-2);
  position: relative;
  transition: width 620ms var(--ease), background 300ms linear;
}
.idx__arw::after {
  content: "";
  position: absolute; right: 0; top: -4px;
  width: 9px; height: 9px;
  border-top: 1px solid currentColor; border-right: 1px solid currentColor;
  color: var(--line-2);
  transform: rotate(45deg);
  transition: color 300ms linear;
}
.idx::before {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--amber);
  transform: scaleX(0); transform-origin: left;
  transition: transform 800ms var(--ease);
}
.idx:hover::before { transform: scaleX(1); }
.idx:hover .idx__t { transform: translateX(12px); color: var(--amber); }
.idx:hover .idx__d { transform: translateX(12px); }
.idx:hover .idx__arw { width: 54px; background: var(--amber); }
.idx:hover .idx__arw::after { color: var(--amber); }

/* ══ Appel final ══════════════════════════════════════════════════════════ */

.end { padding: var(--v-xl) 0 var(--v-l); }
.end__t { max-width: 16ch; margin-bottom: var(--v-s); }
.end p { color: var(--dim); max-width: 48ch; }
.end .acts { margin-top: var(--v-m); }

/* ══ Pied ═════════════════════════════════════════════════════════════════ */

.foot {
  position: relative; z-index: 2;
  border-top: 1px solid var(--line);
  padding: var(--v-m) 0 clamp(56px, 9vh, 84px);
  background: linear-gradient(180deg, rgba(8, 10, 14, .5), var(--ink) 60%);
}
.foot__grid { display: grid; gap: var(--v-s); }
@media (min-width: 820px) { .foot__grid { grid-template-columns: 2fr 1fr 1fr; gap: clamp(24px, 4vw, 70px); } }
.foot__line { color: var(--dim); font-size: var(--t-small); max-width: 36ch; margin-top: 14px; }
.foot__col h2 { font-family: var(--mono); font-size: var(--t-label); letter-spacing: .2em; text-transform: uppercase; color: var(--dimmer); margin: 0 0 16px; font-weight: 400; }
.foot__col ul { list-style: none; margin: 0; padding: 0; }
.foot__col li { margin-bottom: 10px; }
.foot__col a { color: var(--dim); font-size: var(--t-small); transition: color var(--fast) linear; }
.foot__col a:hover { color: var(--amber); }
.foot__base {
  margin: var(--v-m) 0 0; padding-top: 20px;
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 8px 26px;
  font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .16em; text-transform: uppercase; color: var(--dimmer);
}

/* ══ En-tête de page secondaire ═══════════════════════════════════════════ */

.phead {
  min-height: 76svh;
  display: grid; align-content: end;
  padding: var(--v-xl) 0 var(--v-l);
}
.phead .h1 { max-width: 16ch; margin: var(--v-s) 0 var(--v-s); }
.phead .lede { color: var(--dim); max-width: 46ch; }

/* ══ Tête de chapitre des pages secondaires ═══════════════════════════════
   Les pages de détail n'ont pas la colonne de chiffres de l'accueil : leur
   chapitre s'ouvre par un filet, un numéro ambre et le titre sur la même
   ligne de base. Même hiérarchie, moins d'appareil. */

.shead {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: clamp(12px, 2vw, 26px);
  margin: 0 0 var(--v-s);
  padding-top: var(--v-s);
  border-top: 1px solid var(--line);
  font-family: var(--display);
  font-size: var(--t-h2); line-height: 1.06;
  letter-spacing: -.010em; font-weight: 400;
}
.shead__num { font-family: var(--mono); font-size: var(--t-label); letter-spacing: .2em; color: var(--amber); }
.shead__more { margin-left: auto; font-size: var(--t-small); font-weight: 400; }

/* ══ Cartes d'installation ════════════════════════════════════════════════
   Trois colonnes, aucune boîte : des filets et de l'air. Celle qui
   correspond à l'appareil du visiteur s'allume par le haut. */

.cards { display: grid; gap: 0; }
@media (min-width: 880px) {
  .cards { grid-template-columns: repeat(3, 1fr); gap: 0 clamp(24px, 3vw, 56px); }
  .card { border-bottom: 1px solid var(--line); }
}
.card {
  position: relative;
  padding: clamp(24px, 4vh, 40px) 0;
  border-top: 1px solid var(--line);
}
.card:last-child { border-bottom: 1px solid var(--line); }
.card::before {
  content: "";
  position: absolute; left: 0; right: 0; top: -1px; height: 1px;
  background: var(--amber);
  transform: scaleX(0); transform-origin: left;
  transition: transform 900ms var(--ease);
}
.card.is-yours::before { transform: scaleX(1); }
.card__t { font-size: var(--t-h3); font-weight: 600; margin: 0 0 var(--v-xs); letter-spacing: -.015em; }

.steps { margin: 0; padding-left: 1.15em; color: var(--dim); font-size: var(--t-small); }
.steps li { margin-bottom: 9px; }
.steps li::marker { color: var(--dimmer); }

.apk { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); color: var(--dimmer); font-size: var(--t-small); }
.apk__tag {
  display: inline-block; margin-right: 10px;
  font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: .16em; text-transform: uppercase; color: var(--dimmer);
}

.shell--narrow { max-width: 900px; }

/* ══ Points numérotés ═════════════════════════════════════════════════════ */

.point {
  display: grid; grid-template-columns: 1fr; gap: 10px;
  padding: clamp(24px, 4vh, 40px) 0;
  border-top: 1px solid var(--line);
}
.point:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 760px) { .point { grid-template-columns: 3.5rem minmax(0, 1fr); gap: 0 clamp(20px, 3vw, 44px); } }
.point__num { font-family: var(--mono); font-size: var(--t-label); color: var(--amber); letter-spacing: .16em; }
.point__body .h3 { margin-bottom: var(--v-xs); }
.point__body p { color: var(--dim); }

/* ══ Le repli sans WebGL ══════════════════════════════════════════════════
   Sans WebGL et sans JS, ce schéma porte à lui seul l'idée de pistes
   empilées dans la profondeur. La classe `gl` est posée avant le premier
   rendu : il n'apparaît et ne disparaît jamais sous les yeux du visiteur. */

.mock { margin: var(--v-m) 0 0; perspective: 1000px; perspective-origin: 50% 42%; }
.gl .mock { display: none; }
.mock__label { margin: 0 0 14px; }
.mock__stage { transform: rotateX(17deg) rotateZ(-1deg); transform-style: preserve-3d; }
.mock__body { position: relative; }
.mock__lane { display: flex; gap: 4px; height: 40px; margin-bottom: 9px; transform-style: preserve-3d; }
.mock__lane:nth-child(1) { transform: translateZ(48px); }
.mock__lane:nth-child(3) { transform: translateZ(-48px); opacity: .72; }
.mock__lane:nth-child(4) { transform: translateZ(-96px); opacity: .46; }
.mock__tag {
  flex: 0 0 40px; display: grid; place-content: center;
  font-family: var(--mono); font-size: 10px; color: var(--dimmer);
  border: 1px solid var(--line);
}
.mock__clip {
  display: flex; align-items: center; padding: 0 12px;
  font-family: var(--mono); font-size: 11px; color: var(--dim);
  background: rgba(233, 237, 243, .04);
  border: 1px solid var(--line);
  overflow: hidden; white-space: nowrap;
}
.mock__clip--sel { border-color: var(--amber); color: var(--paper); background: var(--amber-a); }
.mock__clip--audio { background: repeating-linear-gradient(90deg, rgba(233, 237, 243, .10) 0 2px, transparent 2px 5px); }
.mock__gap { background: none; }
.mock__play { position: absolute; left: 43%; top: -6px; bottom: -6px; width: 1px; background: var(--amber); }

/* ══ Mouvement réduit ═════════════════════════════════════════════════════
   Personne ne doit subir ce site. Tout ce qui bouge s'arrête, et rien de ce
   qui est masqué ne reste caché. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .js [data-rise], .js [data-fade] { opacity: 1; transform: none; }
  .line > i { transform: none; }
  .rule { transform: none; }
  .cur, .cur-dot { display: none; }
}

/* ══ Impression ═══════════════════════════════════════════════════════════ */

@media print {
  #scene, .head, .hud, .loader, .cur, .cur-dot, .pin,
  body::after, [data-shade] > .shell::after, .seq::before { display: none !important; }
  body, html { background: #fff; color: #000; }
  .js body > * { opacity: 1 !important; }
  .loader { display: none !important; }
  .dim, .note, .kv dt, .foot__col a { color: #333; }
  .chap, .stage, .hero, .phead { min-height: 0; padding: 24px 0; }
  a { color: #000; text-decoration: underline; }
}
