/* ============================================================
   KLYVEA — Transitions inter-pages : Morphose
   ============================================================

   Stratégie duale :
   ① Navigateurs modernes (Chrome 126+, Edge 126+, Safari 18+)
      → View Transitions API multi-pages (MPA).
        Les éléments communs « morphent » fluidement entre pages.
        Les sections propres à chaque page apparaissent/disparaissent
        en fondu + léger glissement.
   ② Firefox et navigateurs sans support
      → Voile de bruit JS (système existant, inchangé).
        Le site fonctionne sans aucune casse.

   Accessibilité : prefers-reduced-motion désactive toutes
   les animations de transition.

   Courbes d'easing — philosophie iOS (v2) :
     ease-out-ios  cubic-bezier(0.25, 0.46, 0.45, 0.94)  arrivée posée
     ease-in-ios   cubic-bezier(0.55, 0.055, 0.675, 0.19) départ vif
     ease-spring   cubic-bezier(0.34, 1.56, 0.64, 1.0)   spring + overshoot
     ease-fluid    cubic-bezier(0.4, 0.0, 0.2, 1.0)       Material Design neutre
   ============================================================ */


/* ── 1. Activation des transitions multi-pages ─────────────
   @view-transition { navigation: auto } demande au navigateur
   d'envelopper chaque navigation interne dans une View Transition.
   Les navigateurs sans support ignorent cette règle silencieusement. */

@view-transition {
  navigation: auto;
}


/* ── 2. Noms de transition — éléments structurels communs ───
   Ces propriétés s'appliquent via les classes CSS partagées.
   Règle d'unicité : un view-transition-name = un seul élément par page.
   Les noms page-title et page-eyebrow sont ajoutés en style inline
   dans chaque HTML (ils varient par page).                          */

@supports (view-transition-name: none) {

  /* Logo + nom "KLYVEA" — paraît immobile (même position partout) */
  .header-brand {
    view-transition-name: brand;
  }

  /* Liens de navigation — immobile */
  .site-nav {
    view-transition-name: nav;
  }

  /* Bouton "Audit gratuit" dans le header — immobile */
  .header-cta {
    view-transition-name: header-cta;
  }

  /* Pied de page complet — immobile */
  .site-footer {
    view-transition-name: footer;
  }

  /* nav-toggle (hamburger mobile) — immobile */
  .nav-toggle {
    view-transition-name: nav-toggle;
  }

} /* fin @supports noms structurels */


/* ── 3. Groupes — durées et courbes iOS ─────────────────────
   Le groupe contrôle l'interpolation de la boîte (position + taille)
   entre la capture sortante et la capture entrante.

   Règle iOS : sortie plus courte (280ms) que l'entrée (420-500ms).
   Le spring (overshoot 1.56) sur les morphs principaux donne la
   sensation de physique réelle — l'élément dépasse légèrement sa
   cible puis revient, perçu comme naturel par le cerveau.          */

@supports (view-transition-name: none) {

  /* ── Contrainte de débordement — uniquement sur les éléments qui
     ne doivent pas déborder. Exclure intentionnellement page-title
     et page-eyebrow : l'overshoot du spring (cubic-bezier 1.56)
     doit pouvoir s'exprimer visuellement sur le H1.               */
  ::view-transition-group(footer),
  ::view-transition-group(nav),
  ::view-transition-group(brand),
  ::view-transition-group(header-cta),
  ::view-transition-group(nav-toggle) {
    overflow: clip;
  }

  /* ── Morphs principaux : spring iOS — départ vif, légère surtension */
  /* cubic-bezier(0.34, 1.56, 0.64, 1.0) — le 1.56 crée l'overshoot   */

  ::view-transition-group(brand) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1.0);
  }

  ::view-transition-group(nav) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1.0);
  }

  ::view-transition-group(header-cta) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1.0);
  }

  /* H1 : le morph le plus visible — spring complet */
  ::view-transition-group(page-title) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1.0);
  }

  /* Eyebrow : suit le H1, décélération iOS */
  ::view-transition-group(page-eyebrow) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  }

  /* ── Éléments ancrés : neutre Material Design — plus posé */
  /* cubic-bezier(0.4, 0.0, 0.2, 1.0) — fluide, sans overshoot         */

  ::view-transition-group(footer) {
    animation-duration: 380ms;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1.0);
  }

  ::view-transition-group(nav-toggle) {
    animation-duration: 380ms;
    animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1.0);
  }

} /* fin @supports groupes */


