/* =========================================
   CINE — Les etapes d'un etalonnage
   Le plan reste fixe, le defilement fait
   avancer le grade etape par etape.
   ========================================= */

.cinematic-page {
  background: #ffffff;
  min-height: 100vh;

  /* Largeur commune a la visionneuse, a ses annotations et a l'arbre de
     noeuds : les trois sont ainsi alignes au pixel pres, ce qui evite d'avoir
     a marquer une separation entre eux.
     Le terme `60vh * 16/9` est la largeur au-dela de laquelle un 16/9
     depasserait 60% de la hauteur d'ecran. En prenant le plus petit des trois,
     l'image ET les annotations tiennent toujours dans la fenetre.
     C'EST LE SEUL REGLAGE DE TAILLE de cette page : monter les 60vh agrandit
     tout, les baisser reduit tout. */
  --cg-w: min(62vw, 880px, calc(46vh * 16 / 9));
}

@supports (height: 1svh) {
  .cinematic-page { --cg-w: min(62vw, 880px, calc(46svh * 16 / 9)); }
}

/* La section porte elle-meme toute la course : un ecran par etape, plus un
   pour que la derniere ait le temps d'exister. Son unique enfant s'y fige.
   Aucun overflow ici ni sur un ancetre : `position: sticky` cesse de
   fonctionner des qu'un ancetre a un overflow autre que visible. */
.cg {
  position: relative;
  height: 820vh;
  height: 820svh;
  margin-top: clamp(2rem, 5vh, 4rem);
}

.cg__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ── Le visionneuse ── */

.cg__viewer {
  position: relative;
  width: var(--cg-w);
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  background: #0a0a0a;
  overflow: hidden;
}

/* Les six plans sont empiles au meme endroit. Seul celui de l'etape courante
   est opaque : c'est ce qui donne un fondu d'une etape a l'autre plutot qu'un
   remplacement sec, et ca evite tout rechargement en cours de route. */
.cg__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  /* La duree est volontairement courte : le fondu doit se lire comme un
     changement d'etage de correction, pas comme un effet. */
  transition: opacity .45s var(--ease-out);
}

.cg__frame.is-active { opacity: 1; }

/* ── Rec. 709 → look : grille de comparateurs sous le breakdown ── */
.looks {
  width: min(88vw, 1240px);
  /* remonte sous les annotations du breakdown (voir color-grade.js) */
  margin: calc(-1 * var(--cg-tail, 0px)) auto 0;
  padding: 2.5rem 0 clamp(4rem, 10vh, 8rem);
}

.looks__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  flex-wrap: wrap;
  margin-bottom: clamp(1.25rem, 3vh, 2rem);
}
.looks__title {
  margin: 0;
  font-size: clamp(1.3rem, 2.2vw, 1.9rem);
  font-weight: 500;
  letter-spacing: -0.05em;
}
.looks__desc {
  margin: 0;
  font-size: .85rem;
  color: var(--ink-soft);
}

.looks__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(.75rem, 1.6vw, 1.5rem);
}

.ba-cmp {
  --ba: 50%;
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #0a0a0a;
  cursor: ew-resize;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}
.ba-cmp.is-in { opacity: 1; transform: none; }

.ba-cmp__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
}
.ba-cmp__before { clip-path: inset(0 calc(100% - var(--ba)) 0 0); }

.ba-cmp__label {
  position: absolute;
  top: .7rem;
  z-index: 2;
  padding: .28rem .6rem;
  border-radius: 100px;
  background: rgba(10, 10, 10, .55);
  color: #fff;
  font-size: .62rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  pointer-events: none;
  transition: opacity .25s ease;
}
.ba-cmp__label--before { left: .7rem; }
.ba-cmp__label--after  { right: .7rem; }
.ba-cmp.is-hide-before .ba-cmp__label--before,
.ba-cmp.is-hide-after  .ba-cmp__label--after { opacity: 0; }

.ba-cmp__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--ba);
  z-index: 3;
  width: 2px;
  margin-left: -1px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(10, 10, 10, .15);
  outline: none;
}
.ba-cmp__knob {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.3rem;
  height: 2.3rem;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  box-shadow: 0 2px 12px rgba(10, 10, 10, .25);
  transition: scale .25s var(--ease-out);
}
.ba-cmp:hover .ba-cmp__knob,
.ba-cmp.is-dragging .ba-cmp__knob { scale: 1.08; }
.ba-cmp__handle:focus-visible .ba-cmp__knob { outline: 2px solid var(--ink); outline-offset: 3px; }

