/* =========================================================================
   ANIMATIONS
   Règle de base : on n'anime que « transform », « translate », « scale »,
   « rotate » et « opacity ». Jamais top, left, width ou height — ce sont
   elles qui coûtent des images par seconde et décalent la mise en page.

   Toutes les valeurs de départ sont conditionnées par la classe « js »,
   posée en tête de document. Sans JavaScript, la page reste complète et
   entièrement lisible.
   ========================================================================= */

/* -------------------------------------------------------------------------
   APPARITION AU DÉFILEMENT
   La classe est-visible est posée par js/animations.js (IntersectionObserver).
   Le décalage entre éléments d'un même bloc passe par --delai.
   ------------------------------------------------------------------------- */
.js [data-revele] {
  opacity: 0;
  translate: 0 22px;
  transition:
    opacity 620ms var(--sortie) var(--delai, 0ms),
    translate 620ms var(--sortie) var(--delai, 0ms);
}

.js [data-revele].est-visible {
  opacity: 1;
  translate: 0 0;
}

/* -------------------------------------------------------------------------
   SÉQUENCE D'OUVERTURE
   ------------------------------------------------------------------------- */

/* Le titre est découpé en mots par js/animations.js : chaque mot monte. */
.js .mot {
  display: inline-block;
  opacity: 0;
  translate: 0 0.5em;
  transition:
    opacity 520ms var(--sortie) var(--delai, 0ms),
    translate 520ms var(--sortie) var(--delai, 0ms);
}

.js .mot.est-visible {
  opacity: 1;
  translate: 0 0;
}

/* Le trait de crête se dessine : la longueur exacte est mesurée en JS
   (getTotalLength) et posée dans --longueur. */
.js .crete__trait {
  stroke-dasharray: var(--longueur, 4000);
  stroke-dashoffset: var(--longueur, 4000);
}

.js .crete__trait.est-tracee {
  transition: stroke-dashoffset 2200ms cubic-bezier(0.33, 0.9, 0.28, 1);
  stroke-dashoffset: 0;
}

.js .crete__aire {
  opacity: 0;
}

.js .crete__aire.est-tracee {
  transition: opacity 900ms var(--doux) 900ms;
  opacity: var(--opacite-aire, 0.45);
}

/* Halos et grille du hero : arrivée en fondu, une seule fois. */
.js .hero__halo,
.js .hero__grille {
  opacity: 0;
  animation: apparition-fond 1600ms var(--doux) 200ms forwards;
}

@keyframes apparition-fond {
  to {
    opacity: var(--opacite-cible, 0.6);
  }
}

.hero__halo {
  --opacite-cible: 0.5;
}

.hero__grille {
  --opacite-cible: 0.7;
}

/* Le trait « descendre » pulse doucement, sans attirer l'œil. */
.hero__descendre-trait {
  animation: descendre 2400ms var(--doux) infinite;
}

@keyframes descendre {
  0%,
  100% {
    transform: translateY(-100%);
  }
  50% {
    transform: translateY(0);
  }
}

/* -------------------------------------------------------------------------
   BANDEAU DE LOGOS — défilement continu.
   La piste contient deux copies identiques : à mi-parcours, l'image est
   la même, la boucle est donc invisible.
   ------------------------------------------------------------------------- */
.js .bandeau__piste.est-animee {
  animation: bandeau-defile var(--duree-bandeau, 42s) linear infinite;
}

