/* =========================================================================
   esdi.pro — le film du hero.

   Un bureau en montagne, la caméra avance jusque dans l'écran, et l'écran
   devient la page : le vrai hero (titre, pile des trois sites, boutons) sort
   de l'écran du portable. Piloté au défilement par assets/js/esdi-film.js.

   RÈGLE DE SÛRETÉ DU THÈME (apprise sur esdi-starter, voir esdi.js) : le
   contenu ne dépend JAMAIS d'une animation pour être visible. Le hero normal
   est affiché par défaut ; le film ne prend la main qu'une fois le script sûr
   de pouvoir dessiner, en posant .esdi-film-js sur <html>. Le script déplace
   alors le hero dans le cadre collant, où il devient la fin du film. Sans JS,
   en mouvement réduit, ou si le cadre n'est pas mesurable, on garde le hero
   classique, tel qu'il est en ligne aujourd'hui.

   Le flou est ici dans les PIXELS des images, jamais en filter: blur() — la
   charte a abandonné les halos flous composités (pages blanches sur Safari iOS).
   ========================================================================= */

/* Tant que le script n'a pas pris la main, le film n'existe pas. */
.film { display: none; }
.esdi-film-js .film { display: block; }

/* WordPress pose 20 px d'espacement de blocs au-dessus de <main> (block-gap
   du gabarit). Invisibles quand le hero avait le fond du menu, ils font un
   liseré entre le menu et le film en haut de page. Le film doit toucher le
   menu : on les retire quand il est actif. */
.esdi-film-js .wp-site-blocks > main,
.esdi-film-js main.wp-block-group { margin-block-start: 0; }

/* La course du défilement : c'est elle qui donne la durée du film.
   320vh, trois arrêts : le bureau, l'écran et son texte, le hero. */
/* L'en-tête est collant (76 px + 1 px de filet, voir .entete dans accueil.css) :
   le cadre se cale juste dessous, sinon il passe derrière. Défini sur :root et
   non sur .film, parce que la section qui SUIT le film s'en sert aussi pour
   son arrêt de snap — sinon elle atterrit sous l'en-tête. */
:root { --entete-h: 77px; }
.film { position: relative; height: 320vh; }

/* Pas de scroll-snap ici, ni obligatoire ni de proximité : sur des arrêts
   aussi espacés, Chrome ramène chaque cran de molette au repère voisin et le
   film ne se conduit plus. La lisibilité du texte tient au palier du script. */

.film-cadre {
  position: sticky; top: var(--entete-h);
  height: calc(100vh - var(--entete-h)); height: calc(100svh - var(--entete-h));
  overflow: clip;
  background: var(--fond);
  --voile: 1;
}

/* La scène occupe tout le cadre : le film est un fond, le texte vit dessus. */
.film-scene { position: absolute; inset: 0; }
.film-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  user-select: none; -webkit-user-select: none;
}
.film-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  /* le zoom final vise l'écran du portable, un peu au-dessus du centre */
  transform-origin: 50% 45%;
  will-change: transform, opacity;
}
/* le canvas prend le relais des images dès qu'il sait dessiner */
.film-scene.est-canvas .film-img { visibility: hidden; }

/* Un voile depuis la gauche : le texte se lit sur l'image sans halo flou,
   c'est un simple dégradé opaque, il ne coûte aucune couche de composition.
   Le script l'éteint (--voile) quand le hero prend la place. */
.film-cadre::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(100deg,
    rgb(11 21 38 / .78) 0%,
    rgb(11 21 38 / .55) 34%,
    rgb(11 21 38 / .10) 62%,
    rgb(11 21 38 / 0) 100%);
  opacity: var(--voile);
  pointer-events: none;
}
@media (max-width: 767px) {
  /* En portrait, le texte passe au-dessus du milieu de l'image : le voile
     devient vertical, sinon la fin de phrase se perd dans la vallée claire. */
  .film-cadre::after {
    background: linear-gradient(176deg,
      rgb(11 21 38 / .74) 0%,
      rgb(11 21 38 / .50) 46%,
      rgb(11 21 38 / .16) 78%,
      rgb(11 21 38 / 0) 100%);
  }
}

