@import url("fonts/fontshare.css");
@import url("fonts/satoshi.css");
@import url("fonts/gf.css");

/* ============================================================
   SITE V5 — « ÉTALONNAGE »
   Le site est un plan qu'on étalonne : il commence en log — plat,
   désaturé, noirs laiteux — et finit étalonné puis inversé en clair.
   La progression colorimétrique EST la progression de Thibault.

   Trois familles, trois rôles, jamais plus :
     Clash Display   la grosse — titres, dates, mots-objets
     Satoshi         la fine — corps ; son italique pour la voix intime
     JetBrains Mono  la métadonnée — repères, légendes, timecodes
   ============================================================ */

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

:root {
  --bg: 6 6 8;
  --ink: 150 155 164;
  --ink-hi: 214 218 224;
  --ink-lo: 140 145 153;
  --accent: 151 156 165;
  --rule: 255 255 255;
  --rule-a: 0.09;
  --grain: 0.05;

  --track-x: 64px;
  --gut: clamp(20px, 4.2vw, 76px);
  --stack: clamp(64px, 9vh, 130px);

  --f-disp: "Clash Display", "Arial Black", system-ui, sans-serif;
  --f-body: "Satoshi", "Helvetica Neue", system-ui, sans-serif;
  --f-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;

  --t-mono: clamp(10px, 0.72vw, 12px);
  --t-body: clamp(17px, 1.2vw, 20px);
  --t-lede: clamp(23px, 2.1vw, 34px);
  --t-h2: clamp(34px, 4.4vw, 72px);
  --t-huge: clamp(60px, 13.5vw, 220px);

  color-scheme: dark;
}

/* pas de scroll-behavior: smooth — sur 30 000 px le défilement natif
   lissé met plusieurs secondes ; le script s'en charge, durée bornée. */
html { scroll-behavior: auto; }

body {
  background: rgb(var(--bg));
  color: rgb(var(--ink));
  font-family: var(--f-body);
  font-weight: 300;
  font-size: var(--t-body);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* pas de transition de couleur : le changement d'acte est un CHANGEMENT
     D'ÉTAT, une bascule nette. Un fondu faisait passer encre et fond l'un
     par l'autre (1,09:1 à mi-course, mesuré) — voir REGLES.md. */
}
img, video, canvas { display: block; max-width: 100%; }
/* <picture> n'est qu'un choix de source : la boîte de mise en page reste l'img */
picture { display: contents; }
::selection { background: rgb(var(--accent)); color: rgb(var(--bg)); }

/* ============================================================
   L'AMORCE — courte. Elle attend que la vidéo du hero puisse jouer.
   ============================================================ */
.boot { position: fixed; inset: 0; z-index: 300; background: transparent; pointer-events: none; }
.boot::before, .boot::after { content: ""; position: absolute; left: 0; right: 0; height: 50.5%; background: rgb(var(--bg)); transition: transform 0.95s cubic-bezier(0.76, 0, 0.24, 1); }
.boot::before { top: 0; } .boot::after { bottom: 0; }
.boot.gone::before { transform: translateY(-101%); } .boot.gone::after { transform: translateY(101%); }
.boot.gone { visibility: hidden; transition: visibility 0s 1s; }
.boot-in { position: absolute; left: 8vw; right: 8vw; top: 50%; height: 1px; background: rgb(var(--accent)); transform: scaleX(0); transform-origin: 0 50%; animation: boot-trait 1.3s cubic-bezier(0.22, 1, 0.36, 1) forwards; z-index: 1; }
.boot.gone .boot-in { animation: boot-trait-fin 0.5s cubic-bezier(0.76, 0, 0.24, 1) forwards; }
#bootS { position: absolute; left: 0; bottom: 14px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.32em; text-transform: uppercase; color: rgb(var(--ink-lo)); white-space: nowrap; }
@keyframes boot-trait { to { transform: scaleX(1); } }
@keyframes boot-trait-fin { from { transform: scaleX(1); transform-origin: 100% 50%; } to { transform: scaleX(0); transform-origin: 100% 50%; } }
/* les textes de la page de garde montent quand l'écran s'ouvre (masque + translation, tout est posé au repos) */
@media (prefers-reduced-motion: no-preference) {
  html.in .hero-txt > * { animation: hero-monte 0.9s cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(0.55s + var(--hi, 0) * 0.11s); }
  .hero-txt > :nth-child(1) { --hi: 0; } .hero-txt > :nth-child(2) { --hi: 1; } .hero-txt > :nth-child(3) { --hi: 2; } .hero-txt > :nth-child(4) { --hi: 3; } .hero-txt > :nth-child(5) { --hi: 4; }
}
@keyframes hero-monte { from { transform: translateY(46px); clip-path: inset(0 0 100% 0); } to { transform: none; clip-path: inset(-0.2em 0 -0.4em 0); } }

/* ---- le fond : du verre sous la souris ---- */
.glass { position: fixed; inset: 0; z-index: 1; width: 100%; height: 100%; pointer-events: none; }

.grain {
  position: fixed; inset: -50%; pointer-events: none; z-index: 90;
  opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: no-preference) { .grain { animation: grainshift 0.9s steps(3) infinite; } }
@keyframes grainshift { 0%{transform:translate(0,0)} 33%{transform:translate(-2%,1.5%)} 66%{transform:translate(1.5%,-2%)} 100%{transform:translate(0,0)} }

/* ============================================================
   LE FILET — la ligne directrice
   Une seule ligne, à gauche, sur toute la hauteur. Un segment
   lumineux y avance avec le visiteur : il montre où on en est et
   prend la couleur de l'acte. Pas de mots. Elle mène, c'est tout.
   ============================================================ */
.filet {
  position: fixed; left: var(--track-x); top: 0; bottom: 0;
  width: 1px; z-index: 40; pointer-events: none;
  background: rgb(var(--rule) / calc(var(--rule-a) * 1.5));
}
.filet-glow {
  position: absolute; left: -1px; width: 3px;
  top: 0; height: 14vh;
  transform: translateY(var(--fp, 0px)) translateY(-50%); will-change: transform;
  background: linear-gradient(rgb(var(--accent) / 0), rgb(var(--accent)) 50%, rgb(var(--accent) / 0));
  filter: drop-shadow(0 0 6px rgb(var(--accent) / 0.9)) drop-shadow(0 0 18px rgb(var(--accent) / 0.5));
}
.filet-head {
  position: absolute; left: -4px; width: 9px; height: 9px; border-radius: 50%;
  top: 0; transform: translateY(var(--fp, 0px)) translateY(-50%) scale(var(--fs, 1)); will-change: transform;
  background: rgb(var(--accent));
  box-shadow: 0 0 12px 2px rgb(var(--accent) / 0.6);
}
@media (max-width: 860px) { :root { --track-x: 22px; } }

/* ============================================================
   BARRE
   ============================================================ */
.bar {
  position: fixed; inset: 0 0 auto 0; z-index: 80;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 18px var(--gut);
  background: rgb(var(--bg) / var(--bar-a, 0));
  border-bottom: 1px solid rgb(var(--rule) / calc(var(--rule-a) * var(--bar-a, 0)));
  backdrop-filter: blur(calc(var(--bar-a, 0) * 14px));
}
.bar a { color: inherit; text-decoration: none; }
.bar-mark { font-family: var(--f-disp); font-weight: 600; font-size: 13px; letter-spacing: 0.16em; text-transform: uppercase; color: rgb(var(--ink-hi)); padding: 12px 0; }
.bar-nav { display: flex; align-items: center; gap: clamp(14px, 2vw, 34px); }
/* liens en ligne : le padding vertical n'affecte pas la ligne mais compte
   dans la zone cliquable — 16 px de texte + 28 px = 44 px */
.bar-nav a { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.12em; text-transform: uppercase; color: rgb(var(--ink-lo)); transition: color 0.25s ease; padding: 14px 6px; margin: 0 -6px; }
.bar-nav a:hover { color: rgb(var(--ink-hi)); }
.dispo { display: inline-flex; align-items: center; gap: 8px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.08em; color: rgb(var(--ink-lo)); }
.dispo i { width: 5px; height: 5px; border-radius: 50%; background: rgb(var(--accent)); }
@media (prefers-reduced-motion: no-preference) { .dispo i { animation: ping 2.6s ease-out infinite; } }
@keyframes ping { 0%{box-shadow:0 0 0 0 rgb(var(--accent)/0.45)} 70%{box-shadow:0 0 0 7px rgb(var(--accent)/0)} 100%{box-shadow:0 0 0 0 rgb(var(--accent)/0)} }
@media (max-width: 720px) { .dispo { display: none; } }

.skip { position: fixed; left: 8px; top: 8px; z-index: 200; transform: translateY(-160%); background: rgb(var(--accent)); color: rgb(var(--bg)); padding: 10px 16px; text-decoration: none; font-family: var(--f-mono); font-size: var(--t-mono); transition: transform 0.2s ease; }
.skip:focus-visible { transform: none; }
:where(a, button, video, [tabindex]):focus-visible { outline: 2px solid rgb(var(--accent)); outline-offset: 3px; }

/* ============================================================
   CHAPITRES
   ============================================================ */
main { position: relative; z-index: 10; }
.ch { position: relative; padding: var(--stack) var(--gut) var(--stack) calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); }
@media (max-width: 860px) { .ch { padding-left: calc(var(--track-x) + 24px); padding-right: 22px; } }

.mark {
  display: flex; align-items: baseline; gap: 18px;
  font-family: var(--f-mono); font-size: var(--t-mono);
  letter-spacing: 0.22em; text-transform: uppercase; color: rgb(var(--ink-lo));
  padding-bottom: 14px; border-bottom: 1px solid rgb(var(--rule) / var(--rule-a));
  margin-bottom: clamp(36px, 6vh, 80px);
}
.mark b { color: rgb(var(--accent)); font-weight: 500; }

/* le passage d'acte : une ligne, en flux, jamais un pin */

h1, h2 { font-family: var(--f-disp); font-weight: 600; line-height: 0.96; letter-spacing: -0.025em; color: rgb(var(--ink-hi)); text-wrap: balance; }
h2 { font-size: var(--t-h2); max-width: 18ch; }

.lede { font-family: var(--f-disp); font-weight: 500; font-size: var(--t-lede); line-height: 1.28; letter-spacing: -0.01em; color: rgb(var(--ink-hi)); max-width: 28ch; text-wrap: pretty; }
/* 42ch de Satoshi ≈ 66 signes par ligne (56ch en faisaient 89, mesuré) ; le récit est en encre haute,
   la voix (italique) en encre haute aussi mais légère, les légendes en encre basse : trois niveaux, pas un gris */
.copy { max-width: 42ch; text-wrap: pretty; color: rgb(var(--ink-hi)); }
.copy.cap-copy { max-width: 46ch; margin-top: 18px; color: rgb(var(--ink)); }
.copy + .copy { margin-top: 1.1em; }

/* la voix : le recul, l'intime. Satoshi italique fin, un peu plus grand. */
.voice { font-style: italic; font-weight: 300; font-size: clamp(18px, 1.4vw, 23px); line-height: 1.5; color: rgb(var(--ink-hi)); max-width: 46ch; }
.em { font-style: italic; font-weight: 300; color: rgb(var(--ink-hi)); }
.lede .em { font-family: var(--f-body); font-size: 0.98em; }
/* le fait : couleur d'acte, un cran de graisse, rien d'autre */
.hi { color: rgb(var(--accent)); font-weight: 500; }
/* le mot-objet */
.key { font-family: var(--f-disp); font-weight: 700; font-size: 1.28em; line-height: 0.95; letter-spacing: -0.02em; color: rgb(var(--ink-hi)); text-transform: uppercase; }
.it { font-style: italic; font-weight: 300; font-size: 1.06em; color: rgb(var(--ink-hi)); }
.gras { font-weight: 700; color: rgb(var(--ink-hi)); }

.cap { margin-top: 12px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.06em; color: rgb(var(--ink-lo)); }
.lab { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.26em; text-transform: uppercase; color: rgb(var(--ink-lo)); margin-bottom: 14px; }
.cta { display: inline-flex; align-items: center; gap: 10px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--ink-hi)); text-decoration: none; padding-bottom: 6px; border-bottom: 1px solid rgb(var(--accent) / 0.5); transition: border-color 0.25s, color 0.25s, gap 0.25s; }
.cta:hover { color: rgb(var(--accent)); border-color: rgb(var(--accent)); gap: 16px; }
/* zone tactile de 44 px sans bouger la mise en page : le padding vertical est
   annulé par des marges négatives, et le soulignement, qui suivait la bordure,
   passe sur un pseudo-élément pour rester à 6 px sous le texte */
.cta { position: relative; padding-top: 12px; padding-bottom: 16px; margin-top: -12px; margin-bottom: -10px; border-bottom: 0; }
.cta::after { content: ""; position: absolute; left: 0; right: 0; bottom: 10px; height: 1px; background: rgb(var(--accent) / 0.5); transition: background-color 0.25s; }
.cta:hover::after { background: rgb(var(--accent)); }


/* ============================================================
   LA GRILLE
   ============================================================ */
.stackset { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(14px, 1.8vw, 30px); row-gap: clamp(26px, 4.5vh, 76px); align-items: start; }
.stackset > * { grid-column: 1 / -1; }
.p-left { grid-column: 1 / 7; } .p-right { grid-column: 7 / 13; } .p-narrow { grid-column: 1 / 6; }
.p-inset { grid-column: 3 / 10; } .p-offset { grid-column: 5 / 13; } .p-wide { grid-column: 1 / 11; }
.p-widest { grid-column: 1 / 13; } .p-center { grid-column: 3 / 11; } .p-tail { grid-column: 8 / 13; }
.p-bleed { grid-column: 1 / 13; margin-right: calc(var(--gut) * -1); }
@media (max-width: 1000px) { .p-left,.p-right,.p-narrow,.p-inset,.p-offset,.p-wide,.p-center,.p-tail,.p-bleed { grid-column: 1 / -1; } .p-bleed { margin-right: 0; } }
.row { display: flex; flex-wrap: wrap; gap: clamp(18px, 3vw, 48px); align-items: flex-start; }

/* ============================================================
   MÉDIAS
   ============================================================ */
.clip { position: relative; }
.clip video, .clip img { width: 100%; height: 100%; background: rgb(var(--bg)); }
.clip img { object-fit: contain; }
.clip video, .clip.photo img { object-fit: cover; }
.clip::after { content: ""; position: absolute; inset: 0; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); pointer-events: none; }
.clip.bare::after { content: none; }
.clip .tag { position: absolute; left: 0; bottom: -1px; transform: translateY(100%); padding-top: 10px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.06em; color: rgb(var(--ink-lo)); }
.reveal { clip-path: inset(0 0 100% 0); }
[data-clip] { transform: translate3d(0, var(--py, 0px), 0) scale(var(--ps, 1)); will-change: transform; }

/* ============================================================
   00 · HERO — la vidéo dort dans le noir, la souris la réveille
   ============================================================ */
#hero { position: relative; height: 100vh; min-height: 560px; overflow: hidden; }
.hero-cv { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; pointer-events: none; }
html.touch .hero-video { opacity: 0.55; }
html.touch .hero-cv { display: none; }
/* le haut est voilé à 94 % sous la barre (transparente en haut de page par
   conception) : son texte garde 4,5:1 même quand la souris révèle la mer */
.hero-veil { position: absolute; inset: 0; background: linear-gradient(rgb(var(--bg) / 0.94), rgb(var(--bg) / 0.6) 90px, transparent 38%, transparent 60%, rgb(var(--bg) / 0.9)); pointer-events: none; }
.hero-txt { position: absolute; left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); right: var(--gut); bottom: clamp(56px, 11vh, 120px); }
#hero h1 { font-size: var(--t-huge); font-weight: 700; letter-spacing: -0.035em; line-height: 0.88; }
.hero-role { margin-top: clamp(18px, 3vh, 30px); font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.22em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
.hero-line { margin-top: 18px; max-width: 36ch; color: rgb(var(--ink)); }
.hero-acts { margin-top: clamp(24px, 4vh, 40px); display: flex; flex-wrap: wrap; gap: 28px; }
.hero-cred { position: absolute; right: var(--gut); bottom: clamp(22px, 4vh, 34px); font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.16em; text-transform: uppercase; color: rgb(var(--ink-lo)); text-align: right; }
.hero-hint { position: absolute; right: var(--gut); top: 50%; transform: translateY(-50%) rotate(90deg); transform-origin: 100% 50%; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.3em; text-transform: uppercase; color: rgb(var(--ink-lo)); white-space: nowrap; transition: opacity 0.5s; }
@media (max-width: 860px) { .hero-hint { display: none; } }

/* ============================================================
   SCÈNES 3D — une section haute, une toile collée, la vidéo dessous
   ============================================================ */
.scene { position: relative; height: 320vh; }
.scene-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; background: rgb(var(--bg)); }
.scene-pin canvas { position: absolute; inset: 0; z-index: 1; width: 100% !important; height: 100% !important; }
/* la légende, les mots, la vidéo plein cadre sont au-dessus de la toile 3D (elle est ajoutée après eux dans le DOM) */
.scene-cap, .mots, .scene-full { z-index: 2; }
.scene-src { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; pointer-events: none; }
.scene.no3d .scene-src { opacity: 1; pointer-events: auto; }
.scene.no3d { height: auto; }
.scene.no3d .scene-pin { position: static; height: auto; aspect-ratio: 16/9; }
.scene-cap { position: absolute; left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); bottom: clamp(28px, 6vh, 64px); right: var(--gut); display: grid; gap: 8px; pointer-events: none; }
.scene-cap .t { font-family: var(--f-disp); font-weight: 600; font-size: clamp(22px, 2.6vw, 42px); color: rgb(214 218 224); letter-spacing: -0.02em; }
.scene-cap .c { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(150 155 164); }
.scene-full { position: absolute; inset: 0; opacity: var(--fo, 0); pointer-events: none; transition: opacity 0.4s; background: #000; }
.scene-full.on { pointer-events: auto; }
.scene-full.regie-clip { z-index: 2; pointer-events: none; }
.scene-full:not(.regie-clip) { z-index: 3; }
.scene-full video { width: 100%; height: 100%; object-fit: cover; }
.scene-full .cap { position: absolute; left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); bottom: 26px; margin: 0; color: rgb(214 218 224 / 0.8); }
@media (max-width: 860px) { .scene { height: auto; } .scene-pin { position: static; height: auto; aspect-ratio: 16/9; } .scene-cap { position: static; padding: 14px 0 0; } }

/* ============================================================
   01 · L'ARCHIVE QU'ON DÉROULE
   ============================================================ */
.unroll { overflow: hidden; }
.unroll img { clip-path: inset(0 var(--ur, 100%) 0 0); }
.unroll-edge { position: absolute; top: 0; bottom: 0; left: calc(100% - var(--ur, 100%)); width: 1px; background: rgb(var(--accent)); opacity: var(--ure, 0); box-shadow: 0 0 18px 1px rgb(var(--accent) / 0.45); }

/* ============================================================
   02 · LE MUR — le seul changement de régime
   ============================================================ */
.wall-stage { position: relative; height: 240vh; }
.wall-pin { position: sticky; top: 0; height: 100vh; display: flex; align-items: center; overflow: hidden; perspective: 1400px; perspective-origin: 50% 50%; }
.wall-track { display: flex; align-items: center; gap: clamp(30px, 5vw, 96px); padding-left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); will-change: transform; transform: translate3d(var(--wx, 0px), 0, 0) rotateY(var(--look, 0deg)); transform-style: preserve-3d; transform-origin: calc(50vw - var(--wx, 0px)) 50%; }
.wall-item { flex: 0 0 auto; width: var(--w, 26vw); transform: translate3d(0, var(--y, 0), var(--z, 0px)); position: relative; perspective: 1100px; }
.wall-item img { width: 100%; height: auto; display: block; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); transform: rotateY(var(--tx, 0deg)) rotateX(var(--ty, 0deg)); transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.wall-item:hover img { transition-duration: 0.12s; }
/* les cartels — nom, une ligne, année : comme au musée, discret */
.cartel { display: grid; gap: 3px; padding-top: 12px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.08em; color: rgb(var(--ink-lo)); text-align: left; }
.cartel b { font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--ink)); }
.cartel i { font-style: normal; }
.wall-end { flex: 0 0 auto; width: min(46ch, 76vw); }
.wall-prog { position: absolute; left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); bottom: 8vh; width: min(320px, 40vw); height: 1px; background: rgb(var(--rule) / var(--rule-a)); display: block; }
.wall-prog i { display: block; height: 100%; width: var(--wp, 0%); background: rgb(var(--accent)); }
@media (max-width: 860px) {
  .wall-stage { height: auto; } .wall-pin { position: static; height: auto; overflow: visible; padding: 0 22px; }
  .wall-track { flex-direction: column; align-items: stretch; transform: none !important; padding-left: 0; gap: 40px; }
  .wall-item { width: 100% !important; transform: none !important; } .wall-prog { display: none; }
}

/* ============================================================
   03 · LA DATE
   ============================================================ */
.mono-date { font-family: var(--f-disp); font-weight: 700; font-size: var(--t-huge); line-height: 0.84; letter-spacing: -0.04em; color: rgb(var(--ink-hi)); }
.mono-date span { display: block; }
.mono-date .y { color: rgb(var(--accent)); font-variant-numeric: tabular-nums; }

/* ============================================================
   04 · TIMELINE BALAYÉE + MANIFESTE
   ============================================================ */