@keyframes bandeau-defile {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

.bandeau:hover .bandeau__piste.est-animee {
  animation-play-state: paused;
}

/* -------------------------------------------------------------------------
   CARTES — inclinaison 3D au survol.
   --inclinaison-x / --inclinaison-y sont posées par js/interactions.js.
   ------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .js [data-lueur] {
    transform: perspective(900px) rotateX(var(--inclinaison-x, 0deg))
      rotateY(var(--inclinaison-y, 0deg));
    transition: transform 380ms var(--sortie), border-color var(--duree-moyenne);
    transform-style: preserve-3d;
  }
}

/* -------------------------------------------------------------------------
   COURBES DES ÉTUDES DE CAS — tracé à l'entrée dans l'écran.
   ------------------------------------------------------------------------- */
.js .graphe__trait {
  stroke-dasharray: var(--longueur, 500);
  stroke-dashoffset: var(--longueur, 500);
}

.js .graphe.est-tracee .graphe__trait {
  transition: stroke-dashoffset 1500ms cubic-bezier(0.33, 0.9, 0.28, 1);
  stroke-dashoffset: 0;
}

/* -------------------------------------------------------------------------
   EFFET DE DÉCODAGE — réservé à deux titres (data-decodage).
   L'animation ne change que le contenu textuel, jamais la taille : la
   largeur est figée par js/animations.js le temps de l'effet.
   ------------------------------------------------------------------------- */
.js [data-decodage].est-en-decodage {
  color: var(--cyan-clair);
}

/* -------------------------------------------------------------------------
   AUDIT EXPRESS — étapes de la simulation.
   ------------------------------------------------------------------------- */
.audit__etape {
  translate: -6px 0;
}

.audit__etape.est-faite {
  translate: 0 0;
  transition: translate var(--duree-moyenne) var(--sortie), opacity var(--duree-moyenne);
}

/* Onde autour du point sur la carte d'Andorre. */
.carte-andorre__onde {
  transform-box: fill-box;
  transform-origin: center;
  animation: onde 3200ms var(--doux) infinite;
}

@keyframes onde {
  0% {
    transform: scale(0.6);
    opacity: 0.9;
  }
  70%,
  100% {
    transform: scale(1.6);
    opacity: 0;
  }
}

/* -------------------------------------------------------------------------
   ACCORDÉON
   La réponse est réellement retirée du flux quand elle est fermée
   (attribut hidden) : c'est ce qui garantit qu'un lecteur d'écran ne la
   lit pas. À l'ouverture, seul le contenu est animé — en opacité et en
   translation, jamais en hauteur. La hauteur, elle, s'ajuste d'un coup :
   c'est le seul moyen de ne pas animer une propriété de mise en page.
   ------------------------------------------------------------------------- */
.js .accordeon__panneau > * {
  opacity: 0;
  translate: 0 -6px;
  transition: opacity 300ms var(--sortie), translate 300ms var(--sortie);
}

.js .accordeon__panneau.est-ouvert > * {
  opacity: 1;
  translate: 0 0;
}

/* -------------------------------------------------------------------------
   MENU MOBILE
   ------------------------------------------------------------------------- */
.js .menu-mobile {
  opacity: 0;
  translate: 0 -8px;
  transition: opacity 260ms var(--doux), translate 260ms var(--sortie);
}

.js .menu-mobile.est-ouvert {
  opacity: 1;
  translate: 0 0;
}

/* -------------------------------------------------------------------------
   TRANSITION DU CHANGEMENT DE LANGUE
   Courte et discrète : le texte s'estompe, se remplace, revient.
   ------------------------------------------------------------------------- */
.js body.change-de-langue [data-i18n] {
  opacity: 0.25;
  transition: opacity 140ms linear;
}

.js [data-i18n] {
  transition: opacity 220ms var(--doux);
}

/* -------------------------------------------------------------------------
   ALLÈGEMENT SUR MOBILE
   Pas de parallaxe, pas de curseur, décor simplifié.
   ------------------------------------------------------------------------- */
@media (max-width: 48rem) {
  .hero__halo {
    filter: blur(64px);
  }
  .hero__grille {
    display: none;
  }
  .crete__couche {
    /* La parallaxe est coupée en JS ; on neutralise aussi tout reste. */
    translate: none !important;
  }
}

/* =========================================================================
   MOUVEMENT RÉDUIT — règle non négociable.
   Tout est coupé, la page reste complète, lisible et utilisable.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .js [data-revele],
  .js .mot {
    opacity: 1 !important;
    translate: none !important;
  }

  .js .crete__trait,
  .js .graphe__trait {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }

  .js .crete__aire {
    opacity: var(--opacite-aire, 0.45) !important;
  }

  .js .graphe__aire {
    opacity: 0.5 !important;
  }

  .js .bandeau__piste.est-animee {
    animation: none !important;
  }

  .js [data-lueur] {
    transform: none !important;
  }

  .hero__descendre-trait,
  .carte-andorre__onde {
    animation: none !important;
  }

  .curseur {
    display: none !important;
  }

  /* L'accordéon s'ouvre d'un coup, sans transition ni fondu. */
  .js .accordeon__panneau > * {
    opacity: 1 !important;
    translate: none !important;
    transition: none !important;
  }
}
