/* =============================================================
   arbusteo — reveal.css
   Animations sobres au scroll. Enrichit le moteur .reveal/.in
   existant (js/site.js) : un seul listener, throttlé en rAF,
   latché (« once »). On n'anime QUE opacity + transform → 0 CLS.

   L'état caché n'existe que sous .reveal-on (posée par le JS) :
   sans JS, ou si reduced-motion, tout reste à son état final.

   Régler l'intensité : modifier les variables ci-dessous.
   Désactiver une famille : retirer son bloc. Désactiver tout :
   prefers-reduced-motion (déjà géré plus bas).
   ============================================================= */

:root {
  --reveal-dur: 550ms;          /* durée d'entrée (M3 ~long2/long3)   */
  --reveal-shift: 18px;         /* montée verticale (fade + montée)   */
  --reveal-slide: 24px;         /* glissement latéral des mockups     */
  --reveal-scale: 0.985;        /* scale de départ des mockups        */
  --reveal-stagger: 90ms;       /* décalage entre cartes d'une grille */
}

/* ---------- 1. Base : fade + montée douce -----------------------------
   Étend le reveal transform-only de site.css en ajoutant le fondu.
   Cible : en-têtes, chapôs, cartes, blocs de contenu sous la flottaison. */
.reveal-on .reveal {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
  transition: opacity var(--reveal-dur) var(--ease-dec),
              transform var(--reveal-dur) var(--ease-dec);
}
.reveal-on .reveal.in {
  opacity: 1;
  transform: none;
}

/* ---------- Héros : jamais d'état caché --------------------------------
   Au-dessus de la flottaison : visible immédiatement, aucun impact LCP,
   pas de fade-in au chargement. */
.reveal-on .hero .reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---------- 2. Stagger des grilles de cartes --------------------------
   Confiance, Pour qui, IA. (Problème = .frag piloté par scrolltext.js,
   Valorisation = stagger propre dans valorisation.css : non touchés.) */
.reveal-on .guard-grid .card.reveal:nth-child(2),
.reveal-on .audience   .card.reveal:nth-child(2),
.reveal-on .ia-cards   .card.reveal:nth-child(2) { transition-delay: var(--reveal-stagger); }
.reveal-on .guard-grid .card.reveal:nth-child(3),
.reveal-on .ia-cards   .card.reveal:nth-child(3) { transition-delay: calc(var(--reveal-stagger) * 2); }
.reveal-on .guard-grid .card.reveal:nth-child(4) { transition-delay: calc(var(--reveal-stagger) * 3); }
.reveal-on .guard-grid .card.reveal:nth-child(5) { transition-delay: calc(var(--reveal-stagger) * 4); }

/* ---------- 3a. Mockups centrés (Aperçu, IA) : montée + léger scale --- */
.reveal-on .pb-frame.reveal {
  transform: translateY(var(--reveal-shift)) scale(var(--reveal-scale));
}
.reveal-on .pb-frame.reveal.in {
  transform: none;
}

/* ---------- 3b. Parcours : texte (montée) + visuel (glissement) -------
   Le conteneur .step ne bouge pas en bloc ; on anime ses deux colonnes
   séparément pour un mouvement plus parlant. */
.reveal-on #parcours .step.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
.reveal-on #parcours .step .step-text,
.reveal-on #parcours .step .step-visual {
  opacity: 0;
  transform: translateY(var(--reveal-shift));   /* mobile : montée simple */
  transition: opacity var(--reveal-dur) var(--ease-dec),
              transform var(--reveal-dur) var(--ease-dec);
}
.reveal-on #parcours .step.reveal.in .step-text,
.reveal-on #parcours .step.reveal.in .step-visual {
  opacity: 1;
  transform: none;
}

/* Desktop : le visuel glisse depuis SON côté (alternance gauche/droite,
   calée sur le :nth-child de sections.css : impair = visuel à droite). */
@media (min-width: 861px) {
  .reveal-on #parcours .step:nth-child(odd)  .step-visual { transform: translateX(var(--reveal-slide)); }
  .reveal-on #parcours .step:nth-child(even) .step-visual { transform: translateX(calc(-1 * var(--reveal-slide))); }
}
/* le glissement latéral ne doit jamais créer de scroll horizontal */
#parcours { overflow-x: clip; }

/* ---------- 4. Fil du parcours qui se remplit au scroll ---------------
   ::before (site CSS) = piste pointillée. ::after = trait plein qui se
   remplit du haut vers le bas via scaleY (--thread-fill piloté par
   site.js). Sans JS / reduced-motion → fil plein (fallback 1). */
.parcours-thread::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  width: 2px;
  height: 100%;
  background: var(--olive);
  transform: translateX(-50%) scaleY(var(--thread-fill, 1));
  transform-origin: top center;
  opacity: 0.85;
  z-index: 1;            /* au-dessus de la piste, sous les nœuds (z:2) */
}
/* Mobile : le fil plein suit la piste (::before) et les nœuds, calés à
   gauche (left:27px dans sections.css). Sans cette surcharge il resterait
   centré à 50 % alors que la piste passe à gauche. Breakpoint identique
   à sections.css (max-width:860px). */