.scrubbed { overflow: hidden; }
.scrub-head { position: absolute; top: 0; bottom: 0; left: var(--sh, 0%); width: 2px; background: rgb(var(--accent)); opacity: var(--sho, 0); box-shadow: 0 0 22px 2px rgb(var(--accent) / 0.5); pointer-events: none; }
.scrub-head::before { content: ""; position: absolute; top: 0; left: -4px; width: 10px; height: 10px; background: rgb(var(--accent)); clip-path: polygon(0 0, 100% 0, 50% 100%); }
.scrubbed img { -webkit-mask-image: linear-gradient(to right, #000 calc(var(--sh, 0%) - 1px), rgb(0 0 0 / 0.62) var(--sh, 0%)); mask-image: linear-gradient(to right, #000 calc(var(--sh, 0%) - 1px), rgb(0 0 0 / 0.62) var(--sh, 0%)); }

.manifest { font-family: var(--f-disp); font-weight: 600; font-size: clamp(26px, 3.9vw, 66px); line-height: 1.0; letter-spacing: -0.03em; color: rgb(var(--ink-hi)); }
@media (min-width: 861px) { .manifest.p-widest { grid-column: 6 / -1; } }
.manifest span { display: block; }
.manifest .em { font-family: var(--f-body); font-weight: 300; font-size: 0.92em; padding-left: 0.06em; }

/* ============================================================
   05 · ÉCOSYSTÈME
   ============================================================ */
#c05 { position: relative; }
.branch { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 5; }
.branch path { fill: none; stroke: rgb(var(--accent)); stroke-width: 1; stroke-linecap: round; opacity: 0.45; stroke-dasharray: var(--len, 1000); stroke-dashoffset: var(--off, 1000); }
.branch circle { fill: rgb(var(--accent)); opacity: var(--dot, 0); }

/* le feed : les vrais posts, dans un téléphone qui défile au scroll */
.feed { width: min(300px, 100%); aspect-ratio: 9 / 18.5; border-radius: 30px; border: 1px solid rgb(var(--rule) / 0.28); background: #000; padding: 10px; position: relative; flex: 0 0 auto; }
.social .feed { position: absolute; left: 50%; top: 50%; width: calc(var(--pw) + 20px); background: transparent; box-shadow: 0 0 0 1px rgb(0 0 0 / 0.6) inset, 0 30px 60px rgb(0 0 0 / 0.45); transform: translate(-50%, -50%); z-index: 7; pointer-events: none; }
.feed-in { width: 100%; height: 100%; border-radius: 22px; overflow: hidden; background: #000; }
.feed-scroll { display: grid; gap: 6px; transform: translateY(var(--fy, 0px)); will-change: transform; }
.feed-scroll img { width: 100%; height: auto; display: block; }
.feed-notch { position: absolute; left: 50%; top: 10px; width: 34%; height: 18px; margin-left: -17%; background: #000; border-radius: 0 0 12px 12px; z-index: 2; }

/* un seul lecteur vertical, et trois formats qu'on choisit */
.viewer { display: grid; grid-template-columns: minmax(200px, 300px) 1fr; gap: clamp(20px, 3vw, 48px); align-items: start; }
.viewer .clip { aspect-ratio: 9 / 16; }
.viewer-list { display: grid; gap: 4px; }
.viewer-list button { all: unset; cursor: pointer; display: grid; grid-template-columns: auto 1fr; gap: 16px; align-items: baseline; padding: 14px 0; border-top: 1px solid rgb(var(--rule) / var(--rule-a)); font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--ink-lo)); transition: color 0.25s; }
.viewer-list button:last-child { border-bottom: 1px solid rgb(var(--rule) / var(--rule-a)); }
.viewer-list button b { font-family: var(--f-disp); font-weight: 600; font-size: clamp(18px, 1.6vw, 26px); letter-spacing: -0.01em; text-transform: none; color: rgb(var(--ink)); transition: color 0.25s; }
.viewer-list button.on, .viewer-list button:hover { color: rgb(var(--accent)); }
.viewer-list button.on b { color: rgb(var(--ink-hi)); }
.viewer-list button:focus-visible { outline: 2px solid rgb(var(--accent)); outline-offset: 4px; }
@media (max-width: 720px) { .viewer { grid-template-columns: 1fr; } }

/* les drapeaux : détourés, petits, ils se plantent */
.flags { display: flex; gap: clamp(10px, 1.6vw, 26px); align-items: flex-end; }
.flag { flex: 1 1 0; min-width: 0; transform-origin: 50% 100%; transform: rotate(var(--fr, 0deg)) translateY(var(--fy, 0)); will-change: transform; transition: transform 0.9s cubic-bezier(0.34, 1.4, 0.64, 1); }
.flag:nth-child(2) { transition-delay: 0.1s; } .flag:nth-child(3) { transition-delay: 0.2s; } .flag:nth-child(4) { transition-delay: 0.3s; }
.flag img { width: 100%; height: auto; }
.flag .tag { position: static; transform: none; display: block; padding-top: 8px; }

/* la tente : ses trois faces, comme un dépliant qui s'ouvre */
.tent { display: grid; grid-template-columns: 1fr 2.15fr 1fr; gap: 6px; align-items: center; perspective: 1400px; }
.tent figure { margin: 0; transform-origin: 100% 50%; transform: rotateY(var(--tl, 0deg)); transition: transform 1s cubic-bezier(0.22, 1, 0.36, 1) 0.15s; }
.tent figure:last-child { transform-origin: 0% 50%; transform: rotateY(var(--tr, 0deg)); }
.tent img { width: 100%; height: auto; display: block; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); }

/* ---- le livre : la plaquette se feuillette ---- */
.book { position: relative; width: min(920px, 100%); aspect-ratio: 2 / 1.414; perspective: 2400px; }
.book-page { position: absolute; top: 0; left: 50%; width: 50%; height: 100%; transform-origin: 0% 50%; transform-style: preserve-3d; transform: rotateY(var(--r, 0deg)); will-change: transform; }
.book-face { position: absolute; inset: 0; backface-visibility: hidden; background: #fff; overflow: hidden; border: 1px solid rgb(0 0 0 / 0.08); }
.book-face img { width: 100%; height: 100%; object-fit: contain; background: #fff; }
.book-face.back { transform: rotateY(180deg); }
.book-face::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(90deg, rgb(0 0 0 / 0.16), transparent 14%); }
.book-face.back::after { background: linear-gradient(-90deg, rgb(0 0 0 / 0.16), transparent 14%); }
.book-spine { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: rgb(0 0 0 / 0.35); z-index: 50; }
.book-cover { position: absolute; top: 0; left: 0; width: 50%; height: 100%; background: #f4f2ee linear-gradient(90deg, rgb(0 0 0 / 0.05), transparent 12%, transparent 88%, rgb(0 0 0 / 0.14)); border: 1px solid rgb(0 0 0 / 0.08); }
.book-n { position: absolute; right: 0; bottom: -28px; font-family: var(--f-mono); font-size: var(--t-mono); color: rgb(var(--ink-lo)); }
.book-hint { position: absolute; left: 0; bottom: -28px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.16em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
@media (max-width: 860px) { .book { aspect-ratio: 1 / 1.414; } .book-page, .book-cover { width: 100%; left: 0; } .book-spine { display: none; } }

/* ---- le châssis qui démarre ---- */
.browser { border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 2)); background: rgb(var(--bg)); clip-path: inset(0 0 calc(100% - var(--bo, 0%)) 0); }
.browser-bar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid rgb(var(--rule) / var(--rule-a)); }
.browser-bar em { display: flex; gap: 6px; }
.browser-bar em i { width: 8px; height: 8px; border-radius: 50%; background: rgb(var(--rule) / 0.24); }
.browser-url { flex: 1; font-family: var(--f-mono); font-size: var(--t-mono); color: rgb(var(--ink-lo)); background: rgb(var(--rule) / 0.06); padding: 5px 12px; white-space: nowrap; overflow: hidden; }
.browser-url::after { content: "▍"; color: rgb(var(--accent)); opacity: var(--bc, 1); }
.browser-live { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--accent)); }
.browser-shot { display: block; background: #fff; }
.browser-shot img { display: block; width: 100%; height: auto; }
.browser-shot:hover img { filter: brightness(0.96); }

/* ============================================================
   06 · LE RACCORD PSG
   ============================================================ */
.psg-stage { position: relative; height: 200vh; }
#psgClip { position: sticky; top: 0; height: 100vh; display: flex; align-items: center; justify-content: center; overflow: hidden; }
#psgStage { position: relative; }
/* la boîte est à sa taille finale (toute la hauteur, 9/16) et seule l'échelle change :
   petite dans l'espace, puis elle avance, puis elle déborde le cadre et le couvre */
.psg-boite { position: relative; height: 100vh; aspect-ratio: 9 / 16; flex: 0 0 auto; transform: scale(var(--pz, 0.4)); transform-origin: 50% 50%; will-change: transform; }
.psg-boite video { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: calc(var(--psg-chrome, 1) * 14px); box-shadow: 0 0 0 calc(var(--psg-chrome, 1) * 2px) rgb(var(--rule) / calc(var(--psg-chrome, 1) * 0.22)), 0 calc(var(--psg-chrome, 1) * 30px) calc(var(--psg-chrome, 1) * 60px) rgb(0 0 0 / calc(var(--psg-chrome, 1) * 0.5)); }
/* le cadre que la Ligne dessine : un tracé qui s'écrit puis se retire */
.psg-cadre { position: absolute; inset: -14px; width: calc(100% + 28px); height: calc(100% + 28px); overflow: visible; pointer-events: none; }
.psg-cadre path { fill: none; stroke: rgb(var(--accent)); stroke-width: 2.5; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-dasharray: 1000; stroke-dashoffset: var(--psg-trace, 1000); filter: drop-shadow(0 0 6px rgb(var(--accent) / 0.8)); }
@media (prefers-reduced-motion: reduce) { .psg-boite { transform: none; } .psg-cadre path { stroke-dashoffset: 0; } }
/* la légende du PSG finit posée sur la vidéo plein cadre : un cartel sombre, lisible sur n'importe quelle image */
#psgCap { position: absolute; left: 50%; bottom: clamp(28px, 6vh, 70px); transform: translateX(-50%); max-width: calc(100% - 2 * var(--gut)); padding: 9px 14px; background: rgb(0 0 0 / 0.86); color: rgb(var(--ink-hi)); text-align: center; z-index: 2; }

/* ============================================================
   07 · UNDERGROUND — la planche, puis l'évolution
   ============================================================ */
.status { border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.8)); padding: clamp(16px, 2.2vw, 26px); max-width: 62ch; }
.status .k { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.2em; text-transform: uppercase; color: rgb(var(--accent)); display: block; margin-bottom: 10px; }

.planche { display: flex; gap: 12px; align-items: flex-start; height: min(76vh, 760px); perspective: 1600px; }
.case { position: relative; border: 2px solid rgb(var(--ink-hi) / 0.82); background: rgb(var(--bg)); overflow: hidden; }
.case img { width: 100%; height: 100%; object-fit: cover; display: block; }
.case-cover { flex: 0 0 auto; height: 100%; aspect-ratio: 1 / 1.414; transform: none; } /* la couverture reste en place (retours 10) ; la planche tient dans l'écran (retours 12) */
.case-sora { flex: 0 0 auto; height: 84%; aspect-ratio: 2 / 3; align-self: flex-end; }
.case-terrain { flex: 1 1 auto; min-width: 0; aspect-ratio: 3 / 2; align-self: flex-start; }
.case-cover::after { content: none; }
.case-k { position: absolute; right: 0; top: 0; z-index: 2; font-family: var(--f-mono); font-size: var(--t-mono); color: rgb(var(--bg)); background: rgb(var(--ink-hi)); padding: 3px 8px; letter-spacing: 0.1em; }
.case .tag { position: absolute; left: 0; right: 0; bottom: 0; transform: none; padding: 26px 12px 10px; background: linear-gradient(transparent, rgb(var(--bg) / 0.92)); color: rgb(var(--ink-hi)); }
@media (max-width: 860px) { .planche { display: grid; grid-template-columns: 1fr; height: auto; } .case-cover, .case-sora, .case-terrain { height: auto; } .case-cover { transform: none !important; } }

/* HINODE : un seul maillot qui évolue, et sa frise */
.evolve-stage { position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
.evolve-stage::before { content: ""; position: absolute; left: 50%; bottom: -10%; width: 90%; height: 120%; transform: translateX(-50%) scale(var(--sun, 0.4)); transform-origin: 50% 100%; background: radial-gradient(55% 50% at 50% 100%, rgb(var(--accent) / 0.55), rgb(var(--accent) / 0.18) 40%, transparent 72%); opacity: var(--sun-o, 0); filter: blur(30px); pointer-events: none; }
.evolve-stage img { position: absolute; inset: 6%; width: 88%; height: 88%; object-fit: contain; opacity: var(--o, 0); transform: scale(var(--s, 1)); will-change: opacity, transform; }
.evolve-k { position: absolute; left: 0; top: 0; font-family: var(--f-disp); font-weight: 700; font-size: clamp(60px, 12vw, 200px); line-height: 0.8; letter-spacing: -0.04em; color: rgb(var(--ink-hi) / 0.12); pointer-events: none; }
.frise { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 2vw, 32px); margin-top: clamp(24px, 4vh, 48px); border-top: 1px solid rgb(var(--rule) / var(--rule-a)); padding-top: 18px; }
.frise button { all: unset; cursor: pointer; display: grid; gap: 8px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--ink-lo)); transition: color 0.3s; }
.frise button img { width: 100%; height: auto; opacity: 0.55; transition: opacity 0.3s; }
.frise button.on, .frise button:hover { color: rgb(var(--accent)); }
.frise button.on img { opacity: 1; }
.frise button:focus-visible { outline: 2px solid rgb(var(--accent)); outline-offset: 4px; }

/* ============================================================
   08 · LE PLEIN CHAMP
   ============================================================ */
/* le takeover occupe sa taille finale dans le flux dès le départ et ne grandit
   qu'en transform : aucun décalage de mise en page pendant le défilement */
.takeover { width: 100%; margin-right: calc(var(--gut) * -1); transform: scale(var(--ts, 1)); transform-origin: calc(50% - var(--gut) / 2) 50%; will-change: transform; }

/* ============================================================
   PROFIL
   ============================================================ */
.facts { display: grid; gap: 12px; }
.facts li { list-style: none; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.08em; color: rgb(var(--ink-lo)); padding-left: 18px; position: relative; }
.facts li::before { content: ""; position: absolute; left: 0; top: 0.62em; width: 8px; height: 1px; background: rgb(var(--accent)); }
.quote { font-family: var(--f-body); font-style: italic; font-weight: 300; font-size: clamp(22px, 3vw, 46px); line-height: 1.22; color: rgb(var(--ink-hi)); max-width: 22ch; letter-spacing: -0.01em; }
.rights { margin-top: 18px; display: inline-block; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--accent)); border: 1px solid rgb(var(--accent) / 0.4); padding: 7px 12px; }

/* ============================================================
   LE GÉNÉRIQUE — un film finit ainsi
   ============================================================ */
.credits { position: relative; height: 260vh; }
.credits-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; display: grid; place-items: center; }
.credits-roll { text-align: center; display: grid; gap: clamp(22px, 4vh, 44px); transform: translateY(var(--cr, 60vh)); will-change: transform; padding: 0 22px; }
.credits-roll .k { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.36em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
.credits-roll .n { font-family: var(--f-disp); font-weight: 700; font-size: clamp(34px, 5vw, 84px); line-height: 0.95; letter-spacing: -0.03em; color: rgb(var(--ink-hi)); }
.credits-roll .m { font-family: var(--f-body); font-weight: 300; font-size: clamp(16px, 1.3vw, 21px); color: rgb(var(--ink)); }
.credits-roll .big { font-family: var(--f-disp); font-weight: 700; font-size: clamp(24px, 4vw, 68px); letter-spacing: -0.03em; color: rgb(var(--ink-hi)); text-decoration: none; border-bottom: 2px solid rgb(var(--accent) / 0.6); transition: color 0.25s, border-color 0.25s; word-break: break-all; }
.credits-roll .big:hover { color: rgb(var(--accent)); border-color: rgb(var(--accent)); }
.credits-roll .big { padding-top: 6px; }
.credits-roll .links { display: flex; justify-content: center; gap: clamp(20px, 3vw, 44px); flex-wrap: wrap; }
.credits-end { position: absolute; left: 0; right: 0; bottom: clamp(24px, 5vh, 48px); text-align: center; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.24em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
@media (max-width: 860px) { .credits { height: auto; padding: var(--stack) 0; } .credits-pin { position: static; height: auto; } .credits-roll { transform: none !important; } .credits-end { position: static; margin-top: 40px; opacity: 1; } }

/* ============================================================
   LE CURSEUR
   ============================================================ */
.cur { position: fixed; left: 0; top: 0; z-index: 200; width: 34px; height: 34px; margin: -17px 0 0 -17px; border: 1px solid rgb(var(--accent) / 0.7); border-radius: 50%; pointer-events: none; transform: translate3d(var(--curx, -100px), var(--cury, -100px), 0) scale(var(--curs, 1)); transition: opacity 0.3s, background-color 0.3s, border-color 0.3s; opacity: 0; display: grid; place-items: center; font-family: var(--f-mono); font-size: 8px; letter-spacing: 0.14em; text-transform: uppercase; color: rgb(var(--bg)); }
.cur.on { opacity: 1; } .cur.hot { background: rgb(var(--accent)); border-color: rgb(var(--accent)); }
.cur i { opacity: 0; transition: opacity 0.2s; font-style: normal; } .cur.hot i { opacity: 1; }
@media (hover: none), (max-width: 860px) { .cur { display: none; } }

/* ============================================================
   L'ENTRÉE
   ============================================================ */
/* l'entrée est une animation, jamais un état : sans elle, tout est visible */
html.js.in .bar, html.js.in .filet { animation: entree 0.85s cubic-bezier(0.22, 1, 0.36, 1) both; }
/* main entre en opacité seule : un translateY sur main déplaçait tout le
   document de 10 px pendant l'animation (ancres décalées, mesuré) */
html.js.in main { animation: entree-main 0.85s cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes entree { from { opacity: 0; transform: translateY(10px); } }
@keyframes entree-main { from { opacity: 0; } }

/* ============================================================
   MOUVEMENT RÉDUIT — le sens ne dépend jamais du mouvement
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html.js.in main, html.js.in .bar, html.js.in .filet { animation: none; }
  .reveal { clip-path: none !important; }
  .grain { animation: none; }
  .unroll img { clip-path: none !important; }
  .scrubbed img { -webkit-mask-image: none !important; mask-image: none !important; }
  .case-cover { transform: none !important; }
  .takeover { transform: none !important; }
  .wall-item img { transform: none !important; }
  .cur { display: none; }
  .browser { clip-path: none !important; }
  .credits { height: auto; } .credits-pin { position: static; height: auto; } .credits-roll { transform: none !important; }
  .evolve-stage img { opacity: 1 !important; position: static; width: 33%; display: inline-block; }
  .hero-video { opacity: 0.55; } .hero-cv { display: none; }
  .acte { height: auto; } .acte-pin { position: static; height: auto; padding-top: var(--stack); padding-bottom: var(--stack); }
}

/* le livre a besoin d'une plage de scroll pour se feuilleter :
   il reste collé pendant qu'on tourne ses sept feuillets. */
.book-stage { position: relative; height: 240vh; }
.book-pin { position: sticky; top: 10vh; }
@media (max-width: 860px) { .book-stage { height: auto; } .book-pin { position: static; } }

/* ============================================================
   STABILITÉ DE MISE EN PAGE
   Toute image chargée en différé réserve sa place AVANT d'arriver.
   Sans cela, chaque chargement pousse ce qui suit de plusieurs
   centaines de pixels et fausse toutes les mesures du moteur — le
   livre se feuilletait tout seul à cause de ça.
   ============================================================ */
.flag img { aspect-ratio: 615 / 1800; object-fit: contain; }
.tent figure:first-child img, .tent figure:last-child img { aspect-ratio: 1000 / 744; object-fit: cover; }
.tent figure:nth-child(2) img { aspect-ratio: 1600 / 1190; object-fit: cover; }
.feed-scroll img { aspect-ratio: 4 / 5; object-fit: cover; }
.frise button img { aspect-ratio: 3 / 2; object-fit: contain; }
.unroll img { aspect-ratio: 1358 / 202; }
.wall-item img { aspect-ratio: 1 / 1; object-fit: contain; }

/* les supports restent un bloc modeste : la tente ne prend pas
   toute la largeur, les drapeaux non plus. */
.tent { max-width: 880px; }

/* le nom du hero est borné par la HAUTEUR de l'écran autant que par
   sa largeur : sur un 1440 x 900, à 13,5 vw il mangeait la ligne de
   rôle sous lui. */
#hero h1 { font-size: min(11.5vw, 21vh, 200px); line-height: 0.9; }
.hero-role { margin-top: clamp(22px, 3.4vh, 36px); }

/* sans 3D, la scène redevient un bloc simple : la vidéo dans le flux,
   sa légende dessous — jamais par-dessus l'image. */
.scene.no3d .scene-pin { aspect-ratio: auto; background: none; }
.scene.no3d .scene-src { position: static; aspect-ratio: 16 / 9; }
.scene.no3d .scene-cap { position: static; padding: 14px calc(var(--track-x) + 24px) 0; }
.scene.no3d .scene-full { display: none; }

/* ============================================================
   RÉVÉLATIONS NATIVES — l'état au repos de tout texte est opacity 1,
   hors de tout @media et de tout @supports. Le mouvement n'est qu'un
   enrichissement, porté par le défilement lui-même (animation-timeline),
   jamais par une écriture d'opacité en JavaScript.
   ============================================================ */
.scene { view-timeline-name: --scene; view-timeline-axis: block; }
.credits { view-timeline-name: --credits; view-timeline-axis: block; }
.hero-hint { transition: opacity 0.4s, visibility 0s 0.4s; }
.hero-hint.gone { opacity: 0; visibility: hidden; }
.evolve-stage img:first-child { --o: 1; }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .lede, .voice, .quote, h2 { animation: rideau linear both; animation-timeline: view(); animation-range: entry 0% entry 85%; }
    .manifest span { animation: rise linear both; animation-timeline: view(); animation-range: entry 0% entry 220%; }
    .scene:not(.no3d) .scene-cap { animation: cap-out linear both; animation-timeline: --scene; animation-range: contain 55% contain 75%; }
    .scene:not(.no3d)[data-scene="corridor"] .scene-cap { animation-range: contain 35% contain 50%; }
    .credits-end { animation: fin-in linear both; animation-timeline: --credits; animation-range: contain 86% contain 95%; }
  }
}
@keyframes rise { from { transform: translateY(0.45em); } to { transform: none; } }
/* le rideau : le texte se découvre de haut en bas en glissant, tout est visible au repos (insets négatifs) */
@keyframes rideau { from { clip-path: inset(0 0 100% 0); transform: translateY(0.4em); } to { clip-path: inset(-0.2em 0 -0.4em 0); transform: none; } }
@keyframes cap-out { to { opacity: 0; transform: translateY(20px); } }
@keyframes fin-in { from { transform: translateY(18vh); } to { transform: none; } }


/* ============================================================
   LA LIGNE (ligne.js) — le calque : au-dessus du verre, sous le texte ;
   pendant la naissance, au-dessus de l'amorce. Le filet DOM ne sert
   plus qu'en secours, sans script.
   ============================================================ */
#ligne { position: fixed; inset: 0; z-index: 40; pointer-events: none; }
#ligne.ligne--naissance { z-index: 310; }
html.ligne-active .filet { display: none; }
.boot-in { position: absolute; left: 0; right: 0; top: calc(50% + 34px); text-align: center; display: block; }

/* ============================================================
   BASCULES D'ACTE — un chapitre de film. 200 vh : la première moitié est
   vide, la Ligne seule ; à mi-course elle traverse l'écran et l'acte
   change (la coupe, voir REGLES.md) ; puis le titre monte de sous
   l'écran. Au repos, tout est en place et visible.
   ============================================================ */
.acte { position: relative; height: 118vh; view-timeline-name: --acte; view-timeline-axis: block; }
.acte-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; display: grid; align-content: center; gap: 14px; padding: 0 var(--gut) 0 calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); }
@media (max-width: 860px) { .acte-pin { padding-left: calc(var(--track-x) + 24px); padding-right: 22px; } }
.acte-k { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.4em; text-transform: uppercase; color: rgb(var(--accent)); }
.acte-t { font-family: var(--f-disp); font-weight: 500; font-size: clamp(56px, 11vw, 190px); line-height: 0.9; letter-spacing: -0.035em; color: rgb(var(--ink-hi)); }
.acte-l { font-family: var(--f-body); font-style: italic; font-weight: 300; font-size: clamp(18px, 1.7vw, 27px); line-height: 1.4; color: rgb(var(--ink)); max-width: 34ch; margin-top: 10px; }
.acte-d { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.24em; color: rgb(var(--ink-lo)); }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .acte-k, .acte-t, .acte-l, .acte-d { animation: monte linear both; animation-timeline: --acte; }
    .acte-k { animation-range: entry 25% entry 70%; }
    .acte-t { animation-range: entry 30% entry 90%; }
    .acte-l { animation-range: entry 45% contain 15%; }
    .acte-d { animation-range: entry 40% contain 10%; }
  }
}
@keyframes monte { from { transform: translateY(70vh); } to { transform: none; } }

/* ============================================================
   PHASE 2 — L'ACTE I, LIEU PAR LIEU
   ============================================================ */
/* le bureau : les mots au mur, dans le DOM, posés sur les points 3D
   projetés (scenes.js). Au repos ils sont là, en gris ; quand la LED du
   bureau — la Ligne — passe, ils s'allument : une couleur, pas une opacité. */
.mots { position: absolute; inset: 0; pointer-events: none; }
.mot { position: absolute; left: 0; top: 0; transform: translate3d(var(--mx, 50%), var(--my, 50%), 0) translate(-50%, -50%); white-space: nowrap; font-family: var(--f-mono); font-size: clamp(11px, 0.95vw, 15px); letter-spacing: 0.34em; text-transform: uppercase; color: rgb(var(--ink)); transition: color 0.5s, text-shadow 0.5s; }
.mot.lit { color: rgb(var(--ink-hi)); text-shadow: 0 0 18px rgb(var(--accent) / 0.75), 0 0 2px rgb(var(--accent) / 0.6); }
.scene.no3d .mots { position: static; display: flex; flex-wrap: wrap; gap: 10px 26px; padding: 14px calc(var(--track-x) + 24px) 0; }
.scene.no3d .mot { position: static; transform: none; }

/* les archives, en profondeur : survol = elle avance, les autres reculent ;
   clic = elle vient au centre, la Ligne la souligne, son contexte s'écrit.
   Transformations seulement : rien ne bouge dans la mise en page. */
.archives { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(18px, 2.4vw, 40px) clamp(14px, 1.8vw, 30px); align-items: start; perspective: 1500px; margin-top: 8px; }
.archive { grid-column: var(--col, 1 / -1); margin: 0; position: relative; cursor: pointer; transform: translate3d(0, 0, var(--az, 0px)) scale(var(--as, 1)); transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1), filter 0.45s; outline-offset: 6px; }
.archive:focus-visible { outline: 1px solid rgb(var(--accent)); }
.archive-cadre { position: relative; background: rgb(var(--bg)); }
.archive-cadre img { display: block; width: 100%; height: auto; }
.archive-cadre::after { content: ""; position: absolute; inset: 0; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); pointer-events: none; }
.archives.a-isole .archive:not(.isolee) { --az: -100px; filter: brightness(0.42); }
.archive.isolee { transform: translate3d(var(--ax, 0px), var(--ay, 0px), 0) scale(var(--as2, 1)); z-index: 3; filter: none; }
.archives-contexte { margin: clamp(18px, 2.4vw, 36px) 0 0; min-height: 3.4em; max-width: 60ch; font-size: var(--t-body); line-height: 1.55; color: rgb(var(--ink)); }
@media (max-width: 860px) {
  .archive { grid-column: 1 / -1 !important; }
  .archives:has(.archive:hover) .archive:not(:hover):not(.isolee) { --az: 0px; }
}
@media (prefers-reduced-motion: reduce) {
  .archive, .mot { transition: none; }
  .archive:hover { --az: 0px; --as: 1; }
}

/* ============================================================
   PHASE 3 — L'ACTE II : le JT
   ============================================================ */
/* le titre en niveaux : le numéro reste isolé (.mark), le verbe immense et
   fin, le complément moyen et décalé, le nom en mono. La grammaire des titres. */
.titre-niveaux { display: grid; gap: 0.08em; max-width: none; font-size: inherit; line-height: 1; }
.tn-verbe { font-family: var(--f-disp); font-weight: 500; font-size: clamp(60px, 11vw, 190px); line-height: 0.88; letter-spacing: -0.035em; color: rgb(var(--ink-hi)); }
.tn-comp { font-family: var(--f-disp); font-weight: 500; font-size: clamp(22px, 2.7vw, 46px); line-height: 1.1; letter-spacing: -0.01em; color: rgb(var(--ink)); margin-left: clamp(0px, 14vw, 240px); margin-top: 0.3em; }
.tn-nom { font-family: var(--f-mono); font-weight: 400; font-size: var(--t-mono); letter-spacing: 0.32em; text-transform: uppercase; color: rgb(var(--accent)); margin-top: 1.4em; margin-left: clamp(0px, 14vw, 240px); }
/* retours 13 : le nom du projet sous le titre du JT, bien plus gros */
#c03 .tn-nom { font-family: var(--f-disp); font-weight: 600; font-size: clamp(22px, 2.6vw, 44px); letter-spacing: 0.02em; text-transform: uppercase; color: rgb(var(--accent)); margin-left: clamp(0px, 14vw, 240px); margin-top: 0.5em; }

/* la galerie du couloir : sur desktop les images sont les cadres 3D et les
   cartels sont projetés sous chaque cadre (un vrai cartel de musée, une
   petite carte sombre) ; sans 3D, une colonne à plat. */
.scene:not(.no3d) .galerie-plate { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
.scene:not(.no3d) .cadre { position: absolute; left: 0; top: 0; margin: 0; width: max-content; max-width: 30ch; transform: translate3d(var(--mx, -9999px), var(--my, 0px), 0) translate(-50%, 0); }
.scene:not(.no3d) .cadre picture { display: none; }
.scene:not(.no3d) .cadre .cartel { padding: 9px 12px 10px; background: rgb(var(--bg) / 0.88); border: 1px solid rgb(var(--rule) / var(--rule-a)); color: rgb(var(--ink)); }
.scene:not(.no3d) .cadre .cartel b { color: rgb(var(--ink-hi)); }
.scene.no3d .galerie-plate { display: grid; gap: 34px; padding: 26px calc(var(--track-x) + 24px) 0; }
.scene.no3d .cadre { margin: 0; }
.scene.no3d .cadre img { display: block; width: 100%; height: auto; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); }

