/* ==========================================================================
   FD Stratégies — États d'animation

   Principe : les états initiaux ne sont posés QUE si le JS a pris la main
   (<html class="fds-anim">). Sans JavaScript, ou en cas d'échec de GSAP, la
   page reste entièrement lisible — aucun contenu n'est masqué.
   ========================================================================== */

/* --- États de départ, posés par la classe racine ------------------------- */

.fds-anim [data-fds-reveal] {
  opacity: 0;
  transform: translate3d(0, 28px, 0);
  will-change: transform, opacity;
}

.fds-anim [data-fds-reveal="left"]  { transform: translate3d(-32px, 0, 0); }
.fds-anim [data-fds-reveal="right"] { transform: translate3d(32px, 0, 0); }
.fds-anim [data-fds-reveal="fade"]  { transform: none; }
.fds-anim [data-fds-reveal="scale"] { transform: scale(.94); }

/* Une fois joué, GSAP nettoie SON transform en ligne (`clearProps`) pour ne
   pas figer un contexte d'empilement qui casserait les positions sticky
   des descendants (voir app.js, initReveals). Mais sans cette règle, retirer
   le transform en ligne fait retomber l'élément sur celui, permanent, posé
   ci-dessus par `[data-fds-reveal="…"]` — dont l'attribut reste présent dans
   le DOM pour toujours. Résultat : la carte reste décalée de -32px/32px/28px
   à vie après son animation d'entrée, un décalage d'autant plus visible que
   l'élément est large (bordures, fond) et que le décalage horizontal est
   grand — exactement le cas ici avec la carte de réservation. Spécificité
   plus élevée (deux classes + un attribut) que les règles ci-dessus : ceci
   gagne dès que `.fds-played` est posée, quel que soit le mode. */
.fds-anim [data-fds-reveal].fds-played { transform: none; }

/* Titres découpés en mots : chaque mot remonte de derrière son masque.
   Le découpage se fait sur les nœuds texte, donc l'italique orange des
   <em> survit intact à l'opération. */
.fds-anim [data-fds-lines] { opacity: 0; }

.fds-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;

  /* Le masque est plus grand que le mot, sur les quatre côtés — sinon il
     rogne le dessin des lettres au lieu de seulement les révéler :
       · en haut   — les accents (é, à) et les capitales dépassent du
                     bloc de ligne dès que l'interlignage est serré (1.02) ;
       · en bas    — les jambages des g, j, p, q, y ;
       · sur les côtés — l'italique penche vers la droite, la dernière
                     lettre d'un mot déborde de sa chasse.
     Les marges négatives annulent l'encombrement ainsi ajouté, la mise en
     page reste identique au pixel près. */
  padding: .26em .1em .18em;
  margin: -.26em -.1em -.18em;
}

.fds-word__i {
  display: inline-block;
  will-change: transform;
}

/* Panneaux qui se dévoilent par un balayage diagonal. */
.fds-anim [data-fds-wipe] {
  clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
  will-change: clip-path;
}

/* Même bug que .fds-played ci-dessus, même correctif : une fois l'habillage
   terminé, GSAP nettoie SON clip-path en ligne (clearProps), ce qui fait
   retomber l'élément sur la règle ci-dessus — collapsé pour toujours,
   invisible. `initWipes()` (app.js) pose désormais `.fds-played` en fin
   d'animation ; cette règle, plus spécifique, l'emporte alors. */
.fds-anim [data-fds-wipe].fds-played { clip-path: none; }

.fds-anim [data-fds-parallax] { will-change: transform; }

/* Une fois joué, on relâche la couche de composition. */
.fds-played { will-change: auto; }

/* --- Effets permanents (sans dépendance JS) ------------------------------ */

/* Bouton magnétique : le JS translate, le CSS amortit. */
[data-fds-magnetic] { transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
[data-fds-magnetic].is-magnetized { transition: transform .1s linear; }

/* Le bandeau de logos s'arrête au survol, courtoisie de lecture. */
.fds-marquee:hover .fds-marquee__track { animation-play-state: paused; }

/* ==========================================================================
   prefers-reduced-motion — respect strict
   Tout est visible, immobile, immédiatement.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  .fds-anim [data-fds-reveal],
  .fds-anim [data-fds-lines] {
    opacity: 1 !important;
    transform: none !important;
  }
  .fds-anim [data-fds-wipe] { clip-path: none !important; }

  .fds-dot::after { display: none; }
  .fds-marquee__track { transform: none !important; }
  .fds-marquee {
    overflow-x: auto;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* Repli si le JS ne démarre jamais : rien ne doit rester invisible. */
.no-js [data-fds-reveal],
.no-js [data-fds-lines] { opacity: 1; transform: none; }
.no-js [data-fds-wipe] { clip-path: none; }