/* ── 4. Snapshots — animations des contenus ─────────────────
   Les pseudo-éléments ::view-transition-old/new contiennent la
   capture visuelle de l'élément. Ils animent le CONTENU pendant
   que le groupe déplace la boîte.

   Asymétrie iOS :
     - Sortie rapide (260-280ms) avec ease-in vif
     - Entrée lente (350-440ms) avec ease-out posé + délai stagger
   Ce décalage crée la sensation que la page "se pose" naturellement. */

@supports (view-transition-name: none) {

  /* ── Valeur fill-mode globale (empêche les flashs entre états) ── */
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-fill-mode: both;
  }

  /* ── Défauts globaux iOS ── */
  /* Sortie : encore plus vive — 200ms. La sortie doit être quasi-invisible,
     l'attention du cerveau se porte sur l'arrivée.                          */
  ::view-transition-old(*) {
    animation-duration: 200ms;
    animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
  }

  /* Entrée : expo-out — départ fulgurant, très longue décélération (500ms).
     cubic-bezier(0.16, 1, 0.3, 1) est l'easing le plus proche du spring
     iOS natif exprimable en cubic-bezier — utilisé par Framer Motion.       */
  ::view-transition-new(*) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  }

  /* ── Root (contenu non nommé) : désactivé ──────────────────────
     Les animations individuelles par élément (H1, eyebrow, cards JS)
     suffisent pour la fluidité. Le root animé crée un flash global
     qui casse la perception de continuité.                          */
  ::view-transition-old(root) {
    animation: none;
  }

  ::view-transition-new(root) {
    animation: none;
  }

  /* ── Eyebrow : drop depuis le haut + micro-blur, stagger 0ms ──
     Premier élément à se révéler. Arrive depuis -8px (léger drop)
     avec un blur 2px → 0 qui donne une sensation de "focus".        */
  ::view-transition-old(page-eyebrow) {
    animation: klv-slide-up-out 200ms cubic-bezier(0.55, 0.055, 0.675, 0.19) 0ms both;
  }

  ::view-transition-new(page-eyebrow) {
    animation: klv-fade-drop-in 380ms cubic-bezier(0.25, 0.46, 0.45, 0.94) 0ms both;
  }

  /* ── H1 titre : drop-in + spring, stagger +30ms ─────────────────
     Le groupe déplace la boîte en spring (effet "wow") ;
     le snapshot fait un drop depuis -8px avec blur — direction
     cohérente avec le scroll to top (contenu vient du dessus).
     30ms de délai après l'eyebrow.                                  */
  ::view-transition-old(page-title) {
    animation: klv-slide-up-out 260ms cubic-bezier(0.55, 0.055, 0.675, 0.19) 0ms both;
  }

  ::view-transition-new(page-title) {
    animation: klv-fade-drop-in 460ms cubic-bezier(0.34, 1.56, 0.64, 1.0) 30ms both;
  }

  /* ── Éléments immobiles : cross-fade très court ─────────────────
     Ces éléments sont à la même position sur toutes les pages —
     on veut juste un croisement rapide, pas une animation visible.  */

  ::view-transition-old(brand),
  ::view-transition-new(brand) {
    animation-duration: 160ms;
    animation-timing-function: ease;
  }

  ::view-transition-old(nav),
  ::view-transition-new(nav) {
    animation-duration: 160ms;
    animation-timing-function: ease;
  }

  ::view-transition-old(header-cta),
  ::view-transition-new(header-cta) {
    animation-duration: 160ms;
    animation-timing-function: ease;
  }

  ::view-transition-old(footer),
  ::view-transition-new(footer) {
    animation-duration: 260ms;
    animation-timing-function: ease;
  }

} /* fin @supports snapshots */


/* ── 5. Keyframes ───────────────────────────────────────────
   Distances de déplacement intentionnellement courtes (≤ 18px) :
   iOS ne déplace jamais les éléments de plus de 20-30px.
   Au-delà, le mouvement devient mécanique et artificiel.           */

/* Sortie : glissement vers le haut + micro-blur
   Direction vers le haut — cohérente avec l'arrivée du contenu entrant.
   Blur à la sortie adoucit la coupure entre les deux états.              */
@keyframes klv-slide-up-out {
  from {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0px);
  }
  to {
    opacity: 0;
    transform: translateY(-6px);
    filter: blur(1px);
  }
}

/* Entrée : léger drop depuis le haut + micro-blur entrant
   Le contenu « tombe » depuis -8px (jamais depuis le bas après scroll to top).
   blur(2px) → blur(0) renforce la sensation de mise au point progressive.    */
