/* ==========================================================================
   SkylineVision — animations.css

   Principe : sobriété. Chaque élément n'est animé qu'une fois, à sa première
   apparition. Aucune boucle permanente, aucun mouvement pendant la lecture.

   Tous les états de départ sont conditionnés à .js (posé par init.js) :
   sans JavaScript, la page s'affiche normalement, sans rien de masqué.
   Tout est désactivé si le visiteur demande moins d'animations.
   ========================================================================== */

:root {
  --anim-courbe: cubic-bezier(0.22, 0.61, 0.36, 1);
  --anim-duree:  0.9s;
}

/* --------------------------------------------------------------------------
   0. RÈGLE DE SÛRETÉ — à lire avant de toucher à ce fichier

   Un élément n'est masqué que s'il porte la classe « pret ». Cette classe est
   posée par site.js, juste avant qu'il ne se mette à observer l'élément —
   autrement dit par le code même qui est chargé de le révéler ensuite.

   Conséquence : aucun enchaînement de pannes ne peut laisser du contenu
   invisible. Script absent, erreur JavaScript, fichier non chargé — dans
   tous les cas « pret » n'est jamais posée et la page s'affiche normalement,
   simplement sans animation.

   NE JAMAIS écrire un état masqué sans la condition .pret.
   -------------------------------------------------------------------------- */

