/* ── MOUVEMENT ──────────────────────────────────────────────────────────────
   Trois dispositifs, et un seul principe : rien n'est calculé en JavaScript.
   Le JS écrit deux nombres par frame (`--vel`, `--vel-abs`) et pose un
   attribut ; tout ce qui suit est de la CSS, donc composité par le GPU.

     1. LA SÉQUENCE D'ENTRÉE — les premières secondes.
     2. LA VÉLOCITÉ — la matière réagit à la vitesse du geste.
     3. LA COUPE — un obturateur, sur les changements de plan francs.
   ───────────────────────────────────────────────────────────────────────── */

/* ════════ 1. LA SÉQUENCE D'ENTRÉE ════════════════════════════════════════
   Ce n'est pas un fondu. C'est un ordre d'apparition, comme un générique :

     0,00 s  noir. Le cadre se dessine.
     0,14 s  l'image s'ouvre depuis une fente horizontale — l'obturateur
             d'un appareil qui s'ouvre, pas un rideau qui tombe
     0,62 s  SPONGE monte de son masque
     0,76 s  PRODUCTIONS suit
     1,04 s  le filet se trace
     1,18 s  la phrase
     1,32 s  le bouton, l'accroche, la signalétique

   Le tout dure 1,9 s et ne se rejoue jamais : les animations se déclenchent
   à la pose de `data-ready`, qui n'arrive qu'une fois. Revenir d'une page
   projet ne relance donc rien.
   ───────────────────────────────────────────────────────────────────────── */

@keyframes intro-ouverture {
  from { clip-path: inset(49.5% 0 49.5% 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@keyframes intro-monte {
  from { opacity: 0; transform: translate3d(0, 0.5em, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes intro-trace {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@keyframes intro-cadre {
  from { opacity: 0; }
  to   { opacity: 1; }
}

html[data-ready='on'] .frame {
  animation: intro-cadre 900ms var(--ease-cut) backwards;
}

html[data-ready='on'] .hero-media {
  animation: intro-ouverture 1100ms var(--ease-in-out) 140ms backwards;
}

/* Le nom. Une ligne, un départ — la seconde suit la première d'un dixième de
   seconde, ce qui suffit à faire lire le bloc comme un mouvement et non comme
   une apparition.

   `backwards` et non `forwards` : passée l'animation, l'élément doit revenir
   sous le contrôle du scroll (`--active-ratio`), pas rester figé sur la
   dernière image de l'animation. */
html[data-ready='on'] #hero-name .o-split__inner {
  animation: intro-monte 1200ms var(--ease-cut) 620ms backwards;
}
html[data-ready='on'] #hero-name .o-split__mask:nth-of-type(2) .o-split__inner {
  animation-delay: 760ms;
}

html[data-ready='on'] #hero-bottom > .o-dashline {
  transform-origin: 0 50%;
  animation: intro-trace 900ms var(--ease-cut) 1040ms backwards;
}

html[data-ready='on'] #hero-statement .o-split__inner {
  animation: intro-monte 1000ms var(--ease-cut) 1180ms backwards;
}

html[data-ready='on'] #hero-actions,
html[data-ready='on'] #hero-top {
  animation: intro-monte 1000ms var(--ease-cut) 1320ms backwards;
}

/* ════════ 2. LA VÉLOCITÉ ═════════════════════════════════════════════════
   `--vel` va de -1 (vers le haut) à +1 (vers le bas), amorti en amont.

   L'étirement est volontairement PETIT. Sur un site de production, une image
   qui se déforme franchement au scroll ne dit pas « maîtrise », elle dit
   « effet ». Ce qu'on cherche est le poids : la sensation qu'il a fallu de
   l'énergie pour lancer cette matière, et qu'elle met un instant à se
   reposer. Quelques pour cent suffisent.
   ───────────────────────────────────────────────────────────────────────── */

/* La file d'images s'incline dans le sens du geste. Le cisaillement est
   appliqué au CONTENEUR, pas aux cartes : une seule couche composite. */
#bande-items-wrapper {
  transform:
    translate3d(var(--shift, 0px), -50%, 0)
    skewY(calc(var(--vel, 0) * -0.7deg));
}

/* Les affiches s'étirent verticalement — c'est la déformation d'un capteur à
   obturateur roulant pendant un mouvement rapide. */
.bande-item-bg,
.bande-item-video {
  transform: scaleY(calc(1 + var(--vel-abs, 0) * 0.055));
  transform-origin: 50% 50%;
}
/* Le survol reprend la main : on ne veut pas que les deux transformations se
   contredisent quand on s'arrête sur une carte. */
.bande-item:hover .bande-item-bg { transform: scale(1.04); }

/* Les grands titres se resserrent très légèrement quand ça défile vite : la
   lettre condensée se condense encore. Personne ne le remarque, tout le monde
   le sent. */
#manifeste-title,
#plateau-title,
#contact-title,
#audience-hero-title {
  letter-spacing: calc(-0.005em - var(--vel-abs, 0) * 0.008em);
}

/* La règle de droite s'allonge avec la vitesse — c'est le seul élément du
   site qui affiche franchement la vélocité, et il est fait pour ça. */
#scroll-indicator__bar {
  height: calc(190px + var(--vel-abs, 0) * 90px);
}

/* ════════ 3. LA COUPE ════════════════════════════════════════════════════
   Un obturateur noir qui traverse en 130 ms, uniquement quand on change de
   plan à vitesse franche (cf. ui/motion.js). C'est ce qui fait que le scroll
   se lit comme un montage et non comme un glissement continu.

   Il ne masque jamais rien d'utile : à 130 ms, l'œil enregistre une rupture,
   pas une occultation.
   ───────────────────────────────────────────────────────────────────────── */

#cut {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  pointer-events: none;
  background: var(--void);
  opacity: 0;
}

#cut.is-cutting {
  animation: coupe 130ms steps(2, jump-none);
}

@keyframes coupe {
  0%   { opacity: 0; }
  40%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ════════ MOUVEMENT RÉDUIT ═══════════════════════════════════════════════
   Tout ce qui précède est du mouvement non essentiel : la page doit rester
   entièrement lisible et utilisable sans une seule de ces animations.       */

@media (prefers-reduced-motion: reduce) {
  html[data-ready='on'] .frame,
  html[data-ready='on'] .hero-media,
  html[data-ready='on'] #hero-name .o-split__inner,
  html[data-ready='on'] #hero-bottom > .o-dashline,
  html[data-ready='on'] #hero-statement .o-split__inner,
  html[data-ready='on'] #hero-actions,
  html[data-ready='on'] #hero-top,
  #cut.is-cutting {
    animation: none;
  }

  #bande-items-wrapper { transform: translate3d(var(--shift, 0px), -50%, 0); }
  .bande-item-bg,
  .bande-item-video { transform: none; }
  #scroll-indicator__bar { height: 190px; }
}