/* le son du JT : un geste, jamais automatique */
.scene-full .son { position: absolute; right: var(--gut); bottom: 22px; padding: 14px 18px; border: 1px solid rgb(var(--ink-hi) / 0.5); background: rgb(var(--bg) / 0.72); color: rgb(var(--ink-hi)); font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.16em; text-transform: uppercase; cursor: pointer; }
.scene-full .son[aria-pressed="true"] { background: rgb(var(--ink-hi)); color: rgb(var(--bg)); border-color: rgb(var(--ink-hi)); }
@media (max-width: 860px) {
  .tn-comp, .tn-nom { margin-left: 0; }
}

/* ============================================================
   PHASE 3b — L'ÉCOSYSTÈME : on manipule
   ============================================================ */
/* les flèches des carrousels (44 px, tactile) et le compteur */
.social-ctl, .supports-ctl { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.social-btn { all: unset; cursor: pointer; width: 46px; height: 46px; display: grid; place-items: center; border: 1px solid rgb(var(--rule) / 0.22); color: rgb(var(--ink-hi)); font-family: var(--f-mono); font-size: 16px; transition: border-color 0.25s, background 0.25s; }
.social-btn:hover, .social-btn:focus-visible { border-color: rgb(var(--accent)); outline: none; background: rgb(var(--accent) / 0.12); }
.social-n { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.14em; color: rgb(var(--ink-lo)); min-width: 6ch; text-align: center; }
.social:focus-visible, .supports:focus-visible { outline: 1px solid rgb(var(--accent)); outline-offset: 12px; }

/* le social : le téléphone au centre, les publications en profondeur */
.social { --pw: min(280px, 64vw); outline: none; }
.social-stage { position: relative; height: calc(var(--pw) * 2.05 + 40px); perspective: 1600px; touch-action: pan-y; cursor: grab; overflow: hidden; }
.social-stage.saisi { cursor: grabbing; }
.pubs { position: absolute; inset: 0; }
.pub { position: absolute; left: 50%; top: 50%; width: var(--pw); aspect-ratio: 9 / 18.5; margin: 0; border-radius: 22px; overflow: hidden; background: #000; transform: translate(-50%, -50%) translate3d(var(--kx, 0px), 0, var(--kz, 0px)) rotateY(var(--kr, 0deg)); filter: brightness(var(--kb, 1)); transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1), filter 0.6s; will-change: transform; }
.pub picture { display: block; width: 100%; height: 100%; }
.pub img { width: 100%; height: 100%; object-fit: contain; object-position: 50% 42%; display: block; }
.pub .cartel { position: absolute; left: 0; right: 0; bottom: 0; padding: 12px 14px 14px; background: rgb(0 0 0 / 0.78); color: rgb(var(--ink)); }
.pub .cartel b { color: rgb(var(--ink-hi)); }
.pub.s0 { --kx: 0px; --kz: 0px; --kr: 0deg; --kb: 1; z-index: 6; }
.pub.s1 { --kx: calc(var(--pw) * 0.62); --kz: -240px; --kr: -16deg; --kb: 0.55; z-index: 5; }
.pub.s-1 { --kx: calc(var(--pw) * -0.62); --kz: -240px; --kr: 16deg; --kb: 0.55; z-index: 5; }
.pub.s2 { --kx: calc(var(--pw) * 1.12); --kz: -520px; --kr: -24deg; --kb: 0.3; z-index: 4; }
.pub.s-2 { --kx: calc(var(--pw) * -1.12); --kz: -520px; --kr: 24deg; --kb: 0.3; z-index: 4; }
.pub.s3 { --kx: 0px; --kz: -760px; --kr: 0deg; --kb: 0.18; z-index: 3; }

/* la vidéo : un écran, les autres dans l'espace */
.viewer-espace { grid-template-columns: minmax(220px, 320px) 1fr; }
.viewer-ecran { position: relative; }
.viewer-cartel { position: absolute; left: 0; right: 0; bottom: 0; padding: 12px 14px; background: rgb(0 0 0 / 0.72); color: rgb(var(--ink)); }
.viewer-cartel b { color: rgb(var(--ink-hi)); }
/* la fuite est à droite : les cartes du fond s'écartent au lieu de se couvrir, chacune reste choisissable */
.viewer-cartes { position: relative; min-height: 420px; perspective: 1400px; perspective-origin: 100% 50%; touch-action: pan-y; overflow: hidden; }
.carte { all: unset; cursor: pointer; position: absolute; left: 2%; top: 0; width: 22%; aspect-ratio: 9 / 16; border-radius: 14px; overflow: hidden; background: #000; border: 1px solid rgb(var(--rule) / 0.18); transform: translate3d(var(--cx, 0%), var(--cy, 0%), var(--cz, 0px)) rotateY(-12deg); filter: brightness(var(--cb, 0.7)); transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1), filter 0.4s, border-color 0.25s; will-change: transform; }
.carte picture, .carte img { display: block; width: 100%; height: 100%; object-fit: cover; }
.carte .carte-t { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 12px; background: rgb(0 0 0 / 0.72); font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.1em; text-transform: uppercase; color: rgb(var(--ink-hi)); display: grid; grid-template-columns: auto 1fr; gap: 10px; }
.carte .carte-t i { font-style: normal; color: rgb(var(--accent)); }
.carte:hover, .carte:focus-visible { border-color: rgb(var(--accent)); --cb: 1; }
.carte.on { border-color: rgb(var(--accent)); --cb: 1; }
.carte.on::after { content: "À l'écran"; position: absolute; left: 12px; top: 12px; padding: 5px 8px; background: rgb(var(--accent)); color: rgb(var(--bg)); font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; }

/* les supports : au centre le support choisi, derrière le précédent et le suivant */
.supports { outline: none; }
.supports-stage { position: relative; height: clamp(320px, 42vw, 560px); perspective: 1700px; touch-action: pan-y; cursor: grab; overflow: hidden; }
.supports-stage.saisi { cursor: grabbing; }
.support { position: absolute; left: 50%; top: 50%; width: min(760px, 78%); transform: translate(-50%, -50%) translate3d(var(--sx, 0%), 0, var(--sz, 0px)) rotateY(var(--sr, 0deg)) scale(var(--ss, 1)); filter: brightness(var(--sb, 1)); transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1), filter 0.6s; will-change: transform; }
.support.s0 { --sx: 0%; --sz: 0px; --sr: 0deg; --ss: 1; --sb: 1; z-index: 6; }
.support.s1 { --sx: 60%; --sz: -520px; --sr: -26deg; --ss: 0.8; --sb: 0.42; z-index: 5; }
.support.s-1 { --sx: -60%; --sz: -520px; --sr: 26deg; --ss: 0.8; --sb: 0.42; z-index: 5; }
.support.s2, .support.s-2 { --sx: 0%; --sz: -900px; --sr: 0deg; --ss: 0.6; --sb: 0.2; z-index: 4; }
/* chaque support révèle sa nature quand il arrive au centre */
.support .tent { --tl: -78deg; --tr: 78deg; }
.support.s0 .tent { --tl: 0deg; --tr: 0deg; }
.support .flag { --fy: 44px; --fr: 0deg; }
.support .flag:nth-child(odd) { --fr: 6.5deg; } .support .flag:nth-child(even) { --fr: -7.5deg; }
.support.s0 .flag { --fy: 0px; --fr: 0deg; }
.support .flags { max-width: 520px; margin: 0 auto; }
.kakemono { margin: 0; width: min(240px, 42%); margin-inline: auto; clip-path: inset(0 0 100% 0); transition: clip-path 1.1s cubic-bezier(0.22, 1, 0.36, 1) 0.2s; }
.support.s0 .kakemono { clip-path: inset(0 0 0 0); }
.kakemono img { display: block; width: 100%; height: auto; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); }
.bache { margin: 0; clip-path: inset(0 100% 0 0); transition: clip-path 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.2s; }
.support.s0 .bache { clip-path: inset(0 0 0 0); }
.bache img { display: block; width: 100%; height: auto; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.4)); }
.supports-cartel { margin-top: 10px; min-height: 3.2em; }

@media (max-width: 860px) {
  .viewer-espace { grid-template-columns: 1fr; }
  .viewer-cartes { min-height: 0; height: auto; display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; perspective: none; }
  .carte { position: static; flex: 0 0 38%; transform: none; }
  .supports-stage { height: 70vw; }
  .support { width: 92%; }
}
@media (prefers-reduced-motion: reduce) {
  .pub, .carte, .support, .tent figure, .flag, .kakemono, .bache { transition: none; }
  .support .tent { --tl: 0deg; --tr: 0deg; } .support .flag { --fy: 0px; --fr: 0deg; }
  .kakemono, .bache { clip-path: none; }
}

/* ============================================================
   PHASE 4 — LES ACTES III ET IV : on découvre, on regarde, on lit
   ============================================================ */
/* UNDERGROUND — l'évolution en trois pièces, lentement : une pièce entre, on la
   voit, elle se décale, la suivante arrive. Plus petites, plus d'air. */
.ug-marque { display: inline-block; vertical-align: middle; width: 54px; height: auto; margin-left: 14px; mix-blend-mode: screen; }
.pieces-stage { position: relative; height: 276vh; } /* retours 58 : 100vh + 2,2 × 80vh */
.pieces-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; }
.pieces-k { position: absolute; left: 0; top: 50%; transform: translateY(-50%); font-family: var(--f-disp); font-weight: 700; font-size: clamp(90px, 18vw, 300px); line-height: 0.8; letter-spacing: -0.04em; color: rgb(var(--ink-hi) / 0.09); pointer-events: none; }
.piece { position: absolute; left: 50%; top: 50%; width: min(680px, 62vw); margin: 0; transform: translate(-50%, -50%) translate3d(var(--px, 120vw), 0, 0) scale(var(--ps, 0.92)); will-change: transform; }
.piece img { display: block; width: 100%; height: auto; max-height: 52vh; object-fit: contain; }
.piece .cartel { justify-items: stretch; text-align: center; padding-top: 22px; }
.piece .cartel b { color: rgb(var(--ink-hi)); }
.piece .cartel span { max-width: 44ch; }
@media (max-width: 860px) { .piece { width: 86vw; } .pieces-k { font-size: 30vw; } }
@media (prefers-reduced-motion: reduce) {
  .pieces-stage { height: auto; } .pieces-pin { position: static; height: auto; display: grid; gap: 40px; overflow: visible; }
  .piece { position: static; transform: none; width: 100%; } .pieces-k { display: none; }
}

/* SOUVENIRS — le format cinéma, et rien d'autre */
.cinema { aspect-ratio: 2.35 / 1 !important; }
.cinema video { width: 100%; height: 100%; object-fit: cover; }

/* AUJOURD'HUI — des fragments du présent, à différentes profondeurs, qui passent
   derrière nous pendant que la Ligne continue */
.fragments-stage { position: relative; height: 320vh; }
.fragments-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; perspective: 1200px; perspective-origin: 50% 50%; }
.fragment { position: absolute; left: 50%; top: 50%; width: var(--fw, 30vw); margin: 0; aspect-ratio: var(--fa, 16 / 9); transform: translate(-50%, -50%) translate3d(var(--fx, 0px), var(--fy, 0px), var(--fz, -1400px)); filter: brightness(var(--fb, 0.4)); will-change: transform; background: #000; }
.fragment video { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 860px) { .fragment { --fw: 70vw !important; } }
@media (prefers-reduced-motion: reduce) {
  .fragments-stage { height: auto; } .fragments-pin { position: static; height: auto; display: grid; gap: 28px; perspective: none; overflow: visible; }
  .fragment { position: static; transform: none; filter: none; width: 100%; }
}

/* PROFIL — on lit dans l'ordre : la Ligne passe devant chaque phrase et l'allume.
   Tout est visible au repos (une couleur, jamais une opacité). */
.profil-fil { display: grid; gap: clamp(36px, 6vh, 90px); max-width: 78ch; padding-left: clamp(28px, 4vw, 56px); position: relative; }
.profil-fil .phrase:nth-child(2) { margin-left: 18%; }
.profil-fil .phrase:nth-child(3) { margin-left: 0; max-width: 40ch; }
.profil-fil .phrase:nth-child(4) { margin-left: 34%; }
.profil-fil .phrase:nth-child(5) { margin-left: 8%; }
.profil-fil .phrase:nth-child(6) { margin-left: -4%; }
.profil-fil .phrase .p-tail { margin-left: 0; }
.profil-fil .facts { display: flex; flex-wrap: wrap; gap: 10px 26px; }
.profil-fil .facts li { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.1em; text-transform: uppercase; color: rgb(var(--ink)); }
.profil-fil .facts li::before { content: "— "; color: rgb(var(--accent)); }
.phrase { color: rgb(var(--ink)); }
.phrase .lede, .phrase .voice, .phrase .copy, .phrase .facts li { color: inherit; }
.phrase .em, .phrase .hi { color: inherit; }
.phrase .lede, .phrase .em, .phrase .voice { color: rgb(var(--ink-hi)); }
.phrase .hi { color: rgb(var(--accent)); }
.phrase .lab { display: block; margin-bottom: 10px; }
.phrase.dispo .disp { display: block; font-family: var(--f-disp); font-weight: 500; font-size: clamp(30px, 4.6vw, 76px); line-height: 0.95; letter-spacing: -0.03em; color: inherit; }
.phrase.dispo .disp { color: rgb(var(--ink-hi)); }

/* ============================================================
   PHASE 5 — TOUJOURS MIEUX : les titres se dévoilent, le curseur fait écho,
   « passer la scène »
   ============================================================ */
/* les grands verbes et la dernière phrase du profil se dévoilent par un masque qui
   descend (clip-path + translation, jamais une opacité) ; au repos, tout est visible */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .tn-verbe { animation: devoile linear both; animation-timeline: view(); animation-range: entry 12% entry 75%; }
  }
}
@keyframes devoile { from { clip-path: inset(0 0 100% 0); transform: translateY(0.22em); } to { clip-path: inset(-0.15em 0 -0.3em 0); transform: none; } }

/* « Passer la scène » : un seul lien fixe, hors écran jusqu'au focus (comme le lien
   d'évitement), dont la cible est toujours le lieu suivant ; en mouvement réduit il
   reste visible, en bas à droite */
.passer { left: auto; right: 8px; }
@media (prefers-reduced-motion: reduce) { .passer { transform: none; top: auto; bottom: 16px; } }

/* ============================================================
   ALLÈGEMENT MOBILE — sur petit écran, pas de filtres ni de calques permanents
   sur les scènes en profondeur : la profondeur se lit déjà par la taille et la
   position, et chaque filtre coûtait une surface de rendu (tâches longues ×4).
   ============================================================ */
@media (max-width: 860px) {
  .pub, .carte, .support, .fragment, .piece, .archive { filter: none; will-change: auto; }
  .scene:not(.no3d) .cadre .cartel, .cur { backdrop-filter: none; }
}

/* ============================================================
   PHASE 6 — retours de Thibault : moins, mais mieux
   ============================================================ */
/* les mots du bureau et les légendes de scène n'existent plus */
.mots, .mot { display: none; }

/* le profil en désordre : chaque phrase a sa colonne, sa largeur, sa taille — l'ordre
   de lecture reste celui du document, la Ligne passe devant chacune */
.profil-fil { max-width: none; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(14px, 1.8vw, 30px); row-gap: clamp(40px, 8vh, 120px); padding-left: 0; }
.profil-fil .phrase:nth-child(1) { grid-column: 1 / 9; }
.profil-fil .phrase:nth-child(1) .lede { max-width: 26ch; font-size: clamp(26px, 3vw, 48px); }
.profil-fil .phrase:nth-child(2) { grid-column: 6 / 13; margin-top: 6vh; }
.profil-fil .phrase:nth-child(3) { grid-column: 1 / 6; }
.profil-fil .phrase:nth-child(4) { grid-column: 7 / 13; margin-top: 10vh; }
.profil-fil .phrase:nth-child(5) { grid-column: 2 / 7; margin-top: -4vh; }
.profil-fil .phrase:nth-child(6) { grid-column: 4 / 13; margin-top: 8vh; }
.profil-fil .phrase:nth-child(6) .disp { font-size: clamp(34px, 6vw, 110px); }
@media (max-width: 860px) { .profil-fil .phrase { grid-column: 1 / -1 !important; margin-top: 0 !important; } }

/* les apparitions mot à mot : chaque mot monte de sous sa ligne (masque + translation,
   jamais une opacité) quand il entre dans l'écran, décalé de ses voisins. Au repos,
   tout est posé. Coupé en mouvement réduit et sur petit écran (app.js ne découpe pas). */
/* les mots restent en ligne, sans boîte : c'est la ligne (.l) qui masque ; 1 300 boîtes de moins à peindre */
.w, .wi { display: inline; }
/* le dévoilement par ligne (d'après landonorris.com, mesuré) : la ligne s'ouvre de gauche à
   droite en 0,6 s, décalée de 0,15 s par ligne ; une barre d'accent la balaie puis se retire
   (0,6 s, + 0,3 s). Sur les phrases paires du profil, tout est en miroir. Repos : tout est là. */
@media (prefers-reduced-motion: no-preference) and (min-width: 861px) {
  /* chaque ligne s'ouvre quand elle passe le bas de l'écran, et se referme si on remonte :
     app.js pose --p (0 → 1) sur le bloc, --n (lignes) ; chaque ligne calcule son propre avancement
     --r à partir de son rang --i, décalée de 0,6 ligne sur sa voisine. Repos (sans JS) : --p vaut 1. */
  .l { position: relative; --r: clamp(0, var(--p, 1) * (1 + 0.8 * (var(--n, 1) - 1)) - 0.8 * var(--i, 0), 1); --rl: clamp(0, (var(--r) - var(--x0, 0)) / max(0.001, var(--x1, 1) - var(--x0, 0)), 1); clip-path: inset(-0.15em calc((1 - var(--rl)) * 100%) -0.15em -0.22em); }
  /* la barre d'accent mène le bord : présente seulement pendant l'ouverture (jamais sur un mot lu) */
  /* la barre ne bouge que par transformation (jamais par left : une mise en page par image, mesuré ~100 ms) ; --lw = largeur de l'enveloppe en px, posée par app.js */
  .l::after { content: ""; position: absolute; top: 0.08em; bottom: 0.02em; width: 0.45em; left: 0; margin-left: -0.45em; background: rgb(var(--accent)); transform: translateX(calc(var(--rl) * var(--lw, 0px))) scaleX(clamp(0, min(var(--rl), 1 - var(--rl)) * 24, 1)); transform-origin: right center; pointer-events: none; }
  /* 2 · de droite à gauche (et les phrases paires du profil) */
  [data-rv="2"] .l, .phrase:nth-child(even) .l { clip-path: inset(-0.15em -0.22em -0.15em calc((1 - var(--rl)) * 100%)); }
  [data-rv="2"] .l::after, .phrase:nth-child(even) .l::after { left: 0; margin-left: 0; transform: translateX(calc((1 - var(--rl)) * var(--lw, 0px))) scaleX(clamp(0, min(var(--rl), 1 - var(--rl)) * 24, 1)); transform-origin: left center; }
  /* 3 · en dégradé : un voile doux qui glisse de gauche à droite, sans barre */
  [data-rv="3"] .l { clip-path: none; -webkit-mask-image: linear-gradient(90deg, #000 calc(var(--rl) * 130% - 30%), transparent calc(var(--rl) * 130%)); mask-image: linear-gradient(90deg, #000 calc(var(--rl) * 130% - 30%), transparent calc(var(--rl) * 130%)); }
  [data-rv="3"] .l::after { content: none; }
  /* 4 · depuis le centre, vers les deux bords */
  [data-rv="4"] .l { clip-path: inset(-0.15em calc((1 - var(--rl)) * 50% - 0.22em) -0.15em calc((1 - var(--rl)) * 50% - 0.22em)); }
  [data-rv="4"] .l::after { content: none; }
  /* 5 · de haut en bas, ligne par ligne */
  [data-rv="5"] .l { clip-path: inset(-0.15em -0.22em calc((1 - var(--rl)) * 100% - 0.15em) -0.22em); }
  [data-rv="5"] .l::after { content: none; }
  /* 6 · de bas en haut, en dégradé vertical */
  [data-rv="6"] .l { clip-path: none; -webkit-mask-image: linear-gradient(0deg, #000 calc(var(--rl) * 140% - 40%), transparent calc(var(--rl) * 140%)); mask-image: linear-gradient(0deg, #000 calc(var(--rl) * 140% - 40%), transparent calc(var(--rl) * 140%)); }
  [data-rv="6"] .l::after { content: none; }
  /* la dernière phrase du profil : les lettres montent, par crans de 0,02 s */
  .phrase.dispo .disp { overflow: clip; }
  .phrase.dispo .mw { display: inline-block; white-space: nowrap; }
  .phrase.dispo .c { display: inline-block; transform: translateY(105%); }
  .phrase.dispo.vu .c, .phrase.dispo .disp.vu .c { animation: mot 0.7s cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(var(--i, 0) * 0.02s); }
}
@keyframes essuie { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 -0.05em 0 0); } }
@keyframes essuie-miroir { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 -0.05em); } }
/* la barre : au bord du dévoilement, de gauche à droite, puis elle s'efface en s'étirant vers rien */
@keyframes barre { 0% { left: 0; margin-left: 0; transform: scaleX(1); } 85% { left: 100%; margin-left: -0.45em; transform: scaleX(1); } 100% { left: 100%; margin-left: -0.45em; transform: scaleX(0); } }
@keyframes barre-miroir { 0% { left: 100%; margin-left: -0.45em; transform: scaleX(1); } 85% { left: 0; margin-left: 0; transform: scaleX(1); } 100% { left: 0; margin-left: 0; transform: scaleX(0); } }

/* le roulement des liens de la barre */
.bar-nav a.roule .rls { position: relative; display: inline-block; overflow: clip; height: 1.3em; line-height: 1.3em; vertical-align: middle; }
.bar-nav a.roule .rl { display: block; white-space: nowrap; }
.bar-nav a.roule .rl span { display: inline-block; transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1); transition-delay: calc(var(--i, 0) * 0.02s); }
.bar-nav a.roule .rl2 { position: absolute; left: 0; top: 100%; }
.bar-nav a.roule:hover .rl span, .bar-nav a.roule:focus-visible .rl span { transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) { .bar-nav a.roule .rl span { transition: none; } .bar-nav a.roule:hover .rl span { transform: none; } }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 861px) {
    /* les blocs découpés ne portent plus le rideau ; le corps de texte, lui, le garde (desktop seulement) */
    .lede, .voice, .quote, h2 { animation: none; }
    .copy { animation: rideau linear both; animation-timeline: view(); animation-range: entry 0% entry 70%; }
  }
}
@keyframes mot { from { transform: translateY(105%); } to { transform: none; } }

/* ============================================================
   PHASE 6b — retours de Thibault, suite
   ============================================================ */
/* la vidéo qui joue n'apparaît pas dans l'éventail */
.carte.on { display: none; }
/* la plaquette se voit entière pendant qu'on la feuillette */
.book { width: min(820px, 100%, calc((100vh - 220px) * 1.414)); }
.book-pin { top: 12vh; }
/* les flèches des supports au centre de la page */
.supports-ctl { justify-content: center; }
/* les maillots : ni numéro géant, ni ligne de texte ; les images détourées respirent */
.pieces-k { display: none; }
.piece .cartel span { display: none; }
.piece img { max-height: 58vh; }
/* les cartels du couloir sont des plaques dans la scène : la version DOM ne sert qu'à plat, sans 3D */
.scene:not(.no3d) .galerie-plate { display: none; }

/* ============================================================
   PHASE 7 — retours de Thibault, troisième tour
   ============================================================ */
/* le PSG : la vidéo tient dans 82 % de la hauteur, la légende vit dessous, dans la bande libre */
.psg-boite { height: calc(100vh - 82px - 13vh); }
#psgCap { position: absolute; left: 50%; bottom: 3.2vh; transform: translateX(-50%); max-width: calc(100% - 2 * var(--gut)); padding: 0; background: none; color: rgb(var(--ink-lo)); text-align: center; z-index: 2; }
#psgClip { align-items: flex-start; padding-top: calc(82px + 2.5vh); }
/* les flèches du social au centre */
.social-ctl { justify-content: center; }
/* la plaquette : centrée, et elle s'ouvre avant de se feuilleter (posée de biais, fermée, puis
   elle se redresse et son plat gauche se déplie) */
.book-pin { display: grid; justify-items: center; }
.book { transform: perspective(2400px) rotateY(calc((1 - var(--bo, 1)) * -34deg)) rotateX(calc((1 - var(--bo, 1)) * 14deg)) scale(calc(0.72 + 0.28 * var(--bo, 1))); transform-origin: 50% 60%; will-change: transform; }
.book-cover { transform-origin: 100% 50%; transform: rotateY(calc((1 - var(--bo, 1)) * 180deg)); backface-visibility: hidden; }
.book-hint, .book-n { bottom: -30px; }
/* le site : plus petit, centré ; on tape l'adresse, une barre de chargement court, puis la page monte dans le cadre */
.browser { max-width: 820px; margin-inline: auto; position: relative; overflow: hidden; }
.browser-charge { position: absolute; left: 0; top: 0; height: 2px; width: 100%; background: rgb(var(--accent)); transform: scaleX(var(--bl, 0)); transform-origin: left center; z-index: 3; }
.browser-shot { display: block; transform: translateY(calc((1 - var(--bp, 1)) * 100%)); will-change: transform; }
@media (prefers-reduced-motion: reduce) { .book { transform: none; } .book-cover { transform: none; } .browser-shot { transform: none; } }

/* ============================================================
   RÈGLE 3, à la racine : rien ne peut élargir le document. `clip` ne crée pas de conteneur de
   défilement (les éléments collants continuent de coller), il coupe seulement ce qui dépasse.
   La plaquette posée de biais (perspective + rotateY) élargissait la fenêtre mobile.
   ============================================================ */
html, body { overflow-x: clip; }
.book-pin { overflow-x: clip; }

/* la recommandation : écartée, aérée, seule sur sa page */
.quote { letter-spacing: 0.012em; word-spacing: 0.08em; line-height: 1.55; max-width: 34ch; margin-block: 10vh 6vh; }