@media (max-width: 860px) {
  .looks { width: 92vw; }
  .looks__grid { grid-template-columns: 1fr; }
}

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

/* ── Étape 7 : avant / après ──
   L'image finale dessous, la conversion Rec. 709 dessus, coupé par clip-path à la
   position de la poignée (--ba, en %). Les libellés Avant / Après restent
   dans leur coin ; chacun s'efface quand son côté est presque masqué. */
.cg__ba {
  --ba: 50%;
  pointer-events: none;
  touch-action: pan-y;        /* le defilement vertical reste possible */
  cursor: ew-resize;
  user-select: none;
  -webkit-user-select: none;
}
.cg__ba.is-active { pointer-events: auto; }

.cg__ba-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
}

.cg__ba-before { clip-path: inset(0 calc(100% - var(--ba)) 0 0); }

.cg__ba-label {
  position: absolute;
  top: clamp(.6rem, 1.6vw, 1.1rem);
  z-index: 2;
  padding: .32rem .7rem;
  border-radius: 100px;
  background: rgba(10, 10, 10, .55);
  color: #fff;
  font-size: .68rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  pointer-events: none;
  transition: opacity .25s ease;
}
.cg__ba-label--before { left: clamp(.6rem, 1.6vw, 1.1rem); }
.cg__ba-label--after  { right: clamp(.6rem, 1.6vw, 1.1rem); }
.cg__ba.is-hide-before .cg__ba-label--before,
.cg__ba.is-hide-after  .cg__ba-label--after { opacity: 0; }

/* La poignee : un trait fin sur toute la hauteur, un rond au centre */
.cg__ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--ba);
  z-index: 3;
  width: 2px;
  margin-left: -1px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(10, 10, 10, .15);
  outline: none;
}
.cg__ba-knob {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.6rem;
  height: 2.6rem;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  box-shadow: 0 2px 12px rgba(10, 10, 10, .25);
  transition: scale .25s var(--ease-out);
}
.cg__ba:hover .cg__ba-knob,
.cg__ba.is-dragging .cg__ba-knob { scale: 1.08; }
.cg__ba-handle:focus-visible .cg__ba-knob { outline: 2px solid var(--ink); outline-offset: 3px; }

/* Ordinateur : la FRAME est centree au pixel dans l'ecran (haut/bas et
   gauche/droite) ; les annotations ne comptent pas dans le centrage, elles
   se posent juste en dessous, sur la meme largeur. */
@media (min-width: 861px) {
  .cg__sticky { position: sticky; }

  .cg__hud {
    position: absolute;
    left: 50%;
    top: calc(50% + var(--cg-w) * 9 / 32);
    translate: -50% 0;
    margin-top: clamp(1rem, 2.5vh, 2rem);
  }
}

/* ── Annotations ── */

/* Meme largeur que la visionneuse, pour que le texte s'aligne sur son bord. */
.cg__hud {
  width: var(--cg-w);
  margin: clamp(1rem, 2.5vh, 2rem) auto 0;
  display: flex;
  align-items: flex-end;
  gap: 2rem;
}

/* Les six annotations occupent la meme case de la grille : la hauteur du bloc
   ne bouge donc pas d'une etape a l'autre, et l'image ne se decale jamais. */
.cg__steps {
  display: grid;
  list-style: none;
  flex: 1;
  min-width: 0;
}

.cg__step {
  grid-area: 1 / 1;
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 1.1rem;
  row-gap: .2rem;
  align-items: baseline;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .4s var(--ease-out), transform .4s var(--ease-out);
  pointer-events: none;
}

.cg__step.is-active {
  opacity: 1;
  transform: none;
}

.cg__num {
  grid-row: 1 / 3;
  font-size: .7rem;
  letter-spacing: .2em;
  color: var(--ink-soft);
  font-feature-settings: "tnum";
  padding-top: .1rem;
}

.cg__name {
  font-size: clamp(.9rem, 1.1vw, 1.05rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--ink);
}

