/* ═══════════════════════════════════════════════════════════════════════
   Socle d'animations Proxymite
   ═══════════════════════════════════════════════════════════════════════

   Ce fichier est copié tel quel dans chaque maquette. Il n'est pas régénéré
   par l'agent : une animation réinventée à chaque site est une animation dont
   on ne maîtrise ni la fluidité ni la tenue sur un vieux téléphone.

   L'agent se contente de poser des attributs `data-anim` sur les éléments.
   Tout le reste — le déclenchement, le décalage, la performance — vit ici.

   Deux règles tenues de bout en bout :

     on n'anime que `transform` et `opacity`. Ce sont les deux seules
     propriétés que le navigateur traite sans recalculer la mise en page ;
     tout le reste fait saccader dès qu'on descend un peu vite.

     `prefers-reduced-motion` désactive tout. Le mouvement donne la nausée à
     certaines personnes, et un site qui l'ignore les met dehors.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  --anim-duree: 780ms;
  --anim-courbe: cubic-bezier(0.16, 1, 0.3, 1); /* départ vif, arrivée posée */
  --anim-distance: 34px;
}

/* ── L'état de départ. Sans JS, rien ne se cache : une page qui reste
      blanche parce qu'un script n'a pas chargé est pire que sans animation. */
html.js [data-anim] {
  opacity: 0;
  will-change: transform, opacity;
  transition:
    opacity var(--anim-duree) var(--anim-courbe),
    transform var(--anim-duree) var(--anim-courbe);
  transition-delay: var(--anim-retard, 0ms);
}

html.js [data-anim="monte"]    { transform: translate3d(0, var(--anim-distance), 0); }
html.js [data-anim="descend"]  { transform: translate3d(0, calc(var(--anim-distance) * -1), 0); }
html.js [data-anim="gauche"]   { transform: translate3d(calc(var(--anim-distance) * -1.4), 0, 0); }
html.js [data-anim="droite"]   { transform: translate3d(calc(var(--anim-distance) * 1.4), 0, 0); }
html.js [data-anim="zoom"]     { transform: scale(0.94); }
html.js [data-anim="fondu"]    { transform: none; }

/* Le volet : l'image se dévoile par le bas, sans bouger elle-même. */
html.js [data-anim="volet"] {
  opacity: 1;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1100ms var(--anim-courbe);
  transition-delay: var(--anim-retard, 0ms);
}

/* ── L'état visible. Une seule classe, posée par l'observateur. */
html.js [data-anim].vu {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
  will-change: auto;
}

/* ── Titre révélé mot à mot : c'est le premier contact visuel, il mérite
      un traitement à part. Les mots sont enveloppés par le script. */
html.js .mot {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}
html.js .mot > span {
  display: inline-block;
  transform: translate3d(0, 108%, 0);
  transition: transform 900ms var(--anim-courbe);
  transition-delay: var(--mot-retard, 0ms);
}
html.js [data-mots].vu .mot > span { transform: none; }

/* ── Parallaxe : le décalage est écrit par le script dans une variable, la
      composition reste au CSS. */
[data-parallaxe] { will-change: transform; }
[data-parallaxe] > * { transform: translate3d(0, var(--parallaxe, 0px), 0); }

/* ── Barre de progression de lecture. Discrète, en haut, épaisse de 3 px. */
.progression-lecture {
  position: fixed;
  inset: 0 auto auto 0;
  height: 3px;
  width: 100%;
  transform: scaleX(var(--progression, 0));
  transform-origin: 0 50%;
  background: var(--accent, currentColor);
  z-index: 999;
  pointer-events: none;
}

/* ── Le repère de défilement du hero : il dit qu'il y a quelque chose en
      dessous, ce qu'un écran plein oublie souvent de signaler. */
.indice-defilement {
  display: inline-flex;
  animation: respire 2.4s var(--anim-courbe) infinite;
}
@keyframes respire {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(9px); opacity: 0.55; }
}

/* ── Survol des visuels : lent, jamais brusque. */
.zoom-doux { overflow: hidden; }
.zoom-doux img {
  transition: transform 900ms var(--anim-courbe);
}
.zoom-doux:hover img { transform: scale(1.06); }

/* ═══ Le mouvement n'est jamais imposé ═══ */
@media (prefers-reduced-motion: reduce) {
  html.js [data-anim],
  html.js [data-anim].vu,
  html.js .mot > span {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  [data-parallaxe] > * { transform: none !important; }
  .indice-defilement { animation: none; }
  .zoom-doux img { transition: none; }
}