/* ---- retours 6 : rythme, légendes, volets ---- */
#c02 { padding-bottom: clamp(16px, 3vh, 36px); }
#c06 { padding-bottom: clamp(12px, 2vh, 28px); }
#c06 .copy.p-tail { margin-left: 8%; }
.psg-stage { height: 180vh; }
/* les quatre volets de l'écosystème : de grands titres, numérotés, qui se dévoilent */
.lab.volet { font-family: var(--f-disp); font-weight: 600; font-size: clamp(34px, 5vw, 84px); line-height: 0.95; letter-spacing: -0.03em; text-transform: none; color: rgb(var(--ink-hi)); margin-bottom: clamp(16px, 2.4vh, 30px); }
.lab.volet b { display: inline-block; font-family: var(--f-mono); font-weight: 500; font-size: var(--t-mono); letter-spacing: 0.3em; color: rgb(var(--accent)); vertical-align: 0.9em; margin-right: 16px; }
/* les légendes sous ce qu'on fait défiler, centrées */
.social-cartel, .supports .supports-cartel { text-align: center; justify-items: center; margin: 12px auto 0; min-height: 2.4em; max-width: 46ch; }
.social-cartel b { color: rgb(var(--ink)); text-transform: none; letter-spacing: 0.08em; }
/* le livre arrive de la droite, hors écran, puis s'ouvre */
.book { translate: calc(var(--bx, 0) * 78vw) 0; }

/* une scène 3D qui a échoué le dit, en bas à gauche, en petit : de quoi me le rapporter */
.scene.no3d[data-erreur] .scene-pin::after { content: "3D indisponible — " attr(data-erreur); position: absolute; left: 14px; bottom: 14px; z-index: 6; font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.06em; color: rgb(var(--ink-lo)); background: rgb(var(--bg) / 0.7); padding: 6px 10px; pointer-events: none; }

/* ---- retours 8 ---- */
#c06 .copy.p-tail { margin-top: clamp(70px, 15vh, 190px); }
@media (min-width: 861px) {
  #c09 .voice.p-tail { grid-column: 3 / -1; max-width: 72ch; font-size: clamp(16px, 1.22vw, 20px); line-height: 1.6; margin-top: clamp(60px, 12vh, 160px); }
}

/* ---- la vidéo : entrée et sortie en domino ----
   --pv (entrée, 0 → 1 quand le bloc monte du bas vers le milieu) et --pw (sortie, 0 → 1 quand il quitte par le
   haut) sont posés sur .viewer par app.js ; chaque carte, décalée par son rang --i, se couche depuis le bas puis
   se relève en partant ; l'écran pivote comme une porte. Transformations seulement, réversible au défilement. */
@media (prefers-reduced-motion: no-preference) and (min-width: 861px) {
  .carte { --d: clamp(0, var(--pv, 1) * 2.6 - var(--i, 0) * 0.32, 1); --e: clamp(0, var(--pw, 0) * 2.6 - var(--i, 0) * 0.32, 1); transform-origin: 50% 100%;
    transform: rotateX(calc((1 - var(--d)) * -88deg + var(--e) * 88deg)) translate3d(var(--cx, 0%), var(--cy, 0%), var(--cz, 0px)) rotateY(-12deg); }
  .viewer-ecran { transform-origin: 0% 50%; transform: perspective(1400px) rotateY(calc((1 - clamp(0, var(--pv, 1) * 1.6, 1)) * -75deg + clamp(0, var(--pw, 0) * 1.6, 1) * 75deg)); }
}