/* Bloc qui monte en fondu */
.js .reveler.pret {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 1s var(--anim-courbe), transform 1s var(--anim-courbe);
}
.js .reveler.pret.est-visible {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   1. Titres — apparition mot à mot
   Le JS découpe le titre en mots ; chaque mot monte derrière sa propre
   fenêtre. C'est l'animation signature du site : réservée aux grands titres.
   -------------------------------------------------------------------------- */
.mot {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* Les grands titres sont composés en line-height 0.92 : la boîte est plus
     basse que les glyphes. Sans cette marge, overflow rognerait les hampes
     (l, h, d) en haut et les jambages (p, g, y) en bas. Le retrait négatif
     annule l'espace ainsi ajouté pour ne pas décaler la mise en page. */
  padding: 0.18em 0;
  margin: -0.18em 0;
}

/* Même règle de sûreté que plus haut : le mot n'est décalé hors champ que si
   le titre porte « pret ». Si le script s'est arrêté entre le découpage et la
   mise en observation, les mots restent simplement en place. */
.js .pret .mot-i {
  display: inline-block;
  /* 125 % et non 100 % : le mot doit franchir aussi la zone de marge
     ci-dessus pour être entièrement hors champ avant de remonter. */
  transform: translateY(125%);
  transition: transform var(--anim-duree) var(--anim-courbe);
  transition-delay: var(--mot-retard, 0s);
}

.js .pret.est-visible .mot-i,
.js .pret.mot-anime .mot-i {
  transform: translateY(0);
}

/* --------------------------------------------------------------------------
   2. Images — dévoilement par volet
   L'image est découverte du bas vers le haut pendant qu'elle se détend
   d'un très léger zoom. Effet de rideau, sans surcharge.
   -------------------------------------------------------------------------- */
.js .media-volet.pret {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.15s var(--anim-courbe);
}
.js .media-volet.pret.est-visible {
  clip-path: inset(0 0 0 0);
}

.js .media-volet.pret img {
  transform: scale(1.14);
  transition: transform 1.6s var(--anim-courbe);
}
.js .media-volet.pret.est-visible img {
  transform: scale(1);
}

/* Le survol des galeries reprend la main une fois le dévoilement terminé */
.js .galerie figure.est-visible:hover img,
.js .secteur.est-visible:hover img {
  transform: scale(1.05);
}

/* Un élément qui porte les deux classes ne joue QUE le rideau : cumuler le
   fondu de .reveler et le dévoilement ferait deux animations pour un seul
   objet, ce qui alourdit au lieu d'accompagner. */
.js .reveler.media-volet.pret {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   3. Hero — entrée au chargement
   Un seul zoom arrière très lent, qui s'arrête. Pas de boucle.
   -------------------------------------------------------------------------- */
.js .hero-media img,
.js .hero-media video {
  animation: heroEntree 2.4s var(--anim-courbe) both;
}

@keyframes heroEntree {
  from { transform: scale(1.09); }
  to   { transform: scale(1); }
}

/* Le titre et l'accroche du hero montent au chargement */
.js .hero-accroche,
.js .hero-pied,
.js .hero-page .label {
  animation: heroTexte 1s var(--anim-courbe) both;
}
.js .hero-accroche { animation-delay: 0.45s; }
.js .hero-pied     { animation-delay: 0.6s; }
.js .hero-page .label { animation-delay: 0.1s; }

@keyframes heroTexte {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   4. Défilement en profondeur
   Décalage très faible entre l'image de fond et la page. Volontairement
   discret : on doit le sentir, pas le voir.
   -------------------------------------------------------------------------- */
.parallaxe {
  will-change: transform;
}

/* Marge haute et basse pour que le décalage ne découvre jamais les bords */
.js .hero-media.parallaxe {
  inset: -8% 0;
}

/* --------------------------------------------------------------------------
   5. Compteurs
   Les chiffres clés s'incrémentent à leur apparition. Largeur figée pendant
   le comptage pour éviter que la mise en page ne tressaute.
   -------------------------------------------------------------------------- */
.chiffre-valeur {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   6. Liens et boutons — retours au survol
   -------------------------------------------------------------------------- */
.bouton {
  position: relative;
  overflow: hidden;
}

/* Léger balayage lumineux au survol des boutons pleins */
.bouton::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    110deg,
    transparent 20%,
    rgba(255, 255, 255, 0.28) 50%,
    transparent 80%
  );
  transform: translateX(-120%);
  transition: transform 0.75s var(--anim-courbe);
  pointer-events: none;
}
.bouton:hover::before { transform: translateX(120%); }
.bouton > * { position: relative; z-index: 1; }

/* Les cartes de secteur laissent remonter leur texte au survol */
.secteur-texte p {
  transition: opacity var(--transition), transform var(--transition);
}
@media (hover: hover) and (min-width: 1025px) {
  .js .secteur-texte p {
    opacity: 0;
    transform: translateY(10px);
  }
  .js .secteur:hover .secteur-texte p,
  .js .secteur:focus-visible .secteur-texte p {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   7. Bandeau des clients — défilement continu
   Seule animation en boucle du site. Elle est lente et sans à-coup : elle
   donne une respiration à la bande sans attirer l'œil pendant la lecture.
   -------------------------------------------------------------------------- */
.bandeau-piste {
  animation: defile 48s linear infinite;
}

/* La piste contient TROIS séries identiques : à -33,333 % elle a exactement
   avancé d'une série, donc l'image est la même qu'au départ.

   Pourquoi trois et non deux : en fin de course la piste s'est décalée d'une
   série, il faut donc qu'il en reste au moins une largeur d'écran à droite.
   Avec deux séries, un écran plus large qu'une série verrait un trou. Avec
   trois, la marge couvre tous les écrans courants. */
@keyframes defile {
  from { transform: translateX(0); }
  to   { transform: translateX(-33.3333%); }
}

/* On s'arrête pour laisser lire un logo */
.bandeau:hover .bandeau-piste,
.bandeau:focus-within .bandeau-piste {
  animation-play-state: paused;
}

/* --------------------------------------------------------------------------
   8. Menu plein écran — les entrées entrent en cascade
   -------------------------------------------------------------------------- */
.js .menu-plein li,
.js .menu-plein .menu-logo {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--anim-courbe), transform 0.6s var(--anim-courbe);
}
.js .menu-plein.est-ouvert li,
.js .menu-plein.est-ouvert .menu-logo {
  opacity: 1;
  transform: none;
}

/* Le logo entre le premier, la navigation suit */
.js .menu-plein.est-ouvert .menu-logo { transition-delay: 0.05s; }
.js .menu-plein.est-ouvert li:nth-child(1) { transition-delay: 0.08s; }
.js .menu-plein.est-ouvert li:nth-child(2) { transition-delay: 0.14s; }
.js .menu-plein.est-ouvert li:nth-child(3) { transition-delay: 0.20s; }
.js .menu-plein.est-ouvert li:nth-child(4) { transition-delay: 0.26s; }

/* --------------------------------------------------------------------------
   Respect du réglage système « réduire les animations »
   Tout est neutralisé : le contenu s'affiche, immobile.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .js .mot-i,
  .js .media-volet,
  .js .media-volet img,
  .js .menu-plein li,
  .js .menu-plein .menu-logo {
    transform: none !important;
    clip-path: none !important;
    opacity: 1 !important;
    transition: none !important;
  }

  .js .hero-media img,
  .js .hero-media video,
  .js .hero-accroche,
  .js .hero-pied,
  .js .hero-page .label {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }

  .js .secteur-texte p { opacity: 1 !important; transform: none !important; }
  .bouton::before { display: none; }
  .parallaxe { transform: none !important; }

  /* Le bandeau ne défile plus : il devient une bande que l'on fait glisser
     à la main. La série en double ferait doublon, on la retire. */
  .bandeau-piste { animation: none !important; transform: none !important; }
  .bandeau { overflow-x: auto; }
  .bandeau-groupe[aria-hidden="true"] { display: none; }
}