.cg__desc {
  grid-column: 2;
  font-size: .7rem;
  letter-spacing: .02em;
  color: var(--ink-soft);
}

/* ── Jauge de progression ── */

.cg__rail {
  flex: none;
  width: clamp(80px, 14vw, 220px);
  height: 2px;
  background: var(--line);
  position: relative;
  margin-bottom: .5rem;
}

.cg__rail-fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0;
  background: var(--ink);
  transition: width .45s var(--ease-out);
}

@media (max-width: 860px) {
  .cg__hud {
    flex-direction: column;
    align-items: stretch;
    gap: .9rem;
  }

  .cg__rail {
    width: 100%;
    margin-bottom: 0;
  }

  /* Sur un telephone, un 16/9 large laisse enormement de vide. On rend la
     visionneuse plus haute pour que le plan reste lisible. */
  .cg__viewer {
    width: 100vw;
    aspect-ratio: 4 / 3;
  }

  /* --cg-w vaut 78vw sur un telephone, trop etroit ici : les annotations
     reprennent la largeur utile de l'ecran. (Le graphe est traite plus bas,
     apres sa propre declaration : place ici, la surcharge serait ecrasee.) */
  .cg__hud { width: 92vw; }

  /* ── Resserrement vertical ──
     Le bloc epingle fait toute la hauteur d'ecran, mais son contenu (le plan
     en 4/3 plus les annotations) n'en occupe qu'environ 45%. Centre, il
     laissait pres de 28% d'ecran vide sous les annotations, auxquels
     s'ajoutait la marge haute du graphe : au total un tiers d'ecran de blanc
     entre les deux.
     Le padding reduit la boite dans laquelle le contenu se centre : il
     descend donc de la moitie de cette valeur, ce qui reprend autant sur
     l'espace du bas. On reste sur `center` et non `flex-end`, qui collerait
     le plan en bas de l'ecran pendant toute la sequence. */
  .cg__sticky { padding-top: 12svh; }

}

/* ═══════════════════════════════════════════
   ARBRE DE NOEUDS
   Prolongement de la sequence, pas une nouvelle
   section : aucun filet, aucun titre, aucun
   encadrement. Seul un ecart vertical le separe
   de la derniere etape.
   ═══════════════════════════════════════════ */

.nodes {
  padding-top: clamp(2rem, 6vh, 4.5rem);
  padding-bottom: clamp(4rem, 12vh, 9rem);
}

/* Calee sur la meme largeur que la visionneuse : les bords du graphe tombent
   exactement sous ceux des plans du dessus. C'est cet alignement qui fait
   lire les deux blocs comme un seul, sans avoir a les delimiter. */
.nodes__fig {
  width: var(--cg-w);
  margin: 0 auto;
}

/* Remise a zero du bouton : il ne doit rien ajouter autour de l'image. */
.nodes__open {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  font: inherit;
  color: inherit;
  line-height: 0;
}

.nodes__open:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

/* L'image tient entiere dans la largeur disponible, y compris sur telephone :
   la faire deborder avec un defilement horizontal la coupait a l'ecran. */
.nodes__img {
  display: block;
  width: 100%;
  height: auto;
}

/* ── Vue agrandie ── */

.zoom {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(255, 255, 255, .98);
}

.zoom[hidden] { display: none; }

/* Le volet defile dans les deux sens : c'est ce qui permet de se promener
   dans le graphe affiche a sa taille reelle. */
.zoom__pane {
  position: absolute;
  inset: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Taille native : c'est tout l'interet de la vue agrandie, les libelles des
   noeuds redeviennent lisibles. max-width neutralise le plafond de base.css. */
.zoom__img {
  width: 2112px;
  max-width: none;
  height: auto;
  flex: none;
  margin: auto;
}

.zoom__close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.8rem;
  line-height: 1;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--bg);
  color: var(--ink);
  cursor: pointer;
  transition: background .3s ease, color .3s ease;
}

.zoom__close:hover {
  background: var(--ink);
  color: var(--bg);
}

/* Le defilement de la page est bloque tant que la vue est ouverte, sinon on
   fait bouger la page derriere en essayant de se deplacer dans le graphe. */
body.zoom-open {
  overflow: hidden;
}