/* ---- test E : l'île en fond d'ardoise d'acte (vidéo Blender), sous un voile sombre pour garder 4,5:1 ---- */
.acte-pin { position: sticky; }
.acte-fond { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.acte-fond img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* l'image respire : un lent zoom pendant que l'ardoise est à l'écran (images du système de prompts) */
@supports (animation-timeline: view()) {
  img.acte-fond--zoom { animation: ile-souffle linear both; animation-timeline: --acte; animation-range: entry 0% exit 100%; }
}
@keyframes ile-souffle { from { transform: scale(1.06) translateY(-1.5%); } to { transform: scale(1.0) translateY(1.5%); } }
@media (prefers-reduced-motion: reduce) { img.acte-fond--zoom { animation: none; } }
.acte-pin::before { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(90deg, rgb(var(--bg) / 0.9) 0%, rgb(var(--bg) / 0.74) 55%, rgb(var(--bg) / 0.35) 100%); pointer-events: none; }
.acte-pin .acte-k, .acte-pin .acte-l, .acte-pin .acte-d { text-shadow: 0 0 14px rgb(var(--bg)), 0 0 4px rgb(var(--bg)); }
.acte-pin > :not(.acte-fond) { position: relative; z-index: 2; }
@media (max-width: 860px) { .acte-fond { display: none; } }
/* l'ouverture : le film est le sujet, le voile ne couvre que le bas gauche, l'ardoise dure plus longtemps */
.acte--film { height: 165vh; }
.acte--film .acte-pin::before { background: linear-gradient(90deg, rgb(var(--bg) / 0.9) 0%, rgb(var(--bg) / 0.82) 38%, rgb(var(--bg) / 0.3) 62%, rgb(var(--bg) / 0) 80%), linear-gradient(0deg, rgb(var(--bg) / 0.8) 0%, rgb(var(--bg) / 0) 50%); }
.acte--film .acte-t { font-size: clamp(48px, 8.4vw, 150px); }
.acte--film .acte-fond { filter: saturate(1.05) contrast(1.03); }
@media (max-width: 860px) { .acte--film { height: auto; } }

/* les cartels des cartes vidéo restent lisibles même quand la carte bascule en domino (fond plus dense) */
.carte .carte-t { background: rgb(0 0 0 / 0.88); }

/* ---- retours 9 ---- */
/* 1 · le social tient dans l'écran */
.social { --pw: min(240px, 34vh, 64vw); }
/* 2 · plus d'air entre les quatre volets de l'écosystème */
#c05 .stackset { row-gap: clamp(64px, 11vh, 170px); }
/* 3 · la plaquette : hors écran tant qu'on n'y est pas, plus petite */
.book { translate: calc(var(--bx, 0) * 118vw + var(--cx, 0px) + var(--bs, 0px)) 0; } /* --cx : recentrage sur l'écran, --bs : la page visible au centre (app.js) */
@media (min-width: 861px) { .book { width: min(680px, 100%, calc((100vh - 260px) * 1.414)); } }
/* 4 · le site Intripid se fait défiler depuis notre cadre */
.browser-shot { max-height: 62vh; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
/* 6 · le PSG plein cadre : la vidéo et sa légende tiennent ensemble */
.psg-boite { height: calc(100vh - 82px - 17vh); }
#psgCap { bottom: 4vh; max-width: 72vw; text-align: center; }
/* 8 · UNDERGROUND : le numéro au-dessus, la légende sous l'image, plus rien dans la photo */
.case { overflow: visible; aspect-ratio: auto !important; }
.case-cover picture, .case-cover img { display: block; aspect-ratio: 1 / 1.414; height: 100%; width: auto; }
.case-sora picture, .case-sora img { display: block; aspect-ratio: 2 / 3; height: 100%; width: auto; }
.case-terrain picture, .case-terrain img { display: block; aspect-ratio: 3 / 2; }
.case-k { top: auto; bottom: 100%; margin-bottom: 8px; }
.case .tag { position: static; display: block; transform: none; padding: 10px 0 0; background: none; color: rgb(var(--ink)); }
.case-cover::after { bottom: auto; aspect-ratio: 1 / 1.414; }
/* 9 · plus de logo UNDERGROUND */
.ug-marque { display: none; }
/* 10 · après le troisième maillot, on descend tout de suite */
.pieces-stage { height: 210vh; }
/* 11 · les souvenirs dans leur format d'origine (posé par app.js depuis la vidéo) */
.cinema { aspect-ratio: var(--ra, 2.35 / 1) !important; }
.cinema video, .fragment video { object-fit: contain; background: #000; }
/* 12 · « Ce que je cherche » et « Comment je travaille » en gras */
.phrase .lab { font-weight: 700; color: rgb(var(--ink-hi)); font-size: calc(var(--t-mono) * 1.15); }
/* 13 · les faits, un par ligne, tirets alignés */
.profil-fil .facts { display: grid; gap: 10px; }
/* 14 · la citation : plus large, un peu plus petite, italique, plus foncée */
.quote { max-width: 58ch; font-size: clamp(20px, 2.1vw, 32px); line-height: 1.5; font-style: italic; font-weight: 400; color: rgb(var(--ink-hi)); }

/* retours 14 : la Ligne dessine à nouveau son rail et sa lumière (ligne.js) */
/* le numéro des cartes vidéo en blanc : lisible même pendant la bascule */
.carte .carte-t i { color: rgb(var(--ink-hi)); }
/* la légende de la vidéo plein cadre du JT : posée sur un fond sombre, lisible quel que soit l'image dessous */
#corridorFull .cap { background: rgb(var(--bg) / 0.86); color: rgb(var(--ink-hi)); padding: 6px 12px; border-radius: 3px; }

/* ---- l'entrée d'acte (retours 11) : une scène typographique en 3D, pilotée par le défilement ----
   Le numéral géant recule dans la profondeur, le titre arrive de loin en se redressant, la Ligne
   se tire sous lui, la ligne d'accroche suit. Rien à charger : c'est du texte. */
.acte-pin { perspective: 1400px; perspective-origin: 30% 50%; }
.acte-pin > .acte-num { position: absolute; right: var(--gut); top: 50%; z-index: 0; font-family: var(--f-disp); font-weight: 600; font-size: clamp(220px, 44vw, 720px); line-height: 1; letter-spacing: -0.06em; color: transparent; -webkit-text-stroke: 3px rgb(var(--ink-lo) / 0.7); transform: translateY(-50%); pointer-events: none; user-select: none; }
.acte-trait { display: block; width: min(38vw, 520px); height: 2px; margin-top: 18px; background: linear-gradient(90deg, rgb(var(--accent)), rgb(var(--accent) / 0)); transform-origin: 0 50%; }
.acte-t { transform-style: preserve-3d; will-change: transform; }
@supports (animation-timeline: view()) {
  .acte-num { animation: acte-num linear both; animation-timeline: --acte; animation-range: entry 0% exit 100%; }
  .acte-t { animation-name: acte-entre; animation-range: entry 22% cover 42%; }
  .acte-trait { animation: acte-trait linear both; animation-timeline: --acte; animation-range: entry 40% cover 50%; }
}
@keyframes acte-entre { from { transform: translateZ(-900px) translateY(60px) rotateX(38deg); opacity: 0; filter: blur(8px); } 60% { opacity: 1; filter: blur(0); } to { transform: none; opacity: 1; filter: blur(0); } }
@keyframes acte-num { from { transform: translateY(-50%) translateZ(-300px) scale(1.35); opacity: 0.15; } 50% { opacity: 0.6; } to { transform: translateY(-50%) translateZ(120px) scale(0.92); opacity: 0.08; } }
@keyframes acte-trait { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (max-width: 860px) { .acte-num { font-size: 40vw; right: 16px; } .acte-trait { width: 52vw; } }
@media (prefers-reduced-motion: reduce) { .acte-pin > .acte-num, .acte-t, .acte-trait { animation: none !important; transform: none; } .acte-pin > .acte-num { transform: translateY(-50%); } }

/* ---- l'entrée dans un lieu (retours 11) : pendant les premiers 14 % du défilement de la scène, la caméra arrive
   (room.js / corridor.js), une vignette s'ouvre et un carton de titre se retire. Tout suit --sp (scenes.js). ---- */
.scene { --sp: 0; } /* scenes.js pose --sp sur la section ; ne pas la redéclarer sur le pin (elle masquerait l'héritage) */
.scene-pin::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; box-shadow: inset 0 0 22vw 12vw rgb(0 0 0 / 0.92); opacity: clamp(0, calc((0.16 - var(--sp)) / 0.16), 1); }
.scene-carte { position: absolute; left: calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); bottom: 14vh; z-index: 4; pointer-events: none; display: grid; gap: 10px; max-width: 52ch; color: #f4f4f0; text-shadow: 0 2px 24px rgb(0 0 0 / 0.7); opacity: clamp(0, calc((0.07 - var(--sp)) / 0.04), 1); transform: translateY(calc(var(--sp) * 140px)); filter: blur(calc(var(--sp) * 60px)); }
.scene-carte em.grand { font-family: var(--f-disp); font-style: normal; font-weight: 500; font-size: clamp(34px, 4.6vw, 76px); line-height: 1.02; letter-spacing: -0.025em; color: #f4f4f0; max-width: 14ch; }
.scene-carte span { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.4em; text-transform: uppercase; color: rgb(159 214 238); }
.scene-carte strong { font-family: var(--f-disp); font-weight: 500; font-size: clamp(44px, 7.4vw, 124px); line-height: 0.92; letter-spacing: -0.03em; }
.scene-carte em { font-family: var(--f-body); font-style: italic; font-weight: 300; font-size: clamp(17px, 1.5vw, 24px); color: rgb(235 238 244 / 0.85); }
.scene.no3d .scene-carte, .scene.no3d .scene-pin::after { display: none; }
@media (max-width: 860px) { .scene-carte, .scene-pin::after { display: none; } }
@media (prefers-reduced-motion: reduce) { .scene-carte { opacity: 0; } .scene-pin::after { opacity: 0; } }

/* retours 12 : plus d'invite « Clique une archive » ; les grands visuels pleine largeur tiennent dans l'écran */
.archives-contexte:empty { display: none; }
.clip.p-bleed { width: min(100%, calc(80vh * 16 / 9)); margin-left: auto; margin-right: auto; }

/* ============================================================
   RETOURS 14 (7 septembre 2026)
   ============================================================ */
/* 1 · la timeline Filmora tient dans l'écran */
.scrubbed { width: min(100%, calc(72vh * 1600 / 968)); margin-inline: auto; }
/* 2 · la plaquette : centrée dans son rail collant */
.book { margin-inline: auto; }
/* 3 · « Explorer intripid.fun » sous le cadre, à droite */
.browser + .cap { text-align: right; margin-top: 22px; }
/* 4 · le début du couloir JT : rien, ni carte ni voile */
#corridorScene:not([data-erreur]) .scene-pin::after { content: none; }
/* 5 · PSG, « la montée au Parc » : le mot géant entre par les côtés, les projecteurs bleu et rouge
   s'allument, le téléphone arrive vite, puis tout s'efface derrière la vidéo (transformations et opacité) */
.psg-mot { position: absolute; inset: 0; z-index: 0; display: grid; align-content: center; overflow: hidden; pointer-events: none; }
.psg-mot span { display: block; font-family: var(--f-disp); font-weight: 600; font-size: clamp(80px, 12.5vw, 220px); line-height: 0.9; letter-spacing: -0.04em; text-transform: uppercase; white-space: nowrap; color: transparent; -webkit-text-stroke: 2px rgb(var(--ink-lo) / 0.75); opacity: calc(1 - var(--psg-voile, 0)); }
.psg-mot span:first-child { justify-self: start; padding-left: calc(var(--track-x) + 2vw); transform: translateX(calc((1 - var(--psg-mot, 0)) * -70vw)); }
.psg-mot span:last-child { justify-self: end; padding-right: 5vw; transform: translateX(calc((1 - var(--psg-mot, 0)) * 70vw)); }
.psg-lum { position: absolute; left: 50%; top: 50%; z-index: 0; width: 130vh; height: 130vh; border-radius: 50%; pointer-events: none; opacity: var(--psg-lum, 0); transform: translate(-50%, -50%) scale(calc(0.6 + 0.6 * var(--psg-lum, 0))); background: radial-gradient(circle at 34% 50%, rgb(28 76 176 / 0.6), transparent 42%), radial-gradient(circle at 66% 50%, rgb(214 32 56 / 0.46), transparent 42%); filter: blur(18px); }
.psg-boite { z-index: 1; }
@media (max-width: 860px) { .psg-mot span { font-size: 15vw; } .psg-mot span:first-child { padding-left: 16px; } }
@media (prefers-reduced-motion: reduce) { .psg-mot, .psg-lum { display: none; } }
/* 6 · UNDERGROUND respire et se dérègle : plus d'air, les planches penchent, les pièces se décalent,
   des étiquettes traînent et le kanji veille en fond */
#c07 { position: relative; }
#c07 > .stackset { position: relative; z-index: 1; }
#c07 .stackset { row-gap: clamp(72px, 16vh, 240px); }
.ug-folie { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.ug-folie::before { content: "地下"; position: absolute; right: -1vw; top: 7%; font-family: var(--f-disp), "Yu Gothic", "Hiragino Sans", "Noto Sans JP", sans-serif; font-weight: 700; font-size: clamp(180px, 28vw, 520px); line-height: 1; color: transparent; -webkit-text-stroke: 1.5px rgb(var(--ink-lo) / 0.22); transform: rotate(-8deg); }
.ug-folie span { position: absolute; left: var(--x); top: var(--y); transform: rotate(var(--r, 0deg)); transform-origin: 0 0; font-family: var(--f-mono); font-size: clamp(11px, 0.95vw, 14px); letter-spacing: 0.42em; text-transform: uppercase; white-space: nowrap; color: rgb(var(--ink-lo) / 0.7); border: 1px solid rgb(var(--ink-lo) / 0.38); padding: 7px 14px; }
@media (min-width: 861px) {
  #c07 .planche { height: min(70vh, 720px); gap: clamp(30px, 4.5vw, 84px); padding: 5vh 3vw 9vh; align-items: center; }
  #c07 .case { box-shadow: 0 34px 90px rgb(0 0 0 / 0.6); }
  #c07 .case-cover { transform: rotate(-4.5deg) translateY(-3vh); }
  #c07 .case-sora { align-self: flex-start; transform: rotate(3.5deg) translateY(9vh); }
  #c07 .case-terrain { transform: rotate(-2deg) translateY(4vh); }
}
@media (max-width: 860px) { .ug-folie { display: none; } }

/* ============================================================
   RETOURS 15 (7 septembre 2026)
   ============================================================ */
/* 1 · l'accueil : noir, la Ligne naît, le compteur suit le chargement, puis « Bienvenue. » */
.boot-in { left: 0; right: 0; top: 0; bottom: 0; height: auto; background: none; animation: none; transform: none; }
.boot.gone .boot-in { animation: none; }
.boot-m { position: absolute; left: 50%; top: calc(50% - 120px); transform: translate(-50%, 14px); margin: 0; font-family: var(--f-disp); font-weight: 500; font-size: clamp(34px, 5vw, 84px); letter-spacing: -0.02em; color: rgb(var(--ink-hi)); opacity: 0; transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1), transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); white-space: nowrap; }
.boot.pret .boot-m { opacity: 1; transform: translate(-50%, 0); }
.boot.gone .boot-m { opacity: 0; transition-duration: 0.35s; }
#bootS { left: var(--gut); bottom: clamp(18px, 3vh, 34px); }
#bootP { position: absolute; right: var(--gut); bottom: clamp(18px, 3vh, 34px); font-family: var(--f-mono); font-size: clamp(14px, 1.4vw, 20px); letter-spacing: 0.2em; color: rgb(var(--ink-hi)); font-variant-numeric: tabular-nums; }
#bootP::after { content: " %"; color: rgb(var(--ink-lo)); }
.boot.gone #bootS, .boot.gone #bootP { opacity: 0; transition: opacity 0.25s; }
/* 2 · les archives : la seconde arrive quand la première a fini de se dérouler, reliée par un trait */
.archives { position: relative; }
html.js .archive + .archive { clip-path: inset(0 100% 0 0); opacity: 0.001; transition: clip-path 1.1s cubic-bezier(0.22, 1, 0.36, 1) 0.35s, opacity 0.2s 0.35s; }
html.js .archive + .archive.suite { clip-path: inset(0 0 0 0); opacity: 1; }
/* (retours 16 : plus de trait entre les deux archives) */
@media (max-width: 860px), (prefers-reduced-motion: reduce) { html.js .archive + .archive { clip-path: none; opacity: 1; transition: none; } .archives::after { content: none; } }
/* 3 · les souvenirs : les fragments s'effacent sur place, jamais coupés par les bords ; plus lisibles */
.fragment { opacity: var(--fo, 1); filter: brightness(var(--fb, 0.85)); }
/* 4 · le texte : pas de barre de lecture sur une enveloppe minuscule (un point, une virgule) */
.l.l-pt::after { content: none; }
/* 5 · PSG : le téléphone centré dans l'espace sous l'en-tête, jamais sous lui */
@media (min-width: 861px) {
  #psgClip { padding-top: 82px; box-sizing: border-box; align-items: center; }
  .psg-boite { height: calc(100vh - 82px - 14vh); } /* retours 21 : de la marge autour du téléphone au zoom maximal (7 vh en haut et en bas) */
}

/* ============================================================
   RETOURS 16 (7 septembre 2026)
   ============================================================ */
/* la fin du chapitre JT descend : plus d'air entre la timeline du montage et les blocs qui suivent */
.ch[data-ch="04"] .p-wide + .voice { margin-top: clamp(60px, 14vh, 200px); }

/* ============================================================
   RETOURS 17 (8 septembre 2026) — la mise en page respire
   Un seul rythme vertical entre les modules, les sections plus espacées, les médias larges au centre,
   la colonne de droite en escalier, des paragraphes un peu plus larges, les boutons « Voir… » qui
   ferment la scène d'avant tenus par un filet, les deux archives rééquilibrées.
   ============================================================ */
:root { --stack: clamp(88px, 13vh, 190px); --rythme: clamp(60px, 9.5vh, 140px); }
.stackset { row-gap: var(--rythme); }
.copy { max-width: 50ch; }
.voice { max-width: 50ch; }
@media (min-width: 861px) {
  /* la page se lit en escalier : la colonne de droite démarre plus bas que celle de gauche */
  .stackset > .p-left + .p-tail, .stackset > .p-narrow + .p-tail { margin-top: clamp(28px, 5vh, 72px); }
  /* les médias larges au centre, mêmes marges des deux côtés */
  .p-wide { grid-column: 2 / 12; }
  /* un bouton « Voir… » en tête de section ferme la scène d'avant : toute la largeur, un filet dessous */
  .stackset > p.p-narrow:first-child:has(> .cta) { grid-column: 1 / -1; padding-bottom: 22px; border-bottom: 1px solid rgb(var(--rule) / var(--rule-a)); }
  .stackset > p.p-narrow:first-child:has(> .cta) + .p-tail { margin-top: 0; }
  /* les archives : le bandeau YouTube sur toute la largeur, la capture du direct centrée dessous */
  .archives { row-gap: clamp(40px, 6vh, 80px); }
}
/* la légende du PSG garde un fond sombre quel que soit l'écran : le banc l'a mesurée à 1,5:1 sur les tribunes dorées */
#psgCap { background: rgb(0 0 0 / 0.82); padding: 9px 14px; color: rgb(var(--ink-hi)); }

/* ============================================================
   RETOURS 18 (8 septembre 2026)
   ============================================================ */
/* 1 · plus de contraste dans les textes : première ligne plus grande, accents gras, voix italique plus grande avec ses accents en romain gras */
.copy .hi { font-weight: 600; font-size: 1.05em; }
.voice { font-size: clamp(19px, 1.5vw, 25px); font-weight: 400; color: rgb(var(--ink-hi)); max-width: 50ch; } /* retours 26 : un peu plus petite */
.voice strong { font-weight: 700; color: rgb(var(--ink-hi)); }
.voice .hi { font-style: normal; font-weight: 700; font-size: 1.06em; color: rgb(var(--accent)); }
/* 2 · les cartels des archives et de la galerie : en blanc, titres gras */
.archive .cartel, .wall-item .cartel { color: rgb(var(--ink-hi)); }
.archive .cartel b, .wall-item .cartel b { color: rgb(var(--ink-hi)); font-weight: 700; font-size: calc(var(--t-mono) * 1.25); letter-spacing: 0.18em; }
/* 3 · MONTAGE aligné sur la timeline : le conteneur prend la largeur de l'image */
.ch[data-ch="04"] .p-wide { grid-column: 1 / 12; width: min(100%, calc(72vh * 1600 / 968)); margin-inline: clamp(20px, 3vw, 48px) auto; } /* retours 25 : la timeline à gauche, avec un léger retrait */
.ch[data-ch="04"] .scrubbed { width: 100%; }
/* 4 · l'écosystème : les étiquettes de modules plus voyantes ; le point atteint par le trait est plein */
#c05 .lab[data-branch] { color: rgb(var(--ink-hi)); font-size: calc(var(--t-mono) * 1.35); font-weight: 600; letter-spacing: 0.32em; }
.branch circle { r: 3.5; }
/* 5 · les boutons « Voir… » plus présents */
.cta { font-size: calc(var(--t-mono) * 1.2); font-weight: 600; }
/* 6 · « Explorer intripid.fun » sous le cadre du site, calé sur sa largeur */
.browser + .cap { max-width: 820px; margin-inline: auto; }
@media (min-width: 861px) {
  /* 7 · les colonnes de droite viennent vers la gauche ; les voix seules encore plus */
  .p-tail { grid-column: 7 / 13; }
  #c05 .voice.p-tail, .ch[data-ch="06"] .voice.p-tail { grid-column: 4 / 11; }
}

/* ============================================================
   RETOURS 19 (8 septembre 2026)
   ============================================================ */
/* 1 · carrousels : un peu plus d'air entre le média et les flèches */
.social-ctl { margin-top: 28px; }
/* 2 · Évian collé à gauche */
.ch[data-ch="06"] .clip.p-wide { grid-column: 1 / 11; }
/* 3 · UNDERGROUND : le texte démarre nettement plus bas que le titre, l'étiquette sans cadre, le texte des gammes à gauche */
@media (min-width: 861px) {
  #c07 h2.p-left + .copy.p-tail { margin-top: clamp(260px, 60vh, 640px); } /* retours 34 : le texte arrive bien après le titre, on défile pour le découvrir */
  #c07 .voice.p-inset { grid-column: 1 / 7; }
}
.ug-folie span { border: 0; padding: 0; }
/* 4 · aujourd'hui : les deux textes rapprochés */
#c09 .copy + .voice { margin-top: calc(-1 * var(--rythme) + 44px); }
/* 5 · les cinq vidéos du présent : une mosaïque nette, toutes visibles, chacune entre en fondu */
.fragments-stage { height: auto; }
.fragments-pin { position: static; height: auto; overflow: visible; perspective: none; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-auto-rows: auto; gap: clamp(10px, 1.2vw, 18px); }
/* (les cinq vidéos sont toutes en 16/9 une fois leur vrai format connu : une grande, puis deux rangées de deux) */
.fragment { position: static; width: auto; margin: 0; transform: none; filter: none; opacity: 1; aspect-ratio: var(--fa, 16 / 9); grid-column: span 3; background: #000; }
.fragment:first-child { grid-column: span 6; }
.fragment video { width: 100%; height: 100%; object-fit: cover; display: block; }
@supports (animation-timeline: view()) {
  .fragment { animation: fragment-entre linear both; animation-timeline: view(); animation-range: entry 0% entry 55%; }
}
@keyframes fragment-entre { from { opacity: 0.3; transform: translateY(24px) scale(0.985); } to { opacity: 1; transform: none; } }
@media (max-width: 860px) { .fragments-pin { grid-template-columns: 1fr; } .fragment, .fragment:first-child { grid-column: auto; aspect-ratio: var(--fa, 16 / 9); width: auto !important; } }
@media (prefers-reduced-motion: reduce) { .fragment { animation: none; } }
/* les flèches passent au-dessus de la scène (elle est positionnée : sans cela elle interceptait les clics — vu au banc de capture) */
.social-ctl, .supports-ctl { position: relative; z-index: 3; }

/* ============================================================
   RETOURS 20 (8 septembre 2026) — le numéro d'acte se dessine
   Le chiffre est un contour SVG : le trait se trace au défilement (dasharray), une tête lumineuse
   court le long du contour comme un fluide qui crée le chiffre, puis s'éteint quand il est complet.
   ============================================================ */
.acte-pin > .acte-num { width: clamp(220px, 40vw, 680px); height: auto; overflow: visible; font-size: 0; -webkit-text-stroke: 0; }
.acte-num text { font-family: var(--f-disp); font-weight: 600; font-size: 760px; letter-spacing: -0.06em; fill: transparent; paint-order: stroke; }
.acte-num-t { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 3; stroke-linejoin: round; stroke-dasharray: 4200; stroke-dashoffset: 4200; }
.acte-num-h { stroke: rgb(var(--accent)); stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 110 4090; stroke-dashoffset: 4200; filter: drop-shadow(0 0 10px rgb(var(--accent) / 0.95)) drop-shadow(0 0 26px rgb(var(--accent) / 0.5)); }
@supports (animation-timeline: view()) {
  .acte-num-t { animation: acte-trace linear both; animation-timeline: --acte; animation-range: entry 5% cover 62%; }
  .acte-num-h { animation: acte-trace linear both, acte-tete linear both; animation-timeline: --acte, --acte; animation-range: entry 5% cover 62%, cover 58% cover 68%; }
}
@supports not (animation-timeline: view()) { .acte-num-t { stroke-dashoffset: 0; } .acte-num-h { display: none; } }
@keyframes acte-trace { from { stroke-dashoffset: 4200; } to { stroke-dashoffset: 0; } }
@keyframes acte-tete { from { opacity: 1; } to { opacity: 0; } }
@media (max-width: 860px) { .acte-pin > .acte-num { width: 42vw; right: 16px; } }
@media (prefers-reduced-motion: reduce) { .acte-num-t { animation: none; stroke-dashoffset: 0; } .acte-num-h { display: none; } }
/* retours 21 : de la folie dans la voix d'Évian — un fragment en display, gras, plus grand */
.voice .grand { font-family: var(--f-disp); font-style: italic; font-weight: 600; font-size: 1.4em; line-height: 1.02; color: rgb(var(--ink-hi)); letter-spacing: -0.01em; }
/* retours 22 : le chapitre 03 se lit petit à petit — les trois textes ont chacun leur rangée, très espacées,
   pour que le lecteur les découvre un par un au défilement (le second passe sous le premier, à droite) */
@media (min-width: 861px) {
  #c03 .stackset { row-gap: clamp(100px, 18vh, 240px); } /* 18 vh : chaque texte arrive séparément, et le lede entier reste dans le premier écran après un saut direct (banc) */
  #c03 .copy.p-tail { grid-column: 6 / 12; margin-top: 0; }
  #c03 .lede.p-inset { grid-column: 2 / 9; }
}
/* retours 27 : la voix sous la vidéo du ski (souvenirs) — plus fine, à gauche, un peu plus large */
@media (min-width: 861px) { #c08 .p-wide + .voice.p-tail { grid-column: 1 / 9; font-weight: 300; max-width: 58ch; margin-top: 0; } }
/* retours 28 : dans le corps courant aussi, un gras franc */
.copy strong { font-weight: 700; color: rgb(var(--ink-hi)); }

/* ============================================================
   RETOURS 32 (8 septembre 2026) — le kanji se dessine, en orange
   ============================================================ */
.ug-folie::before { content: none; }
.ug-kanji { position: absolute; right: -1vw; top: 7%; width: clamp(340px, 50vw, 940px); height: auto; overflow: visible; transform: rotate(-8deg); }
.ug-kanji text { font-family: var(--f-disp), "Yu Gothic", "Hiragino Sans", "Noto Sans JP", sans-serif; font-weight: 700; font-size: 520px; fill: transparent; paint-order: stroke; }
.ug-kanji-t { stroke: rgb(var(--accent) / 0.55); stroke-width: 2.5; stroke-linejoin: round; stroke-dasharray: 9000; stroke-dashoffset: 9000; }
.ug-kanji-h { stroke: rgb(var(--accent)); stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 140 8860; stroke-dashoffset: 9000; filter: drop-shadow(0 0 10px rgb(var(--accent) / 0.95)) drop-shadow(0 0 26px rgb(var(--accent) / 0.5)); }
@supports (animation-timeline: view()) {
  .ug-kanji-t { animation: kanji-trace linear both; animation-timeline: view(); animation-range: entry 0% cover 45%; }
  .ug-kanji-h { animation: kanji-trace linear both, acte-tete linear both; animation-timeline: view(), view(); animation-range: entry 0% cover 45%, cover 42% cover 50%; }
}
@supports not (animation-timeline: view()) { .ug-kanji-t { stroke-dashoffset: 0; } .ug-kanji-h { display: none; } }
@keyframes kanji-trace { from { stroke-dashoffset: 9000; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .ug-kanji-t { animation: none; stroke-dashoffset: 0; } .ug-kanji-h { display: none; } }
/* retours 33 : de la folie dans le corps courant aussi — gras franc, et un fragment en display italique plus grand */
.copy strong { font-weight: 700; color: rgb(var(--ink-hi)); }
.copy .grand { font-family: var(--f-disp); font-style: italic; font-weight: 600; font-size: 1.32em; line-height: 1.05; color: rgb(var(--ink-hi)); }

/* ============================================================
   RETOURS 35 (8 septembre 2026) — la planche UNDERGROUND entre en scène
   Trois cases posées côte à côte, légende sous chaque image ; au défilement la couverture arrive de la
   gauche, Sora monte du bas, le terrain vient de la droite, chacune se pose avec son inclinaison.
   ============================================================ */
@media (min-width: 861px) {
  #c07 .planche { height: auto; align-items: flex-end; padding: 4vh 2vw 6vh; gap: clamp(28px, 3.5vw, 64px); }
  #c07 .case { display: flex; flex-direction: column; overflow: visible; aspect-ratio: auto; height: auto; }
  #c07 .case picture { display: block; }
  #c07 .case-cover { flex: 0 0 auto; width: calc(min(58vh, 600px) / 1.414); }
  #c07 .case-cover img { width: 100%; height: auto; aspect-ratio: 1 / 1.414; }
  #c07 .case-sora { flex: 0 0 auto; width: calc(min(50vh, 520px) * 2 / 3); align-self: flex-end; }
  #c07 .case-sora img { width: 100%; height: auto; aspect-ratio: 2 / 3; }
  #c07 .case-terrain { flex: 1 1 auto; min-width: 0; align-self: flex-end; }
  #c07 .case-terrain img { width: 100%; height: auto; aspect-ratio: 3 / 2; }
  #c07 .case .tag { position: static; transform: none; padding: 10px 0 0; background: none; color: rgb(var(--ink)); }
  #c07 .case-k { top: auto; bottom: 100%; margin-bottom: 8px; }
  #c07 .case-cover { transform: rotate(-4.5deg) translateY(-2vh); }
  #c07 .case-sora { transform: rotate(3.5deg) translateY(2vh); }
  #c07 .case-terrain { transform: rotate(-2deg); }
  @supports (animation-timeline: view()) {
    #c07 .case { animation: case-g cubic-bezier(0.22, 1, 0.36, 1) both; animation-timeline: view(); animation-range: entry 0% entry 85%; }
    #c07 .case-sora { animation-name: case-b; }
    #c07 .case-terrain { animation-name: case-d; }
  }
}
@keyframes case-g { from { opacity: 0.3; transform: translateX(-18vw) rotate(-16deg) translateY(-2vh); } to { opacity: 1; transform: rotate(-4.5deg) translateY(-2vh); } }
@keyframes case-b { from { opacity: 0.3; transform: translateY(16vh) rotate(10deg); } to { opacity: 1; transform: rotate(3.5deg) translateY(2vh); } }
@keyframes case-d { from { opacity: 0.3; transform: translateX(16vw) rotate(7deg); } to { opacity: 1; transform: rotate(-2deg); } }
@media (prefers-reduced-motion: reduce) { #c07 .case { animation: none; } }
/* ============================================================
   RETOURS 36 (8 septembre 2026) — les maillots en vitrine
   Un peu plus haut dans l'écran ; une lumière chaude derrière, une étagère de verre sous les pièces,
   leur reflet dessous, et une lente rotation de présentation, comme un mannequin qui tourne en vitrine.
   ============================================================ */
@media (min-width: 861px) {
  .piece { top: 44%; }
  .pieces-pin::before { content: ""; position: absolute; left: 50%; top: 42%; width: 72vw; height: 78vh; transform: translate(-50%, -50%); background: radial-gradient(ellipse at center, rgb(var(--accent) / 0.16), rgb(var(--accent) / 0.05) 38%, transparent 64%); pointer-events: none; }
  .pieces-pin::after { content: ""; position: absolute; left: 18%; right: 18%; top: calc(44% + 31vh); height: 1px; background: linear-gradient(90deg, transparent, rgb(var(--ink-hi) / 0.35) 30%, rgb(var(--ink-hi) / 0.35) 70%, transparent); box-shadow: 0 1px 24px rgb(var(--accent) / 0.25); pointer-events: none; }
  .piece picture { display: block; perspective: 1400px; }
  .piece img { transform-origin: 50% 62%; animation: vitrine 9s ease-in-out infinite alternate; }
  .piece[data-i="1"] img { animation-delay: -3s; }
  .piece[data-i="2"] img { animation-delay: -6s; }
}
@keyframes vitrine { from { transform: rotateY(-9deg); } to { transform: rotateY(9deg); } }
@media (prefers-reduced-motion: reduce) { .piece img { animation: none; -webkit-box-reflect: none; } }
/* retours 37 : les cinq vidéos arrivent chacune de leur côté (la grande du haut, puis gauche/droite par paire)
   et se rejoignent à leur place dans la mosaïque */
@supports (animation-timeline: view()) {
  .fragment { animation-name: frag-haut; animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); animation-range: entry 0% entry 95%; }
  .fragment:nth-child(2), .fragment:nth-child(4) { animation-name: frag-gauche; }
  .fragment:nth-child(3), .fragment:nth-child(5) { animation-name: frag-droite; }
}
@keyframes frag-haut { from { opacity: 0.3; transform: translateY(-14vh) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes frag-gauche { from { opacity: 0.3; transform: translateX(-28vw) rotate(-3deg); } to { opacity: 1; transform: none; } }
@keyframes frag-droite { from { opacity: 0.3; transform: translateX(28vw) rotate(3deg); } to { opacity: 1; transform: none; } }
/* retours 38 : le profil se lit phrase par phrase — beaucoup plus d'air entre elles, la Ligne conduit le lecteur */
@media (min-width: 861px) { .profil-fil { row-gap: clamp(140px, 30vh, 360px); column-gap: clamp(14px, 1.8vw, 30px); } } /* (le raccourci gap mettait aussi 30 vh entre les colonnes : la grille explosait) */

/* ============================================================
   RETOURS 39 (8 septembre 2026) — la citation, et « Disponible dès septembre 2026 »
   ============================================================ */
/* la citation : large, en display, guillemets en accent, un gras et une italique dedans ; la signature juste dessous, tenue par un trait */
#c11 .quote { font-family: var(--f-disp); font-style: normal; font-weight: 500; font-size: clamp(28px, 3.6vw, 60px); line-height: 1.12; letter-spacing: -0.02em; max-width: 24ch; margin-block: 4vh 0; text-wrap: balance; }
#c11 .quote .guil { color: rgb(var(--accent)); font-weight: 600; }
#c11 .quote strong { font-weight: 700; color: rgb(var(--ink-hi)); }
#c11 .quote .mouche { font-family: var(--f-body); font-style: italic; font-weight: 300; color: rgb(var(--accent)); }
#c11 .signature { margin-top: calc(-1 * var(--rythme) + 34px); padding-top: 18px; position: relative; }
#c11 .signature::before { content: ""; position: absolute; left: 0; top: 0; width: 56px; height: 2px; background: rgb(var(--accent)); }
#c11 .signature .lab { font-family: var(--f-disp); font-weight: 600; font-size: clamp(16px, 1.3vw, 22px); letter-spacing: 0.02em; text-transform: none; color: rgb(var(--ink-hi)); }
#c11 .signature .cap { color: rgb(var(--ink-lo)); }
@media (min-width: 861px) { #c11 .quote, #c11 .signature { grid-column: 2 / 12; } }
/* « Disponible dès septembre 2026 » : plus grand ; « septembre » en italique, « 2026 » en accent avec un trait qui se tire après les lettres */
.profil-fil .phrase:nth-child(6) .disp { font-size: clamp(40px, 8.4vw, 150px); line-height: 0.94; padding-bottom: 0.14em; }
.phrase.dispo .mw { position: relative; }
.phrase.dispo .mw:nth-child(3) .c { font-style: italic; font-weight: 400; }
.phrase.dispo .mw:nth-child(4) .c { color: rgb(var(--accent)); font-weight: 700; }
.phrase.dispo .mw:nth-child(4)::after { content: ""; position: absolute; left: 0.04em; right: 0.04em; bottom: -0.04em; height: 0.07em; background: rgb(var(--accent)); transform: scaleX(0); transform-origin: 0 50%; }
.phrase.dispo.vu .mw:nth-child(4)::after, .phrase.dispo .disp.vu ~ .mw:nth-child(4)::after { animation: dispo-trait 0.9s cubic-bezier(0.22, 1, 0.36, 1) 1.05s forwards; }
.phrase.dispo .lab { font-size: calc(var(--t-mono) * 1.2); color: rgb(var(--accent)); }
@keyframes dispo-trait { to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .phrase.dispo .mw:nth-child(4)::after { transform: none; animation: none; } }
/* « Disponible dès septembre 2026 » : la phrase sort de la colonne étroite du profil et prend la largeur de la page (étiquette à gauche, texte qui se replie sur deux lignes) */
@media (min-width: 861px) {
  .profil-fil .phrase.dispo { grid-column: 1 / -1; display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: clamp(16px, 2vw, 32px); align-items: start; margin-left: 0 !important; width: min(1180px, calc(100vw - var(--track-x) - clamp(30px, 5.5vw, 120px) - var(--gut) - clamp(28px, 4vw, 56px))); max-width: none; }
  .profil-fil .phrase.dispo .lab { padding-top: 0.55em; }
  .profil-fil .phrase:nth-child(6) .disp { font-size: clamp(38px, 7.4vw, 132px); }
}
/* retours 41 : la galerie se centre sous l'en-tête et aucune affiche ne dépasse en hauteur (Vinicius était coupé en haut) */
.wall-pin { padding-top: 82px; box-sizing: border-box; }
.wall-item { width: min(var(--w, 26vw), calc(100vh - 82px - 170px)); }
/* retours 42 : quand le chiffre (et le kanji) a fini de se construire, tout son contour passe à l'accent, avec un halo — on comprend qu'il est terminé */
@supports (animation-timeline: view()) {
  .acte-num-t { animation: acte-trace linear both, acte-fini linear both; animation-timeline: --acte, --acte; animation-range: entry 5% cover 62%, cover 60% cover 70%; }
  .ug-kanji-t { animation: kanji-trace linear both, kanji-fini linear both; animation-timeline: view(), view(); animation-range: entry 0% cover 45%, cover 44% cover 52%; }
}
@keyframes acte-fini { from { stroke: rgb(var(--ink-lo) / 0.8); filter: none; } to { stroke: rgb(var(--accent)); filter: drop-shadow(0 0 14px rgb(var(--accent) / 0.55)); } }
@keyframes kanji-fini { from { stroke: rgb(var(--accent) / 0.55); filter: none; } to { stroke: rgb(var(--accent)); filter: drop-shadow(0 0 14px rgb(var(--accent) / 0.5)); } }
@supports not (animation-timeline: view()) { .acte-num-t, .ug-kanji-t { stroke: rgb(var(--accent)); } }
@media (prefers-reduced-motion: reduce) { .acte-num-t, .ug-kanji-t { stroke: rgb(var(--accent)); } }
/* retours 46 : les étiquettes de modules de l'écosystème (Social, Vidéo, Supports, Commercial & web) — plus de mono espacé :
   le titre en display, en grand, bas de casse, posé au bout de sa branche */
#c05 .lab[data-branch] { font-family: var(--f-disp); font-weight: 600; font-size: clamp(26px, 3.2vw, 52px); line-height: 1; letter-spacing: -0.02em; text-transform: none; color: rgb(var(--ink-hi)); margin-bottom: clamp(34px, 5.2vh, 68px); } /* retours 48 : un peu plus d'air sous l'étiquette */
/* ============================================================
   RETOURS 47 (8 septembre 2026) — le carrousel social : une lumière au fond, et les logos Instagram et LinkedIn
   qui se dessinent puis s'allument, comme les chiffres d'acte
   ============================================================ */
.social-stage::before { content: ""; position: absolute; left: 50%; top: 50%; width: 80%; height: 90%; transform: translate(-50%, -50%); background: radial-gradient(ellipse at center, rgb(var(--accent) / 0.14), rgb(var(--accent) / 0.04) 40%, transparent 68%); pointer-events: none; z-index: 0; }
.social-icone { position: absolute; top: 14px; width: clamp(34px, 3.2vw, 52px); height: auto; overflow: visible; fill: none; stroke: rgb(var(--accent)); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; z-index: 7; pointer-events: none; }
.social-icone--ig { left: 14px; }
.social-icone--in { right: 14px; }
.social-icone rect, .social-icone circle, .social-icone path { stroke-dasharray: 80; stroke-dashoffset: 80; }
@supports (animation-timeline: view()) {
  .social-icone rect, .social-icone circle, .social-icone path { animation: icone-trace linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; }
  .social-icone { animation: icone-fini linear both; animation-timeline: view(); animation-range: entry 100% cover 30%; }
}
@supports not (animation-timeline: view()) { .social-icone rect, .social-icone circle, .social-icone path { stroke-dashoffset: 0; } .social-icone { filter: drop-shadow(0 0 8px rgb(var(--accent) / 0.8)); } }
@keyframes icone-trace { from { stroke-dashoffset: 80; } to { stroke-dashoffset: 0; } }
@keyframes icone-fini { from { filter: none; opacity: 0.8; } to { filter: drop-shadow(0 0 8px rgb(var(--accent) / 0.9)) drop-shadow(0 0 18px rgb(var(--accent) / 0.5)); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .social-icone rect, .social-icone circle, .social-icone path { animation: none; stroke-dashoffset: 0; } .social-icone { animation: none; } }
@media (max-width: 860px) { .social-icone { display: none; } }
/* retours 49 : « Transformer des événements » — le paragraphe démarre bien sous le titre, on défile pour le découvrir */
@media (min-width: 861px) { #c06 h2.p-left + .copy.p-tail { margin-top: clamp(200px, 45vh, 480px); } }
/* retours 51 : les maillots comme avant — on garde seulement la lumière orange derrière ; et la scène des pièces
   déborde jusqu'aux bords de l'écran pour que les maillots soient centrés au centre du site (le chapitre a plus
   de marge à gauche qu'à droite) */
@media (min-width: 861px) {
  .piece { top: 50%; }
  .pieces-pin::after { content: none; }
  .piece img { -webkit-box-reflect: none; animation: none; transform: none; }
  .pieces-pin { margin-left: calc(-1 * (var(--track-x) + clamp(30px, 5.5vw, 120px))); margin-right: calc(-1 * var(--gut)); }
  .pieces-pin::before { top: 50%; }
}
/* retours 53 : dès que le chiffre (ou le kanji) a fini de se tracer, il bascule franchement dans sa couleur d'acte —
   la couleur suit exactement la même plage que le tracé (grise jusqu'à 90 %, puis accent, trait plus épais, halo) */
@supports (animation-timeline: view()) {
  .acte-num-t { animation: acte-trace linear both, acte-fini2 linear both; animation-timeline: --acte, --acte; animation-range: entry 5% cover 62%, entry 5% cover 62%; }
  .ug-kanji-t { animation: kanji-trace linear both, kanji-fini2 linear both; animation-timeline: view(), view(); animation-range: entry 0% cover 45%, entry 0% cover 45%; }
}
@keyframes acte-fini2 { 0%, 88% { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 3; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 4.5; filter: drop-shadow(0 0 16px rgb(var(--accent) / 0.7)); } }
@keyframes kanji-fini2 { 0%, 88% { stroke: rgb(var(--accent) / 0.55); stroke-width: 2.5; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 4; filter: drop-shadow(0 0 16px rgb(var(--accent) / 0.65)); } }
/* retours 53 (suite) : le chiffre ne s'efface plus en reculant — une fois bleu, il reste bien visible */
@keyframes acte-num { from { transform: translateY(-50%) translateZ(-300px) scale(1.35); opacity: 0.25; } 50% { opacity: 0.8; } to { transform: translateY(-50%) translateZ(120px) scale(0.92); opacity: 0.95; } }
/* retours 55 : la voix de fin du JT, un peu plus large */
@media (min-width: 861px) { .ch[data-ch="04"] .voice.p-left { grid-column: 1 / 9; max-width: 60ch; } }
/* ============================================================
   RETOURS 57 (8 septembre 2026) — le carrousel social, le même délire que le kanji : les logos Instagram et
   LinkedIn en très grand, penchés, en contour blanc sur les côtés (derrière les téléphones), des hashtags en
   contour, le compte en mono, un cœur accent qui bat
   ============================================================ */
@media (min-width: 861px) {
  .social-icone { width: clamp(200px, 26vw, 420px); top: auto; z-index: 0; stroke: rgb(var(--ink-hi) / 0.85); stroke-width: 0.9; }
  .social-icone--ig { left: -5vw; top: -4vh; transform: rotate(-12deg); }
  .social-icone--in { right: -7vw; bottom: -6vh; transform: rotate(9deg); }
  .social-icone rect, .social-icone circle, .social-icone path { stroke-dasharray: 90; stroke-dashoffset: 90; }
}
@keyframes icone-fini { from { filter: none; opacity: 0.8; } to { filter: drop-shadow(0 0 10px rgb(var(--ink-hi) / 0.55)) drop-shadow(0 0 24px rgb(var(--ink-hi) / 0.25)); opacity: 1; } }
.social-tag { position: absolute; left: var(--x); top: var(--y); transform: rotate(var(--r, 0deg)); z-index: 0; pointer-events: none; white-space: nowrap; font-family: var(--f-disp); font-weight: 600; font-size: clamp(24px, 2.8vw, 48px); letter-spacing: -0.01em; color: transparent; -webkit-text-stroke: 1px rgb(var(--ink-hi) / 0.7); }
.social-tag.plein { font-family: var(--f-mono); font-weight: 500; font-size: clamp(12px, 1.1vw, 16px); letter-spacing: 0.3em; text-transform: uppercase; color: rgb(var(--ink-hi) / 0.8); -webkit-text-stroke: 0; }
.social-tag.coeur { font-family: "Segoe UI Symbol", "Apple Symbols", sans-serif; font-size: clamp(44px, 5.4vw, 96px); color: rgb(var(--accent)); -webkit-text-stroke: 0; filter: drop-shadow(0 0 14px rgb(var(--accent) / 0.6)); }
@supports (animation-timeline: view()) {
  .social-tag { animation: tag-entre linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; }
}
@keyframes tag-entre { from { opacity: 0.3; translate: 0 18px; } to { opacity: 1; translate: 0 0; } }
@media (prefers-reduced-motion: no-preference) { .social-tag.coeur { animation: coeur-bat 2.4s ease-in-out infinite; } }
@keyframes coeur-bat { 0%, 100% { scale: 1; } 12% { scale: 1.16; } 24% { scale: 1; } 36% { scale: 1.1; } }
@media (max-width: 860px) { .social-tag { display: none; } }
/* retours 59 : souvenirs — le premier texte à gauche, puis la voix seule, plus bas et vers le centre : on sait où regarder */
@media (min-width: 861px) { #c08 .copy.p-left + .voice.p-tail { grid-column: 6 / 12; margin-top: clamp(80px, 16vh, 200px); } }
/* retours 61 : la voix d'« Aujourd'hui » légèrement plus grande ; « filmer » redevient un accent simple */
#c09 .voice { font-size: clamp(20px, 1.65vw, 27px); }
/* retours 62 : le bon timing — les vidéos ont fini de se rejoindre dès qu'elles sont à moitié entrées, pas à la fin */
@supports (animation-timeline: view()) { .fragment { animation-range: entry 0% entry 55%; } }
/* ============================================================
   RETOURS 64 (8 septembre 2026) — la bobine : les infos du profil défilent de droite à gauche sur une bande
   de film sombre, perforée en haut et en bas, sur toute la largeur de l'écran
   ============================================================ */
.profil-fil .phrase:has(> .bobine) { grid-column: 1 / -1 !important; margin-left: 0 !important; max-width: none; }
.bobine { position: relative; overflow: hidden; background: rgb(var(--ink-hi)); color: rgb(var(--bg)); padding: 30px 0; width: 100vw; margin-left: calc(-1 * (var(--track-x) + clamp(30px, 5.5vw, 120px))); box-shadow: 0 18px 60px rgb(0 0 0 / 0.18); }
.bobine::before, .bobine::after { content: ""; position: absolute; left: 0; right: 0; height: 9px; background: repeating-linear-gradient(90deg, rgb(var(--bg) / 0.92) 0 14px, transparent 14px 32px); pointer-events: none; }
.bobine::before { top: 9px; } .bobine::after { bottom: 9px; }
.bobine-piste { display: flex; width: max-content; will-change: transform; animation: bobine 34s linear infinite; }
.bobine-piste:hover { animation-play-state: paused; }
.bobine .facts { display: flex; flex-wrap: nowrap; gap: 0; margin: 0; padding: 0; }
.bobine .facts li { flex: 0 0 auto; padding: 0 clamp(26px, 3.6vw, 64px); font-family: var(--f-mono); font-size: calc(var(--t-mono) * 1.35); letter-spacing: 0.26em; text-transform: uppercase; color: rgb(var(--bg)); white-space: nowrap; }
.bobine .facts li::before { content: "◆"; display: inline-block; margin-right: 18px; color: rgb(var(--accent)); font-size: 0.7em; vertical-align: 0.1em; }
@keyframes bobine { from { transform: translateX(0); } to { transform: translateX(-33.3333%); } }
@media (prefers-reduced-motion: reduce) { .bobine-piste { animation: none; width: auto; } .bobine .facts[aria-hidden] { display: none; } .bobine .facts { flex-wrap: wrap; gap: 12px 0; } }
@media (max-width: 860px) { .bobine { margin-left: calc(-1 * (var(--track-x) + 24px + clamp(28px, 4vw, 56px))); } }
/* retours 65 : la citation — un seul texte, une belle phrase en italique fine qui prend toute la largeur, les guillemets seuls en accent */
#c11 .quote { grid-column: 1 / -1; max-width: none; font-family: var(--f-body); font-style: italic; font-weight: 300; font-size: clamp(28px, 3.7vw, 64px); line-height: 1.22; letter-spacing: -0.005em; text-wrap: balance; }
#c11 .quote strong { font-weight: inherit; color: inherit; }
#c11 .quote .mouche { font-family: inherit; font-weight: inherit; color: inherit; }
#c11 .quote .guil { font-family: var(--f-disp); font-style: normal; font-weight: 600; color: rgb(var(--accent)); }
@media (min-width: 861px) { #c11 .signature { grid-column: 1 / 8; } }
/* retours 66 : profil — la voix « Mon parcours » revient à l'écran (elle était poussée à x = 1785 par le cumul marge + colonne) ;
   Nyvox : « En 2020 » ne commence à s'écrire qu'après la fin de FORTNITE */
@media (min-width: 861px) {
  .profil-fil .phrase:nth-child(2) { grid-column: 5 / 12; margin-left: 0 !important; margin-top: 6vh; }
  .profil-fil .phrase:nth-child(2) .voice { max-width: 46ch; margin: 0; }
  #c01 .lede.p-narrow + .copy.p-tail { margin-top: clamp(90px, 16vh, 200px); }
}
/* retours 66 (suite) : la bobine (100vw) faisait exploser la grille du profil (pistes à 0, phrases de 1900 px) — les phrases ne
   contribuent plus leur largeur intrinsèque, la bobine déborde simplement de sa colonne */
.profil-fil > .phrase { min-width: 0; }
.profil-fil .phrase:has(> .bobine) { contain: inline-size; }
/* retours 67 : les deux scènes 3D partent du noir — un voile couleur de fond qui se lève sur les premiers 9 % du défilement de la scène */
.scene-pin::before { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; background: rgb(var(--bg)); opacity: clamp(0, calc((0.09 - var(--sp)) / 0.09), 1); }

/* ============================================================
   RETOURS 68 (8 septembre 2026) — l'amorce
   Noir. Un cercle de visée, sa croix, un rayon accent qui balaie le cadran au rythme du chargement, le chiffre
   qui claque à chaque tour (3, 2, 1), le grain et le tremblement d'un projecteur, puis « Bienvenue. » et les
   deux volets s'ouvrent. Le compteur et le nom restent en bas.
   ============================================================ */
.boot-in { animation: am-flicker 1.3s linear infinite; }
.amorce { position: absolute; left: 50%; top: 50%; width: min(62vh, 62vw); aspect-ratio: 1; transform: translate(-50%, -50%); animation: am-weave 0.42s steps(2) infinite; }
.amorce-svg { display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: rgb(var(--ink-lo) / 0.55); stroke-width: 1.5; }
.am-c1 { stroke: rgb(var(--ink-hi) / 0.5); }
.am-c2 { stroke: rgb(var(--ink-lo) / 0.45); stroke-dasharray: 4 9; }
.am-croix { stroke: rgb(var(--ink-hi) / 0.6); stroke-width: 2; }
.am-balayage { fill: rgb(var(--accent) / 0.16); stroke: none; }
.am-rayon { stroke: rgb(var(--accent)); stroke-width: 3; stroke-linecap: round; filter: drop-shadow(0 0 8px rgb(var(--accent) / 0.85)); }
.am-chiffre { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -54%); font-family: var(--f-disp); font-weight: 700; font-size: min(36vh, 36vw); line-height: 1; letter-spacing: -0.04em; color: rgb(var(--ink-hi)); }
.am-chiffre.pop { animation: am-pop 0.38s cubic-bezier(0.22, 1, 0.36, 1); }
.am-lab { position: absolute; top: -2.6em; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.32em; text-transform: uppercase; color: rgb(var(--ink-lo)); white-space: nowrap; }
.am-lab--hg { left: 0; } .am-lab--hd { right: 0; }
.amorce::after { content: ""; position: absolute; inset: -60vh -60vw; pointer-events: none; opacity: 0.1; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E"); animation: grainshift 0.5s steps(2) infinite; }
.boot-m { top: 50%; transform: translate(-50%, -50%) scale(0.94); }
.boot.pret .amorce { opacity: 0; transform: translate(-50%, -50%) scale(1.06); transition: opacity 0.32s, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.boot.pret .boot-m { opacity: 1; transform: translate(-50%, -50%) scale(1); }
@keyframes am-weave { 0% { margin-left: 0; margin-top: 0; } 50% { margin-left: 0.7px; margin-top: -0.4px; } 100% { margin-left: -0.5px; margin-top: 0.3px; } }
@keyframes am-pop { from { opacity: 0.2; transform: translate(-50%, -54%) scale(1.3); } to { opacity: 1; transform: translate(-50%, -54%) scale(1); } }
@keyframes am-flicker { 0%, 100% { opacity: 1; } 91% { opacity: 0.86; } 93% { opacity: 1; } 96% { opacity: 0.93; } }
@media (max-width: 860px) { .am-lab { top: -3em; } }

/* ============================================================
   RETOURS 69 (8 septembre 2026) — l'en-tête
   Un filet accent qui avance avec la lecture, un losange devant le nom, la disponibilité en pastille,
   les liens soulignés au survol et le lien de la section courante allumé.
   ============================================================ */
.bar::after { content: ""; position: absolute; left: 0; bottom: -1px; height: 2px; width: calc(var(--lu, 0) * 100%); background: linear-gradient(90deg, rgb(var(--accent) / 0.55), rgb(var(--accent))); pointer-events: none; }
.bar-mark { display: inline-flex; align-items: center; gap: 10px; }
.bar-mark::before { content: ""; width: 7px; height: 7px; background: rgb(var(--accent)); transform: rotate(45deg); flex: 0 0 auto; }
.bar .dispo { border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 2.4)); border-radius: 999px; padding: 7px 13px 7px 11px; color: rgb(var(--ink)); }
.bar-nav a { position: relative; }
.bar-nav a::after { content: ""; position: absolute; left: 6px; right: 6px; bottom: 9px; height: 1px; background: rgb(var(--accent)); transform: scaleX(0); transform-origin: 0 50%; transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1); }
.bar-nav a:hover::after, .bar-nav a.ici::after { transform: scaleX(1); }
.bar-nav a.ici { color: rgb(var(--ink-hi)); }
/* retours 70 : les logos du carrousel plus petits, juste un bout qui dépasse sur les côtés ; le livre se centre sur l'écran par sa scène (plus par correction) */
@media (min-width: 861px) {
  .social-icone { width: clamp(150px, 17vw, 260px); }
  .social-icone--ig { left: -8vw; top: 2vh; }
  .social-icone--in { right: -9vw; bottom: 2vh; }
  .book-pin { margin-left: calc(-1 * (var(--track-x) + clamp(30px, 5.5vw, 120px))); margin-right: calc(-1 * var(--gut)); }
}
/* l'amorce s'efface nettement avant « Bienvenue. » (le tremblement est coupé pour laisser la transition jouer) */
.boot.pret .amorce { animation: none; }
.boot.pret .boot-m { transition-delay: 0.28s; }
/* retours 71 : le kanji, une fois construit, vit — une lumière blanche court sans fin le long du contour et le néon orange cligne par instants */
.ug-kanji-c { stroke: rgb(var(--ink-hi)); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 260 8740; stroke-dashoffset: 9000; opacity: 0; filter: drop-shadow(0 0 10px rgb(var(--accent))) drop-shadow(0 0 22px rgb(var(--accent) / 0.6)); }
@supports (animation-timeline: view()) {
  .ug-kanji-c { animation: kanji-courant 7s linear infinite, kanji-c-on linear both; animation-timeline: auto, view(); animation-range: normal, cover 45% cover 50%; }
  .ug-kanji-t { animation: kanji-trace linear both, kanji-fini2 linear both, kanji-neon 5.2s linear infinite; animation-timeline: view(), view(), auto; animation-range: entry 0% cover 45%, entry 0% cover 45%, normal; }
}
@keyframes kanji-courant { from { stroke-dashoffset: 9000; } to { stroke-dashoffset: 0; } }
@keyframes kanji-c-on { from { opacity: 0; } to { opacity: 0.95; } }
@keyframes kanji-neon { 0%, 6%, 8%, 60%, 63%, 100% { opacity: 1; } 7% { opacity: 0.72; } 61.5% { opacity: 0.6; } 62.5% { opacity: 0.9; } }
@media (prefers-reduced-motion: reduce) { .ug-kanji-c { display: none; } .ug-kanji-t { animation: none; } }
/* retours 72 : souvenirs — la voix plus proche du premier texte, et plus étirée */
@media (min-width: 861px) { #c08 .copy.p-left + .voice.p-tail { grid-column: 5 / 13; margin-top: clamp(16px, 3vh, 48px); max-width: 62ch; } }
/* retours 73 : la voix du ski, plus sobre — italique régulière, un seul accent */
@media (min-width: 861px) { #c08 .p-wide + .voice.p-tail { font-weight: 400; } }
/* retours 74 : Aujourd'hui — la voix ne commence à s'écrire qu'une fois le premier texte terminé (14 vh d'écart) */
#c09 .copy + .voice { margin-top: calc(-1 * var(--rythme) + 14vh); }
/* retours 75 : l'arrivée des cinq vidéos se joue dans le temps (0,9 s) au moment où on arrive dessus, quel que soit le navigateur —
   plus de dépendance à la timeline de défilement */
.fragment { animation: none !important; opacity: 0.3; transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.6s ease-out; }
.fragment:nth-child(1) { transform: translateY(-14vh) scale(0.96); }
.fragment:nth-child(2), .fragment:nth-child(4) { transform: translateX(-28vw) rotate(-3deg); }
.fragment:nth-child(3), .fragment:nth-child(5) { transform: translateX(28vw) rotate(3deg); }
.fragment.vu { opacity: 1; transform: none; }
.fragment:nth-child(2).vu, .fragment:nth-child(3).vu { transition-delay: 0.08s; }
.fragment:nth-child(4).vu, .fragment:nth-child(5).vu { transition-delay: 0.16s; }
@media (prefers-reduced-motion: reduce) { .fragment { opacity: 1; transform: none; transition: none; } }
/* retours 77 : l'amorce fluide — plus de tremblement ni de grain animé (repeints coûteux), plus de filtre sur le rayon qui tourne ;
   le rayon tourne en transformation CSS composée, avec un halo dessiné par un second trait */
.amorce { animation: none; }
.amorce::after { animation: none; opacity: 0.07; }
.am-rayon { filter: none; transform-box: view-box; transform-origin: 400px 400px; will-change: transform; stroke-width: 3.5; }
.am-chiffre { will-change: transform; }
/* retours 79 : le carrousel social, épuré — plus rien derrière les téléphones, juste une lueur blanche */
.social-icone, .social-tag { display: none !important; }
.social-stage::before { width: 86%; height: 96%; background: radial-gradient(ellipse at center, rgb(var(--ink-hi) / 0.18), rgb(var(--ink-hi) / 0.06) 38%, transparent 66%); }
/* retours 81 : le paragraphe UNDERGROUND légèrement vers la gauche (il déborde d'une colonne sur la gauche) */
@media (min-width: 861px) { #c07 h2.p-left + .copy.p-tail { margin-left: -16%; max-width: 54ch; } }
/* retours 82 : le cartouche « projet conceptuel » — un écusson : liseré cousu à l'intérieur, il se pose d'un bloc (pop) quand on arrive, pas de dévoilement du texte */
.status { position: relative; opacity: 0.3; transform: scale(0.92) rotate(-2deg); transform-origin: 40% 60%; transition: transform 0.75s cubic-bezier(0.34, 1.5, 0.64, 1), opacity 0.4s ease-out; }
.status.vu { opacity: 1; transform: none; }
.status::after { content: ""; position: absolute; inset: 7px; border: 1px dashed rgb(var(--ink-lo) / 0.45); pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .status { opacity: 1; transform: none; transition: none; } }
/* retours 83 : la voix des gammes, plus étirée */
@media (min-width: 861px) { #c07 .voice.p-inset { grid-column: 1 / 9; max-width: 62ch; } }
/* retours 84 : la voix d'« Aujourd'hui », plus grande */
#c09 .voice { font-size: clamp(22px, 1.95vw, 31px); max-width: 60ch; }
/* ============================================================
   RETOURS 85 (8 septembre 2026) — la bobine en haut, fine, toujours là
   ============================================================ */
.bobine-haut { position: fixed; left: 0; right: 0; top: 82px; height: 26px; z-index: 79; overflow: hidden; background: rgb(var(--ink-hi)); color: rgb(var(--bg)); pointer-events: none; }
.bobine-haut::before, .bobine-haut::after { content: ""; position: absolute; left: 0; right: 0; height: 3px; background: repeating-linear-gradient(90deg, rgb(var(--bg) / 0.85) 0 6px, transparent 6px 14px); }
.bobine-haut::before { top: 3px; } .bobine-haut::after { bottom: 3px; }
.bobine-haut .bobine-piste { display: flex; width: max-content; animation: bobine 46s linear infinite; }
.bobine-haut .facts { display: flex; flex-wrap: nowrap; gap: 0; margin: 0; padding: 0; }
.bobine-haut .facts li { flex: 0 0 auto; padding: 0 30px; line-height: 26px; font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.3em; text-transform: uppercase; color: rgb(var(--bg)); white-space: nowrap; }
.bobine-haut .facts li::before { content: "◆"; display: inline-block; margin-right: 14px; color: rgb(var(--accent)); font-size: 0.7em; vertical-align: 0.1em; }
html:has(.boot:not(.gone)) .bobine-haut { display: none; }
@media (prefers-reduced-motion: reduce) { .bobine-haut .bobine-piste { animation: none; } }
@media (max-width: 860px) { .bobine-haut { display: none; } }
/* la bobine du haut : 30 px, le texte bien entre les deux rangs de perforations */
.bobine-haut { height: 30px; }
.bobine-haut .facts li { line-height: 30px; }
.bobine-haut::before { top: 3px; } .bobine-haut::after { bottom: 3px; }
/* retours 86 : la citation — plus petite, sur deux lignes, décalée d'une colonne, dans une italique serif plus chaleureuse (Instrument Serif) */
#c11 .quote { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: clamp(30px, 3.15vw, 52px); line-height: 1.2; letter-spacing: 0; max-width: none; text-wrap: balance; }
#c11 .quote .guil { font-family: "Instrument Serif", Georgia, serif; font-style: italic; font-weight: 400; }
@media (min-width: 861px) { #c11 .quote { grid-column: 2 / 13; } #c11 .signature { grid-column: 2 / 8; } }
/* retours 87 : la bobine du haut en noir (couleur de fond de l'acte), texte et perforations clairs */
.bobine-haut { background: rgb(var(--bg)); color: rgb(var(--ink)); border-bottom: 1px solid rgb(var(--rule) / var(--rule-a)); }
.bobine-haut::before, .bobine-haut::after { background: repeating-linear-gradient(90deg, rgb(var(--ink-hi) / 0.55) 0 6px, transparent 6px 14px); }
.bobine-haut .facts li { color: rgb(var(--ink)); }
/* retours 91 : les chiffres d'acte, vraiment lumineux — comme le kanji : une fois tracés, une lumière court sans fin le long du contour
   (halo accent) et le néon cligne par instants */
.acte-num-c { stroke: rgb(var(--ink-hi)); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 200 4000; stroke-dashoffset: 4200; opacity: 0; filter: drop-shadow(0 0 10px rgb(var(--accent))) drop-shadow(0 0 24px rgb(var(--accent) / 0.6)); }
@supports (animation-timeline: view()) {
  .acte-num-c { animation: acte-courant 4.8s linear infinite, kanji-c-on linear both; animation-timeline: auto, --acte; animation-range: normal, cover 62% cover 68%; }
  .acte-num-t { animation: acte-trace linear both, acte-fini2 linear both, kanji-neon 5.2s linear infinite; animation-timeline: --acte, --acte, auto; animation-range: entry 5% cover 62%, entry 5% cover 62%, normal; }
}
@keyframes acte-courant { from { stroke-dashoffset: 4200; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .acte-num-c { display: none; } }
/* retours 92 : « Bienvenue. » et les mentions s'effacent avant l'ouverture des volets */
.boot.adieu .boot-m { opacity: 0 !important; transform: translate(-50%, -50%) scale(0.98) !important; transition: opacity 0.35s ease-out, transform 0.35s ease-out !important; }
.boot.adieu #bootS, .boot.adieu #bootP { opacity: 0; transition: opacity 0.3s; }
/* retours 93 : chapitre 03, second paragraphe légèrement plus grand, « j'ai fait mes preuves » un peu plus gros que le reste */
#c03 .copy.p-tail { font-size: calc(var(--t-body) * 1.08); }
#c03 .copy.p-tail strong { font-size: 1.12em; }
/* retours 94 : le paragraphe « Le JT m'a appris… » un peu plus grand */
.ch[data-ch="04"]:not(#c04) .copy.p-tail { font-size: calc(var(--t-body) * 1.1); max-width: 54ch; } /* seulement « Le JT m'a appris… », pas le paragraphe d'Inventer */
/* retours 98 : le premier texte d'« Aujourd'hui », plus grand */
#c09 .copy.p-left { font-size: calc(var(--t-body) * 1.18); max-width: 52ch; }
/* retours 99 : la mosaïque des cinq vidéos sans animation d'entrée — elles sont simplement là */
.fragment, .fragment:nth-child(n) { opacity: 1 !important; transform: none !important; transition: none !important; animation: none !important; }
/* retours 101 : le profil resserré pour le lecteur — moins d'air entre les phrases, « Ce que je cherche » et « Comment je travaille »
   côte à côte à la même hauteur, la voix « Mon parcours » juste sous la grande phrase */
@media (min-width: 861px) {
  .profil-fil { row-gap: clamp(56px, 11vh, 130px); }
  .profil-fil .phrase:nth-child(2) { margin-top: 0; }
  .profil-fil .phrase:nth-child(3) { grid-column: 1 / 6; }
  .profil-fil .phrase:nth-child(4) { grid-column: 7 / 13; margin-top: 0; margin-left: 0; }
  .profil-fil .phrase:nth-child(5) { margin-top: 0; }
}
/* retours 102 : « 2026 » roule comme un compteur (deux tours) et s'arrête chiffre après chiffre */
.phrase.dispo .roul { display: inline-block; height: 1em; overflow: hidden; vertical-align: bottom; line-height: 1; }
.phrase.dispo .bande { display: block; will-change: transform; transform: translateY(0); }
.phrase.dispo .bande i { display: block; height: 1em; line-height: 1; font-style: normal; }
.phrase.dispo.vu .bande, .phrase.dispo .disp.vu .bande { animation: rouler 1.7s cubic-bezier(0.1, 0.9, 0.2, 1) forwards; animation-delay: calc(0.55s + var(--k, 0) * 0.16s); }
@keyframes rouler { to { transform: translateY(calc(-1em * var(--n, 20))); } }
@media (prefers-reduced-motion: reduce) { .phrase.dispo .bande { animation: none; transform: translateY(calc(-1em * var(--n, 20))); } }
/* retours 103 : la citation arrive plus tard — « Disponible dès septembre 2026 » a le temps de sortir de l'écran — et elle est fixe, sans animation */
@media (min-width: 861px) { #c11 { padding-top: clamp(220px, 48vh, 560px); } }
/* ============================================================
   RETOURS 104 (8 septembre 2026) — la barre du haut, premium, dans la DA du site
   Plus de perforations : un bandeau fin et translucide (flou comme la barre), un filet, le micro-mono
   espacé de l'en-tête, les losanges accent, et un fondu sur les deux bords ; défilement lent.
   ============================================================ */
.bobine-haut { height: 28px; background: rgb(var(--bg) / 0.78); backdrop-filter: blur(12px); border-bottom: 1px solid rgb(var(--rule) / var(--rule-a)); -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent); }
.bobine-haut::before { top: 0; height: 1px; background: linear-gradient(90deg, transparent, rgb(var(--rule) / calc(var(--rule-a) * 1.6)) 20%, rgb(var(--rule) / calc(var(--rule-a) * 1.6)) 80%, transparent); }
.bobine-haut::after { display: none; }
.bobine-haut .bobine-piste { animation-duration: 64s; }
.bobine-haut .facts li { line-height: 28px; padding: 0 36px; font-size: 10px; letter-spacing: 0.34em; color: rgb(var(--ink-lo)); }
.bobine-haut .facts li::before { content: "◆"; margin-right: 16px; font-size: 0.6em; color: rgb(var(--accent)); opacity: 0.9; }
/* les losanges du bandeau : en ligne, sans le tiret absolu de la liste d'origine */
.bobine-haut .facts li::before { position: static; width: auto; height: auto; background: none; top: auto; left: auto; }
/* retours 105 : amorce fluide — plus de scintillement de l'ensemble (une animation d'opacité sur tout l'écran coûte cher sur une carte intégrée) */
.boot-in { animation: none !important; }
/* retours 106 : dans l'amorce, « Portfolio » au centre, en grand et en police fine ; plus d'écriture AMORCE ; le chiffre du compte, plus petit, en bas du cadran */
.am-portfolio { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -54%); margin: 0; font-family: var(--f-body); font-weight: 300; font-size: min(9.5vw, 13vh); line-height: 1; letter-spacing: 0.02em; color: rgb(var(--ink-hi)); white-space: nowrap; }
.am-chiffre { top: 78%; font-size: min(9vh, 9vw); transform: translate(-50%, -50%); }
.am-chiffre.pop { animation-name: am-pop2; }
@keyframes am-pop2 { from { opacity: 0.2; transform: translate(-50%, -50%) scale(1.3); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } }
.am-lab--hd { right: auto; left: 50%; transform: translateX(-50%); }
/* ============================================================
   RETOURS 107 (8 septembre 2026) — le hero un peu plus blanc, et la phrase qui revient en grand quand on le quitte (essai)
   ============================================================ */
.hero-line { color: rgb(var(--ink-hi) / 0.92); }
.hero-role { color: rgb(var(--ink-hi) / 0.72); }
.idee { position: relative; height: 170vh; }
.idee-pin { position: sticky; top: 0; height: 100vh; display: flex; align-items: center; padding: 0 var(--gut) 0 calc(var(--track-x) + clamp(30px, 5.5vw, 120px)); }
.idee-t { max-width: 18ch; font-family: var(--f-disp); font-weight: 500; font-size: clamp(36px, 5.4vw, 92px); line-height: 1.04; letter-spacing: -0.025em; color: rgb(var(--ink-hi)); text-wrap: balance; }
.idee-t em { font-family: var(--f-body); font-style: italic; font-weight: 300; letter-spacing: 0; }
@supports (animation-timeline: view()) {
  .idee-t { animation: idee-entre linear both; animation-timeline: view(); animation-range: entry 10% entry 70%; }
}
@keyframes idee-entre { from { opacity: 0.3; transform: translateY(6vh) scale(0.97); } to { opacity: 1; transform: none; } }
@media (max-width: 860px) { .idee { height: 130vh; } .idee-pin { padding-left: calc(var(--track-x) + 24px); padding-right: 22px; } }
@media (prefers-reduced-motion: reduce) { .idee { height: auto; } .idee-pin { position: static; height: auto; padding-block: 18vh; } .idee-t { animation: none; } }
/* retours 108 : les chiffres d'acte qui claquent — contour épais plein accent, double halo, opacité pleine une fois construits */
@keyframes acte-fini2 { 0%, 88% { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 3; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 6.5; filter: drop-shadow(0 0 14px rgb(var(--accent))) drop-shadow(0 0 40px rgb(var(--accent) / 0.7)); } }
@keyframes acte-num { from { transform: translateY(-50%) translateZ(-300px) scale(1.35); opacity: 0.35; } 50% { opacity: 0.9; } to { transform: translateY(-50%) translateZ(120px) scale(0.92); opacity: 1; } }
.acte-num-c { stroke-width: 8; }
/* retours 109 : premier paragraphe du chapitre 03 un peu plus grand */
#c03 .copy.p-left { font-size: calc(var(--t-body) * 1.08); }
/* retours 110 : second paragraphe du chapitre 03 encore un peu plus grand (×1,15), toujours sous la taille du lede */
#c03 .copy.p-tail { font-size: calc(var(--t-body) * 1.15); }
/* retours 108 (suite) : un cœur blanc dans le trait accent et un halo plus large — le chiffre claque vraiment */
@keyframes acte-fini2 { 0%, 88% { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 3; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 7; filter: drop-shadow(0 0 2px rgb(255 255 255 / 0.9)) drop-shadow(0 0 16px rgb(var(--accent))) drop-shadow(0 0 46px rgb(var(--accent) / 0.8)); } }
/* retours 112 : le lecteur vidéo — la grande carte tient entière dans l'écran (largeur bornée par la hauteur disponible, 9/16) */
@media (min-width: 861px) {
  .viewer-espace { grid-template-columns: minmax(200px, min(320px, calc((100vh - 176px) * 9 / 16))) 1fr; }
  .viewer-ecran video { display: block; width: 100%; height: auto; aspect-ratio: 9 / 16; object-fit: cover; }
}
/* retours 114 : la plaquette descend sous la barre et le bandeau, et tient entière dans l'écran avec un peu d'air (largeur bornée par la hauteur) */
@media (min-width: 861px) {
  .book-pin { top: calc(112px + 3vh); }
  .book { width: min(680px, 100%, calc((100vh - 112px - 3vh - 118px) * 1.414)); }
}
/* retours 116 : les deux textes d'« Aujourd'hui » encore plus grands */
#c09 .copy.p-left { font-size: calc(var(--t-body) * 1.32); max-width: 50ch; }
#c09 .voice { font-size: clamp(24px, 2.2vw, 35px); max-width: 58ch; }
/* retours 117 : la liste d'infos du profil est retirée (elle vit dans le bandeau du haut ; la source reste dans le DOM pour le clonage) */
.profil-fil .phrase:has(> .facts) { display: none; }
/* retours 118 : la grande phrase du profil — « chargé de communication » en accent, le reste en noir, la fin en italique */
.profil-fil .phrase:nth-child(1) .key { color: rgb(var(--accent)); }
.profil-fil .phrase:nth-child(1) .it { font-style: italic; color: inherit; }
/* retours 116 (suite) : la voix d'Aujourd'hui, taille forcée (une règle plus spécifique la rabaissait) */
#c09 .voice { font-size: clamp(24px, 2.2vw, 35px) !important; }
/* retours 119 : l'amorce — le chiffre seul au milieu comme avant, « Portfolio 2026 » écrit au-dessus du cadran, en police fine */
.am-chiffre { top: 50%; font-size: min(36vh, 36vw); transform: translate(-50%, -54%); }
.am-chiffre.pop { animation-name: am-pop; }
.am-portfolio { top: -1.1em; left: 50%; transform: translateX(-50%); font-size: clamp(22px, 2.6vw, 40px); font-weight: 300; letter-spacing: 0.08em; }
/* retours 120 : la phrase quitte le hero (elle revient en grand juste après) */
.hero-line { display: none; }
/* retours 121 : l'interlude — la phrase plus étirée (28 ch), un peu moins grosse, la chute en Instrument Serif italique */
.idee-t { max-width: 28ch; font-size: clamp(30px, 4.2vw, 72px); font-weight: 500; line-height: 1.08; letter-spacing: -0.02em; }
.idee-t em { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: 1.14em; letter-spacing: 0; color: rgb(var(--ink-hi)); }
/* retours 122 : plus d'arrêt après la phrase de l'interlude — la section n'est plus collante, elle défile avec le reste */
.idee { height: auto; }
.idee-pin { position: static; height: auto; min-height: 0; padding-top: 26vh; padding-bottom: 24vh; }
/* ============================================================
   RETOURS 123 (8 septembre 2026) — le chapitre 03, lisible et beau
   Trois temps, une seule taille de corps généreuse : le premier paragraphe à gauche, le second à droite un cran plus
   bas (jamais coupé : largeur bornée à sa colonne), puis le lede en grand, décalé, comme une conclusion.
   ============================================================ */
@media (min-width: 861px) {
  #c03 .stackset { row-gap: clamp(90px, 14vh, 190px); }
  #c03 .copy { font-size: calc(var(--t-body) * 1.24) !important; line-height: 1.58; max-width: min(46ch, 100%); }
  #c03 .copy.p-left { grid-column: 1 / 7; }
  #c03 .copy.p-tail { grid-column: 6 / 13; margin-top: 0; }
  #c03 .copy.p-tail strong { font-size: 1.1em; }
  #c03 .lede.p-inset { grid-column: 2 / 11; font-size: clamp(30px, 3.4vw, 56px); max-width: 24ch; line-height: 1.12; }
}
/* retours 124 : « Ce que je cherche » et « Comment je travaille » n'apparaissent qu'une fois « …manière de créer. » terminé */
@media (min-width: 861px) { .profil-fil .phrase:nth-child(3), .profil-fil .phrase:nth-child(4) { margin-top: clamp(70px, 13vh, 160px); } }
/* retours 126 : « Et maintenant — Disponible dès… » n'arrive qu'une fois les deux colonnes lues (40 vh d'air) */
@media (min-width: 861px) { .profil-fil .phrase.dispo { margin-top: clamp(200px, 40vh, 480px) !important; } }
/* retours 128 : le paragraphe d'« Inventer » (L'objectif était…) plus grand */
#c04 .copy.p-tail { font-size: calc(var(--t-body) * 1.2); max-width: min(48ch, 100%); line-height: 1.58; }

/* ============================================================
   RETOURS 131 (8 septembre 2026) — hero : plus d'air entre « Chargé de communication » et les boutons
   ============================================================ */
.hero-acts { margin-top: clamp(44px, 7.5vh, 80px); }

/* ============================================================
   RETOURS 132 (8 septembre 2026) — l'interlude en citation : guillemets suspendus hors du bloc,
   la phrase garde exactement ses lignes (le « pend à gauche, le » dépasse à droite)
   ============================================================ */
.idee-t::before { content: "« "; margin-left: -0.62em; white-space: pre; }
.idee-t em::after { content: " »"; margin-right: -1em; font-style: normal; white-space: pre; }
@media (max-width: 860px) { .idee-t::before { margin-left: 0; } .idee-t em::after { margin-right: 0; } }

/* ============================================================
   RETOURS 133–137 (8 septembre 2026)
   133 : la carte de la chambre dit « Au départ, il y avait un écran. » (plus de répétition avec le lede du 01)
   134 : chaque affiche du mur se cerne d'un contour lumineux qui avance, comme le kanji d'UNDERGROUND
   135 : les numéros d'acte — le trait final reste fin (3), seul l'éclat change ; lumière courante en proportion
   136 : le premier paragraphe du 03 se dévoile de nouveau ligne à ligne
   137 : « Le JT m'a appris… » plus gros, plus de folie (gras, accents, italique claire)
   ============================================================ */
@keyframes acte-fini2 { 0%, 88% { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 3; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 3; filter: drop-shadow(0 0 1px rgb(255 255 255 / 0.7)) drop-shadow(0 0 12px rgb(var(--accent))) drop-shadow(0 0 36px rgb(var(--accent) / 0.7)); } }
.acte-num-c { stroke-width: 4; }
.ch[data-ch="04"]:not(#c04) .copy.p-tail { font-size: calc(var(--t-body) * 1.34); max-width: 44ch; line-height: 1.4; }
.ch[data-ch="04"]:not(#c04) .copy.p-tail strong { font-weight: 700; color: rgb(var(--ink-hi)); }
.ch[data-ch="04"]:not(#c04) .copy.p-tail em { font-style: italic; color: rgb(var(--ink-hi)); }
.lum-wrap { position: relative; }
.wall-item .lum { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; transform: rotateY(var(--tx, 0deg)) rotateX(var(--ty, 0deg)); transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.wall-item:hover .lum { transition-duration: 0.12s; }
.wall-item .lum rect { fill: none; stroke-linejoin: round; stroke-linecap: round; }
.wall-item .lum-t { stroke: rgb(var(--accent)); stroke-width: 2; stroke-dasharray: 1000; stroke-dashoffset: calc((1 - var(--lt, 0)) * 1000px); opacity: min(1, var(--lt, 0) * 10); filter: drop-shadow(0 0 5px rgb(var(--accent) / 0.9)) drop-shadow(0 0 16px rgb(var(--accent) / 0.45)); }
.wall-item .lum-h { stroke: rgb(var(--ink-hi)); stroke-width: 3; stroke-dasharray: 36 964; stroke-dashoffset: calc((1 - var(--lt, 0)) * 1000px); opacity: calc(min(1, var(--lt, 0) * 10) * min(1, (1 - var(--lt, 0)) * 10)); filter: drop-shadow(0 0 6px rgb(var(--accent))) drop-shadow(0 0 18px rgb(var(--accent) / 0.7)); }
.wall-item .lum-c { stroke: rgb(var(--ink-hi)); stroke-width: 2.5; stroke-dasharray: 90 910; stroke-dashoffset: 1000px; opacity: calc(min(1, max(0, (var(--lt, 0) - 0.92) * 12)) * 0.9); filter: drop-shadow(0 0 6px rgb(var(--accent))) drop-shadow(0 0 16px rgb(var(--accent) / 0.6)); animation: lum-courant 5.5s linear infinite; animation-delay: calc(var(--li, 0) * -1.4s); }
@keyframes lum-courant { from { stroke-dashoffset: 1000px; } to { stroke-dashoffset: 0px; } }
@media (max-width: 860px) { .wall-item .lum { display: none; } }
@media (prefers-reduced-motion: reduce) { .wall-item { --lt: 1; } .wall-item .lum-c { display: none; } }

/* ============================================================
   RETOURS 139–140 (8 septembre 2026) — le titre UNDERGROUND sort du bloc : un escalier vers la droite,
   « UNDERGROUND : » plus grand, « de A à Z » en orange lumineux ; le paragraphe qui suit se dévoile et grandit
   ============================================================ */
#c07 h2.ug-h2 { max-width: none; position: relative; z-index: 1; }
.ug-h2 .ug-az { color: rgb(var(--accent)); text-shadow: 0 0 14px rgb(var(--accent) / 0.55), 0 0 36px rgb(var(--accent) / 0.3); }
@media (min-width: 861px) {
  #c07 h2.ug-h2 { grid-column: 1 / 13; }
  .ug-h2 .ug-l { display: block; }
  .ug-h2 .ug-l1 { font-size: 1.24em; letter-spacing: -0.03em; line-height: 1; }
  .ug-h2 .ug-l2 { margin-left: 15%; margin-top: 0.08em; }
  .ug-h2 .ug-l3 { margin-left: 36%; }
}
#c07 h2.p-left + .copy.p-tail { font-size: calc(var(--t-body) * 1.14); }
/* retours 139 (suite) : le kanji descend sous la dernière marche du titre, dans le vide avant le paragraphe */
@media (min-width: 861px) { .ug-kanji { top: 12.8%; } }
/* retours 142 : plus de folie dans les textes du 09 — gras et accents dans la voix italique aussi */
#c09 .copy strong, #c09 .voice strong { font-weight: 700; color: rgb(var(--ink-hi)); }
#c09 .copy em { font-style: italic; color: rgb(var(--ink-hi)); }
#c09 .voice .hi { font-weight: 700; }

/* ============================================================
   RETOURS 143–149 (8 septembre 2026)
   ============================================================ */
/* 143 : le lede du profil, refait — minuscules, « chargé de communication » en accent semi-gras, la chute en vrai italique
   Instrument Serif (la recette de l'interlude), plus de capitales ni d'italique synthétique */
.profil-fil .phrase:nth-child(1) .lede { max-width: 24ch; font-size: clamp(32px, 4.1vw, 68px); line-height: 1.06; letter-spacing: -0.02em; font-weight: 500; text-wrap: balance; }
.profil-fil .phrase:nth-child(1) .key { font-family: var(--f-disp); font-weight: 600; font-size: 1em; line-height: inherit; letter-spacing: -0.025em; text-transform: none; color: rgb(var(--accent)); }
.profil-fil .phrase:nth-child(1) .it { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: 1.14em; letter-spacing: 0; color: rgb(var(--ink-hi)); }
/* 144 : les colonnes — l'italique porte les intentions, un seul gras par colonne, qui atterrit en fin de phrase */
.profil-fil .phrase:nth-child(3) .copy em, .profil-fil .phrase:nth-child(4) .copy em { font-style: italic; color: rgb(var(--ink-hi)); }
/* 145 : « Disponible dès septembre 2026 » façon Lando Norris — chaque lettre monte d'un masque avec une légère rotation,
   en cascade, puis les chiffres roulent et le trait se tire */
.phrase.dispo .mw { overflow: clip; padding: 0.08em 0.05em 0.16em; margin: -0.08em -0.05em -0.16em; }
.phrase.dispo .c { transform: translateY(118%) rotate(5deg); transform-origin: 0% 100%; }
.phrase.dispo.vu .c, .phrase.dispo .disp.vu .c { animation: lando 1.25s cubic-bezier(0.16, 1, 0.3, 1) both; animation-delay: calc(var(--i, 0) * 0.028s); }
@keyframes lando { from { transform: translateY(118%) rotate(5deg); } to { transform: none; } }
.phrase.dispo .mw:nth-child(4)::after { bottom: 0.08em; }
.phrase.dispo.vu .bande, .phrase.dispo .disp.vu .bande { animation-delay: calc(1.15s + var(--k, 0) * 0.16s); }
.phrase.dispo.vu .mw:nth-child(4)::after, .phrase.dispo .disp.vu ~ .mw:nth-child(4)::after { animation-delay: 1.95s; }
@media (prefers-reduced-motion: reduce) { .phrase.dispo .c { transform: none; animation: none; } }
/* 146 : l'intro sans pourcentage ni mention en bas */
#bootS, #bootP { display: none; }
/* 147 : le hero — le nom monte en deux lignes masquées (légère rotation, long amorti), un éclat traverse les lettres,
   la fonction et les boutons suivent, un indice de défilement respire en bas */
#hero h1 .hl { display: block; overflow: clip; padding: 0.06em 0.06em 0.14em 0; margin: -0.06em -0.06em -0.14em 0; }
#hero h1 .hw { display: inline-block; transform-origin: 0% 100%; }
@media (prefers-reduced-motion: no-preference) {
  html.in .hero-txt > h1 { animation: none; clip-path: none; }
  #hero h1 .hw { transform: translateY(112%) rotate(3deg); }
  html.in #hero h1 .hw { animation: hero-nom 1.35s cubic-bezier(0.16, 1, 0.3, 1) both, hero-eclat 1.5s ease-in-out 1 both; animation-delay: calc(0.45s + var(--hl, 0) * 0.13s), calc(1.75s + var(--hl, 0) * 0.13s); background: linear-gradient(105deg, rgb(var(--ink-hi)) 0 40%, #fff 50%, rgb(var(--ink-hi)) 60% 100%); background-size: 280% 100%; background-position: 100% 0; -webkit-background-clip: text; background-clip: text; color: transparent; }
  #hero h1 .hl:nth-child(2) .hw { --hl: 1; }
  html.in .hero-txt > .hero-role { animation-delay: 1.15s; }
  html.in .hero-txt > .hero-acts { animation-delay: 1.3s; }
  html.in .hero-cred, html.in .hero-cue { animation: hero-fondu 1s ease-out both; }
  html.in .hero-cred { animation-delay: 1.7s; }
  html.in .hero-cue { animation-delay: 2s; }
}
@keyframes hero-nom { from { transform: translateY(112%) rotate(3deg); } to { transform: none; } }
@keyframes hero-eclat { from { background-position: 100% 0; } to { background-position: 0% 0; } }
@keyframes hero-fondu { from { opacity: 0; } to { opacity: 1; } }
.hero-cue { position: absolute; left: 50%; bottom: clamp(18px, 3.4vh, 30px); transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 10px; pointer-events: none; transition: opacity 0.4s; }
.hero-cue i { display: block; width: 1px; height: clamp(34px, 6vh, 56px); background: linear-gradient(rgb(var(--ink-hi) / 0) 0%, rgb(var(--ink-hi) / 0.9) 50%, rgb(var(--ink-hi) / 0) 100%); background-size: 100% 300%; animation: hero-cue-file 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
.hero-cue span { font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.32em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
.hero-cue.gone { opacity: 0; }
@keyframes hero-cue-file { from { background-position: 0 100%; } to { background-position: 0 -100%; } }
@media (max-width: 860px) { .hero-cue { display: none; } }
@media (prefers-reduced-motion: reduce) { .hero-cue i { animation: none; } }
/* 148 : le paragraphe Nyvox un peu plus gros */
#c01 .lede.p-narrow + .copy.p-tail { font-size: calc(var(--t-body) * 1.14); }
/* 149 : le contour des affiches — une animation en temps réel (1,7 s) lancée dès que l'affiche est à l'écran, --lt animé */
@property --lt { syntax: "<number>"; inherits: true; initial-value: 0; }
.wall-item.lum-on { animation: lum-t 1.7s cubic-bezier(0.5, 0, 0.15, 1) both; animation-delay: var(--ld, 0s); }
@keyframes lum-t { from { --lt: 0; } to { --lt: 1; } }
@media (prefers-reduced-motion: reduce) { .wall-item.lum-on { animation: none; --lt: 1; } }

/* ============================================================
   RETOURS 150–152 (8 septembre 2026)
   150 : « C'est là que mon rôle… » n'entre à l'écran qu'une fois « chargé de communication » entièrement dévoilé
   151 : le carrousel social (téléphone) plus petit — la bande du haut prend de la place, tout doit tenir dessous
   152 : le viewer vidéo (Concept POV…) plus petit, même raison
   ============================================================ */
@media (min-width: 861px) { #c03 .stackset .lede.p-inset { margin-top: clamp(260px, 48vh, 580px); } }
.social { --pw: min(210px, 26vh, 60vw); }
@media (min-width: 861px) { .viewer-espace { grid-template-columns: minmax(200px, min(320px, calc((100vh - 260px) * 9 / 16))) 1fr; } }
/* retours 153 : sous les quatre supports, seul le titre en capitales reste (plus de ligne en dessous) */
#supportLigne { display: none; }

/* ============================================================
   RETOURS 154–155 (8 septembre 2026)
   154 : le paragraphe « UNDERGROUND est né… » à gauche, un petit retrait, un peu plus étiré (moins bloc)
   155 : les légendes de la planche, plus courtes, tenues dans la case (marges intérieures, retour à la ligne propre)
   ============================================================ */
@media (min-width: 861px) { #c07 h2.p-left + .copy.p-tail { grid-column: 1 / 12; margin-left: clamp(24px, 4vw, 72px); max-width: 62ch; } }
#c07 .case .tag { padding: 10px 12px 12px; white-space: normal; overflow-wrap: anywhere; line-height: 1.4; }
/* retours 142 (correctif) : les paragraphes « Souvenirs » sont dans le chapitre 08 — mêmes gras, italiques et accents */
#c08 .copy strong, #c08 .voice strong { font-weight: 700; color: rgb(var(--ink-hi)); }
#c08 .copy em { font-style: italic; color: rgb(var(--ink-hi)); }
#c08 .voice .hi { font-weight: 700; }
/* retours 157 : « FORTNITE » plus gros dans le lede du 01 */
#c01 .lede .key { font-size: 1.7em; line-height: 0.95; }

/* ============================================================
   RETOURS 158–159 (8 septembre 2026)
   158 : le nom du hero — « Thibault » en Clash allégé, « Cachet » bien plus grand en Instrument Serif italique,
         décalé vers la droite comme une signature (même contraste que l'interlude et le profil)
   159 : le » de l'interlude n'apparaît qu'à la toute fin du dévoilement (il lit --p, la progression des lignes)
   ============================================================ */
#hero h1 { font-weight: 600; letter-spacing: -0.04em; line-height: 0.86; }
#hero h1 .hl { padding-left: 0.08em; margin-left: -0.08em; }
#hero h1 .hl:nth-child(2) { margin-left: calc(18% - 0.08em); margin-top: -0.1em; }
#hero h1 .hl:nth-child(2) .hw { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: 1.42em; line-height: 0.82; letter-spacing: -0.02em; }
@media (max-width: 860px) { #hero h1 .hl:nth-child(2) { margin-left: calc(6% - 0.08em); } #hero h1 .hl:nth-child(2) .hw { font-size: 1.28em; } }
.idee-t em::after { opacity: clamp(0, (var(--p, 1) - 0.93) * 15, 1); }
/* retours 161 : « C'est là que mon rôle… » remonte (plus de marge ajoutée, le rythme du chapitre suffit) */
@media (min-width: 861px) { #c03 .stackset .lede.p-inset { margin-top: 0; } }
/* retours 162 : « Le JT s'est arrêté… » se dévoile ligne à ligne comme les autres textes (cible du découpage) */
/* retours 162 (correctif) : les enveloppes de mots et de lignes du manifeste restent en ligne, seuls les trois spans de premier niveau sont des blocs */
.manifest .w, .manifest .l { display: inline; animation: none; }

/* retours 163 : « Les événements m'ont permis… » — plus gros, plus de folie (gras, italiques, accent), colonne tirée vers la gauche */
.copy.evts { font-size: calc(var(--t-body) * 1.3); line-height: 1.42; max-width: 56ch; }
.copy.evts strong { font-weight: 700; color: rgb(var(--ink-hi)); }
.copy.evts em { font-style: italic; color: rgb(var(--ink-hi)); }
@media (min-width: 861px) { .copy.p-tail.evts { grid-column: 3 / 13; } }
/* retours 164 : le paragraphe UNDERGROUND remonte (34 vh sous le titre) ; le kanji revient a droite du titre, plus petit et plus a droite ; escalier un peu resserre */
@media (min-width: 861px) {
  #c07 h2.p-left + .copy.p-tail { margin-top: clamp(180px, 34vh, 400px); }
  .ug-kanji { top: 5.5%; right: -6vw; width: clamp(300px, 42vw, 760px); }
  .ug-h2 .ug-l2 { margin-left: 12%; }
  .ug-h2 .ug-l3 { margin-left: 30%; }
}

/* retours 165 : le contour lumineux sur tout [data-lum] (la grande photo des maillots) — trait rentré de 1 px pour rester
   dans la boîte même sous le clip-path du dévoilement */
[data-lum] .lum { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 2; }
[data-lum] .lum rect { x: 1px; y: 1px; width: calc(100% - 2px); height: calc(100% - 2px); fill: none; stroke-linejoin: round; stroke-linecap: round; }
[data-lum] .lum-t { stroke: rgb(var(--accent)); stroke-width: 2; stroke-dasharray: 1000; stroke-dashoffset: calc((1 - var(--lt, 0)) * 1000px); opacity: min(1, var(--lt, 0) * 10); filter: drop-shadow(0 0 5px rgb(var(--accent) / 0.9)) drop-shadow(0 0 16px rgb(var(--accent) / 0.45)); }
[data-lum] .lum-h { stroke: rgb(var(--ink-hi)); stroke-width: 3; stroke-dasharray: 36 964; stroke-dashoffset: calc((1 - var(--lt, 0)) * 1000px); opacity: calc(min(1, var(--lt, 0) * 10) * min(1, (1 - var(--lt, 0)) * 10)); filter: drop-shadow(0 0 6px rgb(var(--accent))) drop-shadow(0 0 18px rgb(var(--accent) / 0.7)); }
[data-lum] .lum-c { stroke: rgb(var(--ink-hi)); stroke-width: 2.5; stroke-dasharray: 90 910; stroke-dashoffset: 1000px; opacity: calc(min(1, max(0, (var(--lt, 0) - 0.92) * 12)) * 0.9); filter: drop-shadow(0 0 6px rgb(var(--accent))) drop-shadow(0 0 16px rgb(var(--accent) / 0.6)); animation: lum-courant 5.5s linear infinite; animation-delay: calc(var(--li, 0) * -1.4s); }
[data-lum].lum-on .lum { animation: lum-t 1.7s cubic-bezier(0.5, 0, 0.15, 1) both; } /* sur le calque du trait : l'élément porte déjà son animation d'entrée */
@media (max-width: 860px) { [data-lum] .lum { display: none; } }
@media (prefers-reduced-motion: reduce) { [data-lum].lum-on .lum { animation: none; --lt: 1; } [data-lum] .lum-c { display: none; } }

/* retours 166 : chapitre 08 — une couleur, un noir, un mot plus gros par paragraphe ; l'accent n'est plus en gras dans la voix */
#c08 .voice .hi { font-weight: 600; }
#c08 .copy .grand, #c08 .voice .grand { color: rgb(var(--ink-hi)); }

/* retours 168 : le hero — le nom et la fonction montent en haut (la silhouette reste visible), les boutons descendent
   en bas à gauche, alignés sur « Saint-Jean-de-Luz » */
@media (min-width: 861px) {
  .hero-txt { top: calc(82px + 28px + 3vh); bottom: clamp(22px, 4vh, 34px); }
  .hero-role { margin-top: clamp(16px, 2.6vh, 26px); }
  .hero-acts { position: absolute; left: 0; bottom: 0; margin-top: 0; }
}
/* retours 168 (suite) : la fonction descend au-dessus des boutons (elle tombait sur les lumières de la ville), ombre légère */
@media (min-width: 861px) {
  .hero-role { position: absolute; left: 0; bottom: clamp(50px, 7.2vh, 66px); margin-top: 0; text-shadow: 0 1px 14px rgb(0 0 0 / 0.7); }
}

/* retours 171 : les numéros d'acte vraiment fins — tracé 1,2, trait final 1,4, tête 3, lumière courante 2,2 */
.acte-num-t { stroke-width: 1.2; }
.acte-num-h { stroke-width: 3; }
.acte-num-c { stroke-width: 2.2; }
@keyframes acte-fini2 { 0%, 88% { stroke: rgb(var(--ink-lo) / 0.8); stroke-width: 1.2; filter: none; } 100% { stroke: rgb(var(--accent)); stroke-width: 1.4; filter: drop-shadow(0 0 1px rgb(255 255 255 / 0.6)) drop-shadow(0 0 10px rgb(var(--accent))) drop-shadow(0 0 30px rgb(var(--accent) / 0.6)); } }

/* retours 172 : prénom et nom à la même hauteur, sur une seule ligne (base alignée), plus loin de la bande qui défile */
@media (min-width: 861px) {
  .hero-txt { top: calc(82px + 28px + 7vh); }
  #hero h1 { display: flex; align-items: baseline; gap: 0.22em; font-size: min(11.5vw, 21vh, 200px, calc((100vw - 240px) / 8.9)); }
  #hero h1 .hl:nth-child(2) { margin-left: -0.08em; margin-top: 0; }
}

/* ============================================================
   RETOURS 173–176 (8 septembre 2026)
   173 : la carte de la chambre — les mots montent d'un masque en cascade dès que la scène commence (--sp), l'étiquette fond
   175 : « En suivant beaucoup le sport… » plus gros
   176 : « C'est là que mon rôle… » façon Lando Norris — les mots de chaque ligne montent d'un masque au fil du défilement,
         précédés d'un gros trait d'accent qui balaie la ligne (variante 7)
   ============================================================ */
.scene-carte em.grand .mw { display: inline-block; overflow: clip; padding: 0.08em 0.03em 0.14em; margin: -0.08em -0.03em -0.14em; vertical-align: top; }
.scene-carte em.grand .c { display: inline-block; --a: clamp(0, 1 - (var(--sp, 0) - var(--k, 0) * 0.006) * 26, 1); transform: translateY(calc(var(--a) * 115%)) rotate(calc(var(--a) * 4deg)); transform-origin: 0% 100%; }
.scene-carte > span { opacity: clamp(0, var(--sp, 0) * 25, 1); }
@media (prefers-reduced-motion: reduce) { .scene-carte em.grand .c { transform: none; } .scene-carte > span { opacity: 1; } }
#c02 .copy.p-left { font-size: calc(var(--t-body) * 1.2); max-width: 50ch; }
@supports (animation-timeline: view()) {
  [data-rv="7"] .l { clip-path: inset(-0.12em -0.22em -0.06em -0.22em); }
  [data-rv="7"] .l .w { display: inline-block; transform: translateY(calc((1 - var(--r, 1)) * 112%)) rotate(calc((1 - var(--r, 1)) * 4deg)); transform-origin: 0% 100%; }
  [data-rv="7"] .l::after { width: 1.1em; top: -0.04em; bottom: -0.04em; margin-left: -1.1em; }
}
/* retours 177 : le nom centré sur l'écran (la ligne s'étend sur toute la largeur, puis se centre) */
@media (min-width: 861px) {
  #hero h1 { justify-content: center; margin-left: calc(-1 * (var(--track-x) + clamp(30px, 5.5vw, 120px))); margin-right: calc(-1 * var(--gut)); }
}
/* retours 178 : des lumières fines autour des deux archives (grille YouTube, direct) — même système, traits plus fins */
.archive-cadre .lum-t { stroke-width: 1.4; }
.archive-cadre .lum-h { stroke-width: 2.4; }
.archive-cadre .lum-c { stroke-width: 1.8; }
/* retours 179 : « À l'époque… » façon Lando aussi (variante 7) */
/* retours 180 : « L'objectif était de créer… » — même traitement que le paragraphe des événements (classe evts : ×1.3, colonne tirée vers la gauche) */
/* retours 181 : « Les événements m'ont permis… » remonte (plus de marge au-dessus) */
#c06 .copy.p-tail.evts { margin-top: 0; }

/* ============================================================
   RETOURS 178 (suite) à 185 (8 septembre 2026)
   ============================================================ */
/* 178 : les archives du 01 — l'accent du chapitre est gris, la lumière fine est donc blanche */
.archive-cadre .lum-t { stroke: rgb(var(--ink-hi) / 0.9); filter: drop-shadow(0 0 4px rgb(255 255 255 / 0.85)) drop-shadow(0 0 12px rgb(255 255 255 / 0.35)); }
.archive-cadre .lum-h { filter: drop-shadow(0 0 5px rgb(255 255 255)) drop-shadow(0 0 14px rgb(255 255 255 / 0.6)); }
.archive-cadre .lum-c { filter: drop-shadow(0 0 5px rgb(255 255 255 / 0.9)) drop-shadow(0 0 12px rgb(255 255 255 / 0.5)); }
/* 182 : « J'ai aussi appris à m'adapter… » collé plus à droite */
@media (min-width: 861px) { .ch[data-ch="06"] .voice.p-tail { grid-column: 6 / 12; } }
/* 183 : la lueur de « de A à Z » n'est plus coupée en rectangle par le masque de ligne (marges du masque élargies) */
@supports (animation-timeline: view()) {
  .ug-h2 .l { clip-path: inset(-0.6em calc((1 - var(--rl)) * 100% - 0.6em) -0.6em -0.6em); }
}
/* 184–185 : les mots « grands » du 08 restent dans la police du texte, simplement plus grands et plus appuyés */
#c08 .voice .grand { font-family: inherit; font-style: italic; font-weight: 600; font-size: 1.28em; letter-spacing: -0.01em; line-height: 1; }
#c08 .copy .grand { font-family: inherit; font-style: normal; font-weight: 700; font-size: 1.24em; letter-spacing: -0.01em; line-height: 1; }

/* ============================================================
   RETOURS 186 (8 septembre 2026) — l'amorce, version premium
   Même rythme (3-2-1 une seconde chacun, bips, « Bienvenue. », volets). Cadran très fin, arc de seconde tracé,
   chiffres en grande italique Instrument Serif qui montent d'un masque et sortent par le haut, étiquette mono
   espacée, lignes de visée qui traversent l'écran, halo discret. Plus de grain ni de tremblement.
   ============================================================ */
.boot-in { animation: none; background: linear-gradient(rgb(var(--ink-hi) / 0.05), rgb(var(--ink-hi) / 0.05)) 50% 50% / 100% 1px no-repeat, linear-gradient(rgb(var(--ink-hi) / 0.05), rgb(var(--ink-hi) / 0.05)) 50% 50% / 1px 100% no-repeat; }
.amorce { width: min(58vh, 58vw); animation: none; }
.amorce::after { content: none; }
.amorce::before { content: ""; position: absolute; inset: -22%; border-radius: 50%; background: radial-gradient(circle at 50% 50%, rgb(var(--ink-hi) / 0.07), transparent 62%); pointer-events: none; }
.amorce-svg { stroke-width: 1; }
.am-c1 { stroke: rgb(var(--ink-hi) / 0.22); stroke-width: 1; }
.am-c2 { stroke: rgb(var(--ink-hi) / 0.18); stroke-width: 1; stroke-dasharray: 1.5 10.5; }
.am-croix { stroke: rgb(var(--ink-hi) / 0.4); stroke-width: 1; }
.am-balayage { fill: none; stroke: rgb(var(--ink-hi) / 0.92); stroke-width: 2; stroke-linecap: round; }
.am-rayon { stroke: rgb(var(--ink-hi) / 0.4); stroke-width: 1; filter: none; }
.am-chiffre { transform: translate(-50%, -50%); overflow: clip; padding: 0.08em 0.16em 0.16em; margin: 0; font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: min(46vh, 40vw); line-height: 1; letter-spacing: -0.02em; color: rgb(var(--ink-hi)); will-change: auto; }
.am-chiffre.pop { animation: none; }
.am-chiffre .am-in { display: block; animation: am-monte 0.75s cubic-bezier(0.16, 1, 0.3, 1) both; }
.am-chiffre .am-out { display: block; position: absolute; left: 0.16em; top: 0.08em; animation: am-sort 0.55s cubic-bezier(0.4, 0, 0.2, 1) both; }
@keyframes am-monte { from { transform: translateY(108%) rotate(3deg); opacity: 0.5; } to { transform: none; opacity: 1; } }
@keyframes am-sort { from { transform: none; opacity: 1; } to { transform: translateY(-108%) rotate(-3deg); opacity: 0; } }
.am-portfolio { top: -2.2em; font-family: var(--f-mono); font-weight: 400; font-size: 11px; letter-spacing: 0.44em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
.boot-m { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: clamp(44px, 6.4vw, 108px); letter-spacing: -0.01em; }
@media (prefers-reduced-motion: reduce) { .am-chiffre .am-in, .am-chiffre .am-out { animation: none; } }
/* retours 188 : « En suivant beaucoup le sport… » — un gras, une italique, un accent */
#c02 .copy.p-left em { font-style: italic; color: rgb(var(--ink-hi)); }
/* retours 189 : l'interlude dit « qui donne envie d'être regardée. » */
/* retours 190 : la carte « 2020 · Acte I » revient comme avant — texte visible d'emblée, plus de montée des mots */
.scene-carte em.grand .c { transform: none; }
.scene-carte > span { opacity: 1; }
/* retours 190 (correctif) : les mots de la carte gardent la police du titre (les spans internes ne prennent pas le style mono de l'étiquette) */
.scene-carte em.grand span { font: inherit; letter-spacing: inherit; text-transform: none; color: inherit; }
/* retours 191 : la chambre retrouve son intro sombre d'avant (voile, allumage progressif, descente de caméra) — retours 187 annulé, seule la carte reste statique */
/* retours 193 : le carrousel des supports remonte un peu (scene moins haute, supports places plus haut dedans) */
.supports-stage { height: clamp(300px, 37vw, 500px); }
.support { top: 47%; }
/* retours 194 : le titre du 06 et « Les événements m'ont permis… » rapprochés (8 vh au lieu de 45) */
@media (min-width: 861px) { #c06 h2.p-left + .copy.p-tail.evts { margin-top: clamp(40px, 8vh, 100px); } }
/* retours 195 : la vidéo Évian a le contour lumineux bleu qui court (data-lum) */
/* retours 196-197 : le kanji descend (9 %) et se resserre a droite (36 vw) ; le paragraphe UNDERGROUND remonte (10 vh sous le titre) — ils se cotoient sans se chevaucher */
@media (min-width: 861px) {
  .ug-kanji { top: 9%; right: -6vw; width: clamp(280px, 36vw, 640px); }
  #c07 h2.p-left + .copy.p-tail { margin-top: clamp(60px, 10vh, 140px); }
}
/* retours 198 : le paragraphe Sora — un peu plus gros, gras (Sora, un terrain caché) et italiques */
#c07 .copy.p-center { font-size: calc(var(--t-body) * 1.14); max-width: 58ch; }
#c07 .copy.p-center em { font-style: italic; color: rgb(var(--ink-hi)); }
/* retours 200 : plus de bandes noires sur les videos souvenirs — cadre 16/9 et recadrage plein (la video Serbie est un 4/3 avec bandes incrustees, exactement coupees) */
.cinema { aspect-ratio: 16 / 9 !important; }
.cinema video { object-fit: cover; }
/* retours 201 : les chiffres de 2026 roulent vraiment — trois tours, 2,6 s, deceleration longue, un chiffre apres l autre */
.phrase.dispo.vu .bande, .phrase.dispo .disp.vu .bande { animation: rouler 2.6s cubic-bezier(0.22, 0.9, 0.24, 1) forwards; animation-delay: calc(1.15s + var(--k, 0) * 0.24s); }
.phrase.dispo.vu .mw:nth-child(4)::after, .phrase.dispo .disp.vu ~ .mw:nth-child(4)::after { animation-delay: 3.6s; }
/* retours 202 : les chiffres de l amorce changent par simple fondu croise, sans mouvement */
.am-chiffre .am-in { animation: am-fondu-in 0.35s ease-out both; }
.am-chiffre .am-out { animation: am-fondu-out 0.28s ease-out both; }
@keyframes am-fondu-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes am-fondu-out { from { opacity: 1; } to { opacity: 0; } }
/* retours 204 : le kanji descend encore, cale entre le titre et le paragraphe, un peu plus a droite pour ne toucher ni l un ni l autre */
@media (min-width: 861px) { .ug-kanji { top: 10.5%; right: -10vw; } }
/* retours 205 : bug des chiffres en barres — les chiffres empiles du rouleau prennent leur largeur de contenu (Chrome ne la remontait pas), centres dans le rouleau */
.phrase.dispo .bande i { width: max-content; margin: 0 auto; }
/* retours 205 (cause reelle) : la regle du point de la pastille (.dispo i : 5 px, rond, fond accent, ping) attrapait les chiffres du rouleau — neutralisee ici */
.phrase.dispo .bande i { width: max-content; height: 1em; border-radius: 0; background: none; animation: none; margin: 0 auto; }
/* retours 210 : le kanji entier a l ecran (plus de depassement a droite), encore plus bas ; le paragraphe un peu moins large pour ne pas passer dessous */
@media (min-width: 861px) {
  .ug-kanji { top: 12.5%; right: 0.5vw; width: clamp(280px, 34vw, 600px); }
  #c07 h2.p-left + .copy.p-tail { max-width: 56ch; }
}
/* retours 212 : sans rouleaux, le trait sous 2026 se tire juste après la montée des lettres */
.phrase.dispo.vu .mw:nth-child(4)::after, .phrase.dispo .disp.vu ~ .mw:nth-child(4)::after { animation-delay: 1.9s; }

/* ============================================================
   RETOURS 208 (8 septembre 2026) — le bouton « Son » dans la barre
   ============================================================ */
.son-btn { font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.12em; text-transform: uppercase; color: rgb(var(--ink-lo)); background: none; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 1.6)); border-radius: 999px; padding: 7px 12px 7px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; transition: color 0.25s ease, border-color 0.25s ease; }
.son-btn::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: rgb(var(--accent)); box-shadow: 0 0 8px rgb(var(--accent) / 0.8); transition: background 0.25s, box-shadow 0.25s; }
.son-btn:hover, .son-btn:focus-visible { color: rgb(var(--ink-hi)); border-color: rgb(var(--ink-hi) / 0.5); outline: none; }
.son-btn.off::before { background: rgb(var(--ink-lo) / 0.45); box-shadow: none; }
.son-btn.bloque { color: rgb(var(--ink-hi)); border-color: rgb(var(--accent) / 0.7); }
.son-btn.bloque::before { animation: son-pulse 1.4s ease-out infinite; }
@keyframes son-pulse { 0% { box-shadow: 0 0 0 0 rgb(var(--accent) / 0.7); } 100% { box-shadow: 0 0 0 9px rgb(var(--accent) / 0); } }
@media (max-width: 860px) { .son-btn { padding: 6px 10px 6px 8px; letter-spacing: 0.08em; } }
@media (prefers-reduced-motion: reduce) { .son-btn.bloque::before { animation: none; } }

/* retours 220 : l'invite « Lancer le JT » au centre de la scène, quand le navigateur bloque le son à l'entrée de la pièce */
.jt-lancer { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 6; width: 136px; height: 136px; border-radius: 50%; border: 1px solid rgb(var(--accent) / 0.85); background: rgb(0 0 0 / 0.38); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); color: rgb(var(--ink-hi)); font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.3em; text-transform: uppercase; display: grid; place-items: center; align-content: center; gap: 10px; cursor: pointer; animation: jt-lancer-pulse 1.8s ease-out infinite; transition: background 0.25s, transform 0.25s; }
.jt-lancer::before { content: ""; width: 0; height: 0; border-left: 16px solid rgb(var(--accent)); border-top: 10px solid transparent; border-bottom: 10px solid transparent; margin-left: 4px; }
.jt-lancer:hover, .jt-lancer:focus-visible { background: rgb(0 0 0 / 0.6); transform: translate(-50%, -50%) scale(1.04); outline: none; }
.jt-lancer[hidden] { display: none; }
@keyframes jt-lancer-pulse { 0% { box-shadow: 0 0 0 0 rgb(var(--accent) / 0.55); } 100% { box-shadow: 0 0 0 24px rgb(var(--accent) / 0); } }
@media (prefers-reduced-motion: reduce) { .jt-lancer { animation: none; } }
/* retours 222 : plus de gros carré « Activer le son » sur l'écran plein cadre du JT — le lecteur a déjà le sien */
#jtSon { display: none !important; }
/* retours 223 : « Bienvenue. » dans la police de titre du site, plus l'italique serif */
.boot-m { font-family: var(--f-disp); font-style: normal; font-weight: 500; letter-spacing: -0.02em; font-size: clamp(38px, 5.4vw, 92px); }
/* retours 229 : « Voir avec le son » juste sous la légende de la vidéo Évian, dans le cartouche */
.clip .tag .tag-son { display: inline-block; margin-top: 12px; letter-spacing: 0.12em; }
.clip .tag { white-space: normal; }

/* ============================================================
   RETOURS 232 (8 septembre 2026) — la fin, en vrai générique
   Le nom une seule fois, en ouverture. Puis les quatre actes et le générique technique, en paires alignées de part et
   d'autre d'une gouttière centrale (la grammaire d'un générique de cinéma). Des filets séparent les blocs. L'adresse
   ferme le film. Le rouleau garde son défilement, la section est un peu plus longue pour qu'il reste posé.
   ============================================================ */
.credits { height: 320vh; }
.credits-roll { gap: clamp(30px, 5.2vh, 62px); }
.cr-bloc { display: grid; gap: clamp(12px, 1.8vh, 22px); justify-items: center; }
.cr-filet { display: block; width: clamp(52px, 7vw, 96px); height: 1px; background: rgb(var(--rule) / calc(var(--rule-a) * 2.2)); justify-self: center; }
.cr-duo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(22px, 3vw, 54px); row-gap: clamp(12px, 1.9vh, 22px); max-width: min(820px, 92vw); margin: 0 auto; align-items: baseline; }
.cr-duo dt { grid-column: 1; text-align: right; font-family: var(--f-mono); font-size: calc(var(--t-mono) * 0.95); letter-spacing: 0.24em; text-transform: uppercase; color: rgb(var(--ink-lo)); }
.cr-duo dd { grid-column: 2; margin: 0; text-align: left; font-family: var(--f-body); font-weight: 300; font-size: clamp(16px, 1.32vw, 22px); line-height: 1.3; color: rgb(var(--ink-hi)); }
.credits-roll .n { font-size: clamp(38px, 6vw, 104px); }
.credits-roll .m { max-width: 46ch; }
.cr-fin { gap: clamp(16px, 2.4vh, 28px); }
.cr-fin .big { font-size: clamp(26px, 4.4vw, 76px); }
@media (max-width: 860px) {
  .cr-duo { grid-template-columns: 1fr; row-gap: 4px; text-align: center; }
  .cr-duo dt { grid-column: 1; text-align: center; margin-top: 14px; }
  .cr-duo dd { grid-column: 1; text-align: center; }
}

/* retours 233 : la fin, plus simple et plus resserrée — le contact est le point d'arrivée */
.credits { height: 190vh; }
.credits-roll { gap: clamp(20px, 3.2vh, 38px); }
.cr-bloc { gap: clamp(8px, 1.2vh, 14px); }
.cr-fin { margin-top: clamp(14px, 2.4vh, 30px); gap: clamp(14px, 2vh, 24px); }
.cr-fin .big { font-size: clamp(26px, 4.6vw, 80px); }
.cr-fin .links { margin-top: clamp(4px, 0.8vh, 10px); }

/* retours 236 : les trois cases de la planche UNDERGROUND se cernent d'un trait lumineux, l'une après l'autre */
[data-lum].lum-on .lum { animation-delay: var(--ld, 0s); }
#c07 .case:nth-of-type(2) { --ld: 0.22s; }
#c07 .case:nth-of-type(3) { --ld: 0.44s; }
#c07 .case .lum-t { stroke-width: 1.6; }
#c07 .case .lum-h { stroke-width: 2.6; }
#c07 .case .lum-c { stroke-width: 2; }

/* retours 238 : une lueur douce, bleu-blanc, derrière le carrousel social — juste de quoi détacher la publication du noir */
.social-stage::before { content: ""; position: absolute; left: 50%; top: 50%; width: min(78%, 620px); aspect-ratio: 1 / 1.1; transform: translate(-50%, -50%); border-radius: 50%; background: radial-gradient(closest-side, rgb(255 255 255 / 0.10), rgb(var(--accent) / 0.11) 42%, rgb(var(--accent) / 0) 72%); pointer-events: none; z-index: 0; }

/* retours 240 : un filet fin se trace autour des vidéos souvenirs — sur fond clair, pas de gros halo, juste le trait */
.cinema .lum-t { stroke-width: 1.1; stroke: rgb(var(--accent) / 0.85); filter: drop-shadow(0 0 3px rgb(var(--accent) / 0.3)); }
.cinema .lum-h { stroke-width: 1.8; stroke: rgb(var(--accent)); filter: drop-shadow(0 0 5px rgb(var(--accent) / 0.55)); }
.cinema .lum-c { stroke-width: 1.3; stroke: rgb(var(--accent)); filter: drop-shadow(0 0 4px rgb(var(--accent) / 0.45)); }
.cinema:nth-of-type(2) { --ld: 0.18s; }

/* retours 241 : les vidéos souvenirs tiennent dans l'écran — leur largeur est bornée par la hauteur libre (en-tête, bande, légende et lien compris) */
@media (min-width: 861px) { .cinema { width: min(100%, calc((100vh - 250px) * 16 / 9)); margin-inline: auto; } }

/* ============================================================
   RETOURS 242 (8 septembre 2026) — la fin prend du caractère
   Le nom joue des deux polices du site, comme le hero. La disponibilité devient une pastille vivante. L'adresse est
   la pièce maîtresse : elle monte d'un masque à l'arrivée, et au survol le trait se retire puis revient en accent.
   ============================================================ */
.cr-nom { display: inline-flex; align-items: baseline; gap: 0.16em; flex-wrap: wrap; justify-content: center; }
.cr-nom .b { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: 1.18em; letter-spacing: -0.01em; }
.cr-pastille { display: inline-flex; align-items: center; gap: 10px; margin: 0 auto; padding: 9px 18px; border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 2)); border-radius: 999px; font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.12em; color: rgb(var(--ink)); background: rgb(var(--ink-hi) / 0.02); }
.cr-fin .big { position: relative; border-bottom: 0; padding-bottom: 0.1em; }
.cr-fin .big::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: rgb(var(--accent)); transform-origin: 0 50%; transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1); }
.cr-fin .big:hover, .cr-fin .big:focus-visible { color: rgb(var(--accent)); outline: none; }
.cr-fin .big:hover::after, .cr-fin .big:focus-visible::after { animation: cr-trait 0.7s cubic-bezier(0.65, 0, 0.35, 1); }
@keyframes cr-trait { 0% { transform: scaleX(1); transform-origin: 100% 50%; } 49% { transform: scaleX(0); transform-origin: 100% 50%; } 51% { transform: scaleX(0); transform-origin: 0 50%; } 100% { transform: scaleX(1); transform-origin: 0 50%; } }
.cr-fin .links .cta { border: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 2)); border-radius: 999px; padding: 11px 20px; transition: border-color 0.25s ease, color 0.25s ease; }
.cr-fin .links .cta::after { content: none; }
.cr-fin .links .cta:hover { border-color: rgb(var(--accent)); color: rgb(var(--accent)); }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .cr-fin .big { display: inline-block; animation: cr-monte linear both; animation-timeline: --credits; animation-range: contain 34% contain 58%; }
  }
}
@keyframes cr-monte { from { opacity: 0; transform: translateY(0.34em); } to { opacity: 1; transform: none; } }
/* retours 244 : « Voir avec le son » aligné exactement sous la vidéo (même largeur bornée, même centrage) */
@media (min-width: 861px) { .cinema-lien { width: min(100%, calc((100vh - 250px) * 16 / 9)); margin-inline: auto; } }
/* retours 245 : la vidéo de Serbie se pose à droite (et sa légende et son lien avec elle) — le ski reste centré, les deux se répondent */
@media (min-width: 861px) { .takeover .cinema, .takeover .cinema-lien { margin-left: auto; margin-right: 0; } }
/* retours 246 : les deux boutons de la fin quittent la police technique pour celle des titres */
.cr-fin .links .cta { font-family: var(--f-disp); font-weight: 600; font-size: clamp(15px, 1.15vw, 19px); letter-spacing: 0; text-transform: none; padding: 12px 22px; }
/* retours 247 : la fin resserrée contre la citation */
.credits { height: 165vh; }

/* retours 248 : contour lumineux sur l'aperçu du site et sur les vignettes du lecteur — traits fins, en cascade */
.browser .lum rect, .carte .lum rect { rx: 14px; }
.browser .lum-t, .carte .lum-t { stroke-width: 1.2; }
.browser .lum-h, .carte .lum-h { stroke-width: 2; }
.browser .lum-c, .carte .lum-c { stroke-width: 1.5; }
.carte:nth-of-type(2) { --ld: 0.12s; } .carte:nth-of-type(3) { --ld: 0.24s; } .carte:nth-of-type(4) { --ld: 0.36s; }
.carte:nth-of-type(5) { --ld: 0.48s; } .carte:nth-of-type(6) { --ld: 0.6s; }
.browser .lum rect { rx: 0; }
/* retours 249 : le grand écran du lecteur a lui aussi son contour tracé, puis la lumière qui tourne en continu */
.viewer-ecran .lum-t { stroke-width: 1.3; }
.viewer-ecran .lum-h { stroke-width: 2.2; }
.viewer-ecran .lum-c { stroke-width: 1.8; stroke-dasharray: 120 880; animation-duration: 4.6s; }
/* retours 250 : le cadre du téléphone du carrousel social se trace lui aussi, puis la lumière y tourne */
.social .feed .lum rect { rx: 30px; }
.social .feed .lum-t { stroke-width: 1.3; }
.social .feed .lum-h { stroke-width: 2.2; }
.social .feed .lum-c { stroke-width: 1.8; stroke-dasharray: 120 880; animation-duration: 5s; }

/* ============================================================
   OPTIMISATION (8 septembre 2026) — accessibilité
   Le nom du hero est peint par un dégradé (background-clip: text) : si un navigateur ne le sait pas faire, le texte
   redevient plein. Les cibles tactiles passent à 44 px de haut au doigt (recommandation confort ; le seuil AA de
   24 px était déjà tenu partout).
   ============================================================ */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  html.in #hero h1 .hw { background: none; color: rgb(var(--ink-hi)); }
}
@media (max-width: 860px) {
  .cta, .son-btn, .skip { min-height: 44px; display: inline-flex; align-items: center; }
  .cr-fin .links .cta { min-height: 48px; }
}
@media (max-width: 860px) { .cinema-lien .cta, .clip .tag .tag-son { min-height: 44px; display: inline-flex; align-items: center; } }

/* ============================================================
   BENCH (8 septembre 2026) — les trois derniers contrôles
   1. l'adresse de contact tenait sur deux lignes en dessous de 380 px
   2. la légende du hero restait invisible après un saut direct (animation « both » jamais lancée)
   3. le titre du 03 était coupé par le bord bas après un saut direct
   ============================================================ */
@media (max-width: 460px) { .cr-fin .big { font-size: 6vw; letter-spacing: -0.035em; white-space: nowrap; } }
.hero-cred { opacity: 1; }
@media (prefers-reduced-motion: no-preference) { html.in .hero-cred, html.in .hero-cue { animation-fill-mode: backwards; } }
@media (min-width: 861px) { #c03 .stackset > h2:first-of-type, #c03 .mark + .stackset .lede { margin-top: 0; } }
/* le lien des mentions légales, discret, à côté du mot de la fin */
.credits-end .mentions { margin-left: 18px; padding-bottom: 2px; color: rgb(var(--ink-lo)); text-decoration: none; border-bottom: 1px solid rgb(var(--rule) / calc(var(--rule-a) * 2)); }
.credits-end .mentions:hover { color: rgb(var(--ink-hi)); border-color: rgb(var(--accent)); }
@media (max-width: 620px) { .credits-end .mentions { display: block; margin: 10px 0 0; } }