@media (max-width: 860px) {
  .parcours-thread::after { left: 27px; }
}
/* nœud qui s'allume quand son étape est révélée (transform + opacity) */
.step-node::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--green-deep);
  opacity: 0;
  transform: scale(0.5);
  transition: opacity var(--reveal-dur) var(--ease-dec),
              transform var(--reveal-dur) var(--ease-dec);
}
.reveal-on #parcours .step.reveal.in .step-node::after {
  opacity: 1;
  transform: scale(1);
}

/* ---------- Accessibilité : réduction de mouvement -------------------
   Tout apparaît immédiatement dans son état final, aucune animation. */
@media (prefers-reduced-motion: reduce) {
  .reveal-on .reveal,
  .reveal-on .reveal.in,
  .reveal-on .pb-frame.reveal,
  .reveal-on .pb-frame.reveal.in,
  .reveal-on #parcours .step .step-text,
  .reveal-on #parcours .step .step-visual,
  .reveal-on #parcours .step.reveal.in .step-text,
  .reveal-on #parcours .step.reveal.in .step-visual {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .reveal-on .guard-grid .card.reveal,
  .reveal-on .audience   .card.reveal,
  .reveal-on .ia-cards   .card.reveal { transition-delay: 0s !important; }
  .parcours-thread::after { transform: translateX(-50%) scaleY(1) !important; }
  .step-node::after { opacity: 1 !important; transform: scale(1) !important; transition: none !important; }
}

/* =============================================================
   GENÈSE (genese.html) — mêmes effets sobres que l'accueil, calés
   sur la structure propre à cette page (figure-block, converge-grid,
   frise). Même moteur .reveal/.in, mêmes variables. Le héros est
   exclu de tout état caché (au-dessus de la flottaison / LCP).
   ============================================================= */

/* ---------- Héros : visible immédiatement, aucun fondu au chargement -- */
.reveal-on .genese-hero .reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---------- Stagger des cartes de convergence ------------------------
   Grille 2 colonnes : la carte de droite de chaque rangée entre
   juste après celle de gauche. */
.reveal-on .converge-grid .card.reveal:nth-child(even) {
  transition-delay: var(--reveal-stagger);
}

/* ---------- Blocs portrait : portrait + contenu animés séparément ----
   On n'anime pas le bloc en entier : le portrait glisse depuis SON côté
   (alternance normal/reverse, calée sur l'ordre de grille de genese.css),
   le contenu monte un cran après. Mobile : tout monte simplement. */
.reveal-on .figure-block.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
.reveal-on .figure-block .figure-portrait,
.reveal-on .figure-block .figure-content {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
  transition: opacity var(--reveal-dur) var(--ease-dec),
              transform var(--reveal-dur) var(--ease-dec);
}
.reveal-on .figure-block .figure-content { transition-delay: var(--reveal-stagger); }
.reveal-on .figure-block.reveal.in .figure-portrait,
.reveal-on .figure-block.reveal.in .figure-content {
  opacity: 1;
  transform: none;
}
/* le glissement latéral ne doit jamais créer de scroll horizontal */
.figure-block { overflow-x: clip; }

/* Desktop : le portrait glisse depuis son côté (normal = gauche,
   reverse = droite). Le .in remet transform:none (règle ci-dessus,
   plus spécifique → l'emporte). */
@media (min-width: 881px) {
  .reveal-on .figure-block .figure-portrait {
    transform: translateY(var(--reveal-shift)) translateX(calc(-1 * var(--reveal-slide)));
  }
  .reveal-on .figure-block.reverse .figure-portrait {
    transform: translateY(var(--reveal-shift)) translateX(var(--reveal-slide));
  }
}

/* ---------- Frise chronologique : cascade des étapes -----------------
   La frise entre en un bloc ; ses étapes se révèlent en cascade
   (gauche→droite en desktop, haut→bas en mobile). La piste pointillée
   (::before) reste fixe, comme le fil de l'accueil. */
.reveal-on .frise.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
.reveal-on .frise .frise-step {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
  transition: opacity var(--reveal-dur) var(--ease-dec),
              transform var(--reveal-dur) var(--ease-dec);
}
.reveal-on .frise.reveal.in .frise-step { opacity: 1; transform: none; }
.reveal-on .frise.reveal.in .frise-step:nth-child(2) { transition-delay: var(--reveal-stagger); }
.reveal-on .frise.reveal.in .frise-step:nth-child(3) { transition-delay: calc(var(--reveal-stagger) * 2); }
.reveal-on .frise.reveal.in .frise-step:nth-child(4) { transition-delay: calc(var(--reveal-stagger) * 3); }

/* ---------- Accessibilité : réduction de mouvement (genèse) ----------
   Les blocs .reveal génériques sont déjà couverts par le garde plus haut ;
   ici on neutralise les enfants animés et les délais propres à la genèse. */
@media (prefers-reduced-motion: reduce) {
  .reveal-on .figure-block .figure-portrait,
  .reveal-on .figure-block .figure-content,
  .reveal-on .figure-block.reveal.in .figure-portrait,
  .reveal-on .figure-block.reveal.in .figure-content,
  .reveal-on .frise .frise-step,
  .reveal-on .frise.reveal.in .frise-step {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0s !important;
  }
  .reveal-on .converge-grid .card.reveal:nth-child(even) { transition-delay: 0s !important; }
}