.nodes__caption {
  margin-top: .9rem;
  font-size: .8rem;
  letter-spacing: .02em;
  color: var(--ink-soft);
}

/* Apparition au defilement, posee par color-grade.js */
.nodes__fig {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .9s var(--ease-out), transform .9s var(--ease-out);
}

.nodes.is-in .nodes__fig {
  opacity: 1;
  transform: none;
}

/* Surcharges mobiles du graphe. Elles sont volontairement APRES les regles
   ci-dessus : a specificite egale, c'est la derniere declaree qui l'emporte,
   et placees dans le bloc mobile plus haut dans le fichier elles etaient
   silencieusement ecrasees. */
@media (max-width: 860px) {
  .nodes__fig { width: 92vw; }

  /* Le vide sous les annotations du bloc epingle suffit largement a separer
     les deux : toute marge supplementaire ici s'y ajouterait. */
  .nodes {
    padding-top: 0;
    padding-bottom: clamp(3rem, 8vh, 5rem);
  }
}

/* ═══════════════════════════════════════════
   EN-TETE + MUR DE STILL FRAMES
   Les valeurs d'animation (filtre LOG, bandeau,
   survol, frame agrandie, flou, voile) sont dans
   js/cinematic.js, en tete de fichier.
   ═══════════════════════════════════════════ */

/* La scene fait elle-meme l'espace sous la nav (works-hub.css met 8rem a
   toutes les pages works). */
.cinematic-page { padding-top: 0; }

/* Un rectangle de la hauteur de l'ecran, avec les memes marges que la page
   Lab (largeur max --hub-max, marges laterales --hub-pad). cinematic.js
   l'epingle et transforme le defilement vertical en glissement du mur de
   gauche a droite. */
.cine-stage {
  height: 100vh;
  height: 100svh;
  max-width: var(--hub-max);
  margin: 0 auto;
  padding: 6rem var(--hub-pad) clamp(1.5rem, 4vh, 2.5rem);
}

.cine-stage__inner {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.cine-head { flex: none; }

/* En-tete discret, sur une ligne : le mur est le sujet de la page. */
.cine-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1.5rem;
  padding: 0 0 1rem;
}

.cine-head__titles {
  display: flex;
  align-items: baseline;
  gap: .75rem;
}

.cine-head__title {
  font-size: clamp(1.4rem, 1.8vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.055em;
  line-height: 1;
  text-transform: lowercase;
  color: var(--ink);
}

.cine-head__sub {
  font-size: .9rem;
  font-weight: 300;
  color: var(--ink-soft);
}

/* Meme traitement que les liens de la nav : fin, minuscules, grossit et
   s'epaissit au survol. */
.cine-head__pg {
  padding: .25rem 0;
  border: 0;
  background: none;
  font-size: .9rem;
  font-weight: 300;
  text-transform: lowercase;
  color: var(--ink);
  cursor: pointer;
  transform-origin: right center;
  transition: transform .45s var(--ease-out), font-weight .2s linear;
}

.cine-head__pg:hover,
.cine-head__pg:focus-visible {
  transform: scale(1.1);
  font-weight: 700;
}

/* Fenetre sur le mur : elle prend toute la hauteur restante de la scene.
   Sans script, on y defile a l'horizontale normalement ; avec, cinematic.js
   la ferme (is-pinned) et fait glisser le mur au defilement vertical. */
.wall-viewport {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
}

/* Coupe a gauche et a droite (bords de l'ecran), mais pas en haut ni en
   bas : la frame survolee et les rangees qu'elle ecarte peuvent deborder
   un peu au-dessus et au-dessous du mur. */
.wall-viewport.is-pinned { overflow: hidden; }

@supports (overflow: clip) {
  .wall-viewport.is-pinned { overflow-x: clip; overflow-y: visible; }
}

/* Grille serree, sans espace, rangee en colonnes : le degrade se lit de
   gauche a droite. --rows frames de haut ; la largeur des colonnes
   (--tile-w) est posee par cinematic.js pour garder le 16:9 quelle que
   soit la hauteur de l'ecran. */
.wall {
  --rows: 4;
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--rows), minmax(0, 1fr));
  grid-auto-columns: var(--tile-w, 280px);
  /* Espacement entre les frames : fin, juste de quoi les separer */
  gap: clamp(.25rem, .4vw, .4rem);
  width: max-content;
  height: 100%;
  will-change: transform;
}