/* Les textes : dans le cadre collant, par-dessus le dessin. */
.film-textes {
  position: relative; z-index: 2;
  height: 100%;
  display: flex; align-items: center;
}
.film-dedans {
  max-width: var(--mesure);
  margin-inline: auto;
  padding-inline: var(--marge);
  width: 100%;
  display: grid;                       /* les textes se superposent, un seul est visible */
}
.film-txt {
  grid-area: 1 / 1; align-self: center;
  max-width: 34rem;
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  will-change: opacity, transform;
  pointer-events: none;
}
/* le premier texte est lisible avant même que le script ne tourne */
.film-txt[data-in="0"] { opacity: 1; transform: none; }
.film-txt.est-actif { pointer-events: auto; }

/* Les titres du film ne sont pas des titres de la page : le seul H1 est dans
   le hero, qui arrive à la fin. Ce sont des paragraphes habillés en titre. */
.film-titre {
  color: #fff; margin: 0;
  font-weight: 800; letter-spacing: -.03em; line-height: 1.05;
  font-size: clamp(1.875rem, 3.8vw, 2.75rem);
  text-wrap: balance;
}
.film-titre--grand { font-size: clamp(2.5rem, 6.4vw, 4.75rem); letter-spacing: -.04em; line-height: 1.02; }
.film-titre em { font-style: normal; color: #7fd8e4; }
.film-txt p:not(.film-titre):not(.film-ligne) {
  color: rgb(255 255 255 / .84);
  font-size: 1.0625rem; line-height: 1.65;
  max-width: 32rem;
  margin: 1.25rem 0 0;
}
.film-txt p strong { color: #fff; font-weight: 600; }
/* Trois lignes courtes plutôt qu'un bloc : chacune arrive à son tour (data-in
   propre, piloté par le script), taille entre le titre et le courant. */
.film-txt .film-ligne {
  color: #fff; margin: 0;
  font-weight: 700; letter-spacing: -.02em; line-height: 1.2;
  font-size: clamp(1.5rem, 2.7vw, 2.15rem);
  max-width: 32rem;
  opacity: 0; transform: translate3d(0, 14px, 0); will-change: opacity, transform;
}
.film-txt .film-ligne + .film-ligne { margin-top: .7rem; }
.film-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }
/* Le pattern emploie .btn-blanc et .btn-clair, les deux boutons que la charte
   a déjà prévus « sur fond bleu profond ». Surtout pas de blanc sur turquoise,
   que la charte écarte explicitement (2,2:1). */

/* Le vrai hero, déplacé par le script dans le cadre : il grandit depuis le
   fond de l'écran jusqu'à sa taille réelle. Le script pilote opacité et
   échelle ; ici seulement la mise en place. */
.film-hero {
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center;
  opacity: 0;
  transform: scale(.84);
  transform-origin: 50% 46%;
  will-change: opacity, transform;
  pointer-events: none;
  overflow: hidden;
}
.film-hero.est-la { pointer-events: auto; }
.film-hero .hero { width: 100%; padding-block: clamp(1rem, 3vw, 2rem); }
/* C'est le film qui révèle le hero : ses propres animations d'entrée n'ont
   plus lieu d'être, elles joueraient dans le vide. */
.film-hero .hero [data-m], .film-hero .pile img { animation: none; }
@media (max-width: 1023px) {
  /* Sur téléphone le hero est plus haut que le cadre : on part du haut, et la
     ligne de preuve, dernière, s'efface — elle revient plus bas dans la page. */
  .film-hero { align-items: flex-start; }
  .film-hero .hero-preuve { display: none; }
}

/* Une invitation à descendre, le temps du premier écran seulement. */
.film-molette {
  position: absolute; z-index: 2;
  left: 50%; translate: -50% 0;
  bottom: calc(2rem + env(safe-area-inset-bottom));
  width: 24px; height: 38px;
  border: 1.5px solid rgb(255 255 255 / .45);
  border-radius: 999px;
  opacity: var(--voile);
  pointer-events: none;
}
.film-molette::after {
  content: "";
  position: absolute; left: 50%; top: 7px;
  width: 3px; height: 7px; border-radius: 2px;
  background: rgb(255 255 255 / .8);
  animation: film-molette 1.9s var(--sortie) infinite;
}
@keyframes film-molette {
  0%, 12%  { transform: translate(-50%, 0);    opacity: 0; }
  28%      { opacity: 1; }
  70%,100% { transform: translate(-50%, 13px); opacity: 0; }
}
@media (max-width: 600px) { .film-molette { display: none; } }
@media (prefers-reduced-motion: reduce) { .film-molette::after { animation: none; } }