@keyframes klv-fade-drop-in {
  from {
    opacity: 0;
    transform: translateY(-8px);
    filter: blur(2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0px);
  }
}

/* Fondu sortant simple (eyebrow — le groupe gère le déplacement) */
@keyframes klv-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* Fondu entrant simple */
@keyframes klv-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Entrée en cascade des cartes de contenu
   Délai et stagger injectés par JS via pagereveal.
   Distance : 12px — cohérent avec klv-slide-up-in.                 */
@keyframes klv-card-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}


/* ── 6. Accessibilité : prefers-reduced-motion ──────────────
   Désactive intégralement toutes les animations View Transitions
   si l'utilisateur a activé la préférence de mouvement réduit.
   La navigation reste fonctionnelle, juste instantanée.            */

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
  ::view-transition-group(*) {
    animation-duration: 0ms !important;
  }
}


/* ══════════════════════════════════════════════════════════
   FALLBACK — Navigateurs sans View Transitions (Firefox…)
   ══════════════════════════════════════════════════════════
   Ces styles gèrent le "Voile de bruit" piloté par transitions.js.
   Ils coexistent sans conflit avec les styles VT ci-dessus.
   Sur les navigateurs avec VT, le JS n'instancie pas le voile.     */

/* Prévention du flash blanc à l'entrée de page
   Le flag [data-klv-entering] est posé par le <script> inline
   dans le <head> de chaque page, et retiré dès que le DOM est prêt. */
html[data-klv-entering] body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: all;
  background-color: #09090E;
  background-image: radial-gradient(
    ellipse 80% 60% at 50% 50%,
    rgba(91, 33, 182, 0.12) 0%,
    transparent 70%
  );
}

/* Voile principal (div créée dynamiquement par transitions.js) */
.page-veil {
  position: fixed;
  inset: 0;
  z-index: 10000;
  pointer-events: none;
  will-change: transform;
  transform: translateY(-100%);
  background-color: #09090E;
  background-image: radial-gradient(
    ellipse 80% 60% at 50% 50%,
    rgba(91, 33, 182, 0.12) 0%,
    rgba(30, 58, 138, 0.06) 40%,
    transparent 70%
  );
  overflow: hidden;
}

/* Grain film — texture animée sur le voile */
.page-veil::before {
  content: '';
  position: absolute;
  inset: -100px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
  opacity: 0.04;
  animation: klv-grain 0.16s steps(3) infinite;
  pointer-events: none;
}

/* Liseré lumineux sur le bord d'attaque du voile */
.page-veil::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 1.5px;
  background: linear-gradient(
    90deg,
    transparent  0%,
    #1E3A8A     12%,
    #7C3AED     38%,
    #A855F7     50%,
    #7C3AED     62%,
    #1E3A8A     88%,
    transparent 100%
  );
  box-shadow:
    0  0 10px  2px rgba(168, 85, 247, 0.55),
    0  0 30px  6px rgba(91,  33, 182, 0.22),
    0  0 60px 10px rgba(30,  58, 138, 0.12);
}

@keyframes klv-grain {
  0%   { transform: translate(  0px,  0px); }
  33%  { transform: translate( -5px,  2px); }
  66%  { transform: translate(  3px, -4px); }
  100% { transform: translate( -2px,  5px); }
}

/* Sortie : le voile descend pour couvrir l'écran */
@keyframes klv-veil-in {
  from { transform: translateY(-100%); }
  to   { transform: translateY(0);     }
}

/* Entrée : le voile continue vers le bas, révélant la nouvelle page */
@keyframes klv-veil-out {
  from { transform: translateY(0);    }
  to   { transform: translateY(100%); }
}

.page-veil--exit {
  pointer-events: all;
  animation: klv-veil-in 280ms cubic-bezier(0.65, 0, 0.35, 1) forwards;
}

.page-veil--enter {
  pointer-events: all;
  animation: klv-veil-out 440ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* Micro-flash violet du logo au déclenchement de la navigation */
@keyframes klv-logo-flash {
  0%   { filter: none; }
  25%  { filter: drop-shadow(0 0 7px rgba(168, 85, 247, 0.85)) brightness(1.35); }
  100% { filter: none; }
}

.klv-logo-pulse {
  animation: klv-logo-flash 480ms ease-out forwards;
}

/* En mode reduced : désactiver les animations cosmétiques du fallback */
@media (prefers-reduced-motion: reduce) {
  .page-veil::before,
  .klv-logo-pulse {
    animation: none !important;
  }
}