/* La frame prend la hauteur de sa rangee et sa largeur en decoule : elle
   reste en 16:9 quoi qu'il arrive, meme si la largeur des colonnes n'est
   pas encore recalculee (changement de taille de fenetre). */
.wall__item {
  position: relative;
  justify-self: start;
  width: auto;
  height: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 0;
  background: var(--bg-2);
  overflow: hidden;
  cursor: zoom-in;
  line-height: 0;
}

/* La frame survolee passe au-dessus de ses voisines (z-index pose par
   cinematic.js pendant le survol). */
.wall__item.is-hover { z-index: 2; }
/* La derniere survolee passe devant celle qui est en train de rapetisser */
.wall__item.is-front { z-index: 3; }

.wall__item:focus-visible {
  z-index: 4;
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.wall__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Materiel de la frame survolee (boitier · objectif) : une seule ligne,
   noir sur blanc, dans le blanc sous la galerie. Rien sur la frame.
   Position verticale posee par cinematic.js (juste sous les frames). */
.cine-stage__inner { position: relative; }

/* Centree sur la largeur et sur sa ligne (le point d'ancrage pose par
   cinematic.js est le milieu du blanc sous les frames). Le centrage passe
   par `translate` et non `transform`, que GSAP anime pour le fondu. */
.wall-caption {
  position: absolute;
  left: 50%;
  translate: -50% -50%;
  text-align: center;
  margin: 0;
  font-size: .8rem;
  font-weight: 400;
  letter-spacing: .03em;
  color: var(--ink);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  display: flex;
  align-items: center;
  gap: .55em;
}

/* La fleur du logo, en petit, comme un tiret devant la description */
.wall-caption__mark {
  flex: none;
  width: .85em;
  height: .85em;
  fill: currentColor;
}

/* La vignette agrandie quitte le mur : sa case reste vide le temps de
   l'agrandissement, elle y revient a la fermeture. */
.wall__item.is-out { visibility: hidden; }

/* Telephone et tablette : pas de defilement horizontal ni de survol. Le
   mur est une grille classique de 2 frames par ligne qui defile avec la
   page ; un tap agrandit la frame (materiel affiche sous elle). Meme seuil
   que DESKTOP_MIN dans cinematic.js. */
@media (max-width: 860px) {
  .cine-stage {
    height: auto;
    padding: 5.5rem var(--hub-pad) clamp(2.5rem, 8vh, 4rem);
  }

  .cine-stage__inner {
    height: auto;
    display: block;
  }

  /* Le mur ne touche plus les bords de l'ecran : petite marge de 12 px de
     chaque cote (la scene a une marge plus large, on en annule le reste). */
  .wall-viewport {
    overflow: visible;
    margin: 0 calc(12px - var(--hub-pad));
  }

  .wall {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: none;
    grid-auto-columns: auto;
    width: auto;
    height: auto;
    will-change: auto;
  }

  .wall__item {
    width: 100%;
    height: auto;
  }

  .wall-caption { display: none; }
}

/* ── Frame agrandie ── */
.lb {
  position: fixed;
  inset: 0;
  z-index: 190;
}

.lb[hidden] { display: none; }

/* Simple voile blanc qui capte le clic de fermeture ; le flou est applique
   a la page elle-meme par cinematic.js. */
.lb__backdrop {
  position: absolute;
  inset: 0;
  cursor: zoom-out;
}

/* Taille et position posees par cinematic.js ; le transform est reserve a
   l'animation FLIP. */
.lb__frame {
  position: fixed;
  overflow: hidden;
  background: var(--bg-2);
  transform-origin: 0 0;
  cursor: zoom-out;
  outline: none;
  touch-action: pan-y;
  will-change: transform;
}

.lb__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

.lb__img.is-front { opacity: 1; }

/* Materiel du plan sous la frame agrandie. Position posee par
   cinematic.js, calee sur le bord gauche de la frame. */
.lb__info {
  position: fixed;
  margin: 0;
  font-size: .8rem;
  font-weight: 400;
  letter-spacing: .03em;
  color: var(--ink);
  pointer-events: none;
  opacity: 0;
}

/* ── Panneau powergrade ── */
.pg {
  position: fixed;
  inset: 0;
  z-index: 180;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  background: rgba(255, 255, 255, .82);
}

.pg[hidden] { display: none; }

/* Meme place et meme style que le bouton back (.covers-back) : il le
   recouvre exactement tant que le panneau est ouvert. */
.pg__close {
  position: fixed;
  top: 1.5rem;
  left: calc(var(--gutter) + 4rem);
  z-index: 3;
  padding: .5rem 1rem;
  border: 0;
  border-radius: 100px;
  background: rgba(255, 255, 255, .85);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  font-size: .85rem;
  letter-spacing: .1em;
  color: var(--ink);
  cursor: pointer;
  transition: transform .4s var(--ease-out), color .3s ease;
}

.pg__close:hover { transform: translateX(-4px); }

@media (max-width: 900px) {
  .pg__close { top: 1rem; left: calc(var(--gutter) + 3rem); }
}

/* Arbre de noeuds agrandi : deplacement ET zoom au doigt. */
.zoom__pane { touch-action: pan-x pan-y pinch-zoom; }

/* Ordinateur : meme espace entre le bas de la galerie et l'arbre de noeuds
   qu'entre l'arbre et la frame du breakdown.
   --cg-gap = blanc au-dessus de la frame du breakdown (frame centree dans
   l'ecran). --gal-bottom = blanc deja laisse sous les frames de la galerie
   (pose par cinematic.js). On complete jusqu'a --cg-gap au-dessus de
   l'arbre, et rien en dessous : la frame centree apporte deja --cg-gap.
   La legende de l'arbre est posee sous l'image sans compter dans l'espace. */
@media (min-width: 861px) {
  .cinematic-page {
    --cg-gap: calc((100vh - var(--cg-w) * 9 / 16) / 2);
  }

  @supports (height: 1svh) {
    .cinematic-page { --cg-gap: calc((100svh - var(--cg-w) * 9 / 16) / 2); }
  }

  .nodes {
    padding: max(0px, calc(var(--cg-gap) - var(--gal-bottom, 0px))) 0 0;
  }

  .nodes__fig { position: relative; }

  .nodes__caption {
    position: absolute;
    top: 100%;
    left: 0;
  }

  .cg { margin-top: 0; }
}

/* Telephone : meme espace (--m-gap) entre la galerie et l'arbre de noeuds
   qu'entre l'arbre (legende comprise) et la frame du breakdown. La frame
   du breakdown n'est plus centree dans l'ecran (ce qui laissait un grand
   vide au-dessus) : elle se pose a --m-gap du haut, sous la nav. */
@media (max-width: 860px) {
  .cinematic-page { --m-gap: 5.5rem; }

  .cine-stage { padding-bottom: var(--m-gap); }

  .nodes { padding: 0; }

  .cg { margin-top: 0; }

  /* Telephone : le breakdown s'arrete au milieu de l'ecran (bloc epingle
     plein ecran, contenu centre sous la nav) pendant que les etapes
     defilent. Pour ne pas l'isoler entre deux grands vides, la section
     remonte sous l'arbre de noeuds (--cg-head) et les comparatifs
     remontent sous les annotations (--cg-tail) : a l'entree on voit la fin
     de l'arbre au-dessus, a la sortie le debut des comparatifs en dessous.
     Les deux valeurs sont mesurees par color-grade.js. Le vide transparent
     du bloc ne doit pas bloquer les clics sur l'arbre : seuls l'image et
     les annotations recoivent la souris / le doigt. */
  .cg {
    margin-top: calc(2.5rem - var(--cg-head, 0px));
    pointer-events: none;
  }
  .cg__viewer,
  .cg__hud { pointer-events: auto; }
  .cg__sticky {
    justify-content: center;
    padding-top: 4.5rem;
  }
  .looks { padding-top: 2rem; }
}

/* Mouvement reduit : plus de fondu, l'etape change net. */
@media (prefers-reduced-motion: reduce) {
  .cg__frame,
  .cg__step,
  .cg__rail-fill,
  .nodes__fig {
    transition: none;
  }

  /* Sans transition, l'etat de depart resterait fige a opacite 0 */
  .nodes__fig {
    opacity: 1;
    transform: none;
  }
}
