/* =============================================================================
   Charlotte Bard — animations.css (v1, 14/10/2026 ; premier écran « carte de visite » le 15/10/2026)
   Propriétaire : ANIMATIONS. Chargé après styles.css et avant css/reservation.css.

   Règles du contrat d'intégration :
   - tout état caché ou de départ est écrit sous .anim ET dans
     @media (prefers-reduced-motion: no-preference) : sans JS, en mouvement
     réduit ou si le chien de garde du <head> retire .anim, la page est complète
     et statique ;
   - propriétés animées : transform, opacity, clip-path et filter (léger) ;
   - espace de noms : classes d'état .anim-*, @keyframes anim-*, --anim-rang ;
   - .btn::before et .btn::after appartiennent à ce fichier.
   Classes d'état posées par js/animations.js : .anim-vu, .anim-instant,
   html.logo-heros-visible (aussi posée par le script du <head> d'index.html) ;
   attributs : html[data-animations], .barre-mobile[data-etat="visible"].
   Aucune boucle infinie (rien ne bouge plus de 5 s) : pas de bouton pause nécessaire.
   16/10/2026 : la galerie « En live » est passée dans css/stories.css, l'apparition du prénom dans
   css/plume.css, celle des taches dans css/aquarelle.css (voir le README, « Chorégraphie »).
   ============================================================================= */


/* -----------------------------------------------------------------------------
   1. DÉCOR PERMANENT (tous les modes, y compris sans JS et mouvement réduit)
   ----------------------------------------------------------------------------- */

/* Filet des surtitres (28 × 1 px, couleur courante). Il ne s'anime que sous .anim. */
.surtitre::before {
  content: "";
  display: inline-block;
  width: 28px;
  height: 1px;
  margin-right: 12px;
  vertical-align: .32em;
  background: currentColor;
  transform-origin: 0 50%;
}
/* Titres centrés : le filet passe au-dessus du texte, centré. Sur téléphone,
   il passe au-dessus partout (sinon « Bouches-du-Rhône » se coupe au trait d'union). */
.entete-centre .surtitre::before {
  display: block;
  margin: 0 auto 12px;
  transform-origin: 50% 50%;
}
@media (max-width: 560px) {
  .surtitre::before { display: block; margin: 0 0 10px; }
  .entete-centre .surtitre::before { margin: 0 auto 12px; }
}

/* Héros : chaque groupe du titre est une boîte en ligne (le texte reste
   lisible tel quel ; une boîte trop longue se replie sur elle-même). */
.titre-groupe > span { display: inline-block; }

/* Section Charlotte : la vraie guirlande de la terrasse (positions mesurées sur la photo 4:5). */
.ampoule {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 9%;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 236, 190, .95) 0 8%, rgba(255, 200, 120, .45) 30%, transparent 70%);
  mix-blend-mode: screen;
  opacity: .8;
  pointer-events: none;
}

/* Navigation : filet rose sous la rubrique en cours (créé par le JS, visible à partir de 901 px). */
.nav-liens { position: relative; }
.nav-filet {
  position: absolute;
  left: 0;
  bottom: -9px;
  width: 100px;
  height: 2px;
  border-radius: 2px;
  background: var(--rose, #B5675B);
  transform-origin: 0 50%;
  transform: scaleX(0);
  opacity: 0;
  pointer-events: none;
}
.nav-filet[data-actif] { opacity: 1; }
.nav-liens a[aria-current="true"] { color: var(--rose-fonce, #93574F); }

/* Déroulé : le trait entre les étapes devient doré (même spécificité que styles.css, chargé après). */
.etapes > li:not(:last-child)::after { background: var(--or, #C9A27A); transform-origin: 0 50%; }

/* Barre mobile : logique dans tous les modes. Sans js/animations.js
   (pas de html[data-animations]), elle reste visible comme avant. */
.barre-mobile { bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
html[data-animations] .barre-mobile:not([data-etat="visible"]) {
  transform: translateY(140%);
  opacity: 0;
  visibility: hidden;
}
/* Focus dans la demande de date ou dans le pied de page : le bouton fixe s'efface pour ne
   jamais couvrir le champ ou le lien actif (WCAG 2.4.11), avec ou sans JS. Ailleurs, c'est
   scroll-padding-bottom (styles.css) qui garde l'élément actif au-dessus du bouton. */
html:has(#date:focus-within, .pied:focus-within) .barre-mobile {
  transform: translateY(140%);
  opacity: 0;
  visibility: hidden;
}

/* En live : appel sous les arches (css/stories.css pour les arches) */
.live-appel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px 20px;
  margin: 40px 0 0;
  text-align: center;
  font-family: "Fraunces", "Fraunces Repli", Georgia, serif;
  font-size: 1.4rem;
  line-height: 1.3;
}


/* -----------------------------------------------------------------------------
   2. MOUVEMENT (seulement sous .anim, seulement sans préférence de mouvement réduit)
   ----------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {

  /* ---------- 2.1 Entrée du héros, en CSS pur ---------- */
  .anim .hero .surtitre { animation: anim-apparait .7s ease-out .05s backwards; }
  .anim .hero .surtitre::before { animation: anim-filet .8s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .2s backwards; }

  /* Groupes du titre : montée derrière un masque. Le clip-path accompagne la
     translation pour que le bord du masque reste presque fixe, avec des marges
     négatives qui ne coupent ni les jambages ni l'italique. */
  .anim .titre-groupe > span {
    animation: anim-leve .9s cubic-bezier(.2, .7, .15, 1) calc(.12s + var(--i, 0) * .11s) backwards;
  }
  /* « douce » sort d'un léger flou, comme une voix qui monte. */
  .anim .hero .slogan em { animation: anim-net .8s ease-out .55s backwards; }

  /* Chapo, boutons, atouts, badge : les boutons sont pleinement visibles vers 0,35 s.
     Jusqu'à 900 px, le portrait passe en tête (css/elle-d-abord.css) et devient l'élément LCP ; le
     chapo glisse quand même sans fondu (--anim-depart: 1), pour être lisible dès la première image.
     Le nom de l'animation ne change pas de part et d'autre de 900 px : franchir ce seuil (rotation,
     redimensionnement) ne la rejoue pas. */
  .anim .hero .chapo { animation: anim-monte .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .1s backwards; }
  @media (max-width: 900px) { .anim .hero .chapo { --anim-depart: 1; } }
  .anim .hero .actions { animation: anim-monte .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .14s backwards; }
  .anim .hero .atouts { animation: anim-monte .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .6s backwards; }
  .anim .hero-badge { animation: anim-monte .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) 1.1s backwards; }

  /* Barre de navigation de l'accueil : fondu entre la barre transparente (logotype du héros visible)
     et la barre papier ; le petit logo apparaît en fondu, puis disparaît en fondu avant d'être caché. */
  .anim .nav-heros { transition: background-color .3s ease-out, border-color .3s ease-out; }
  .anim .nav-heros .logo { transition: opacity .35s ease-out, visibility 0s; }
  .anim.logo-heros-visible .nav-heros .logo { transition: opacity .25s ease-out, visibility 0s linear .25s; }

  /* Section Charlotte : la photo de la terrasse passe du crépuscule à la lumière, puis les ampoules de la
     guirlande s'allument une à une, la lanterne en dernier. Une seule fois, sans boucle. */
  .anim [data-revele="photo"] img { transition: filter 1.6s cubic-bezier(.3, .6, .2, 1) .15s; }
  .anim [data-revele="photo"]:not(.anim-vu) img { filter: brightness(.6) saturate(.8); }
  .anim [data-revele="photo"]:not(.anim-vu) .ampoule { opacity: 0; }
  .anim [data-revele="photo"].anim-vu .ampoule { animation: anim-filament .5s linear calc(.8s + var(--i, 0) * .22s) both; }
  .anim [data-revele="photo"].anim-instant img { transition: none; }
  .anim [data-revele="photo"].anim-instant .ampoule { animation: none; }

  /* ---------- 2.2 Révélations (une seule fois) ---------- */
  /* Blocs : montée en cascade (--anim-rang de 0 à 4, posé par le JS). */
  .anim [data-revele="bloc"] {
    transition:
      opacity .7s ease-out calc(var(--anim-rang, 0) * 90ms),
      transform .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) calc(var(--anim-rang, 0) * 90ms);
  }
  .anim [data-revele="bloc"]:not(.anim-vu) { opacity: 0; transform: translateY(24px); }

  /* Titres : le h2 se lève comme un rideau, puis le mot fort sort du flou. */
  .anim [data-revele="titre"] h2 {
    clip-path: inset(-.3em -.5em -.25em -.5em);
    transition:
      clip-path .9s cubic-bezier(.2, .65, .15, 1),
      transform .9s cubic-bezier(.2, .65, .15, 1);
  }
  .anim [data-revele="titre"]:not(.anim-vu) h2 {
    clip-path: inset(0 -.5em 100% -.5em);
    transform: translateY(.3em);
  }
  .anim [data-revele="titre"] h2 em { transition: opacity .8s ease-out .15s, filter .8s ease-out .15s; }
  .anim [data-revele="titre"]:not(.anim-vu) h2 em { opacity: 0; filter: blur(5px); }
  .anim [data-revele="titre"] .surtitre { transition: opacity .6s ease-out; }
  .anim [data-revele="titre"]:not(.anim-vu) .surtitre { opacity: 0; }
  .anim [data-revele="titre"] .surtitre::before { transition: transform .8s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .1s; }
  .anim [data-revele="titre"]:not(.anim-vu) .surtitre::before { transform: scaleX(0); }
  /* Autres enfants du titre (chapo, chiffre…) : 200 ms plus tard. */
  .anim [data-revele="titre"] > :not(h2):not(.surtitre):not(div),
  .anim [data-revele="titre"] > div > :not(h2):not(.surtitre) {
    transition: opacity .7s ease-out .2s, transform .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) .2s;
  }
  .anim [data-revele="titre"]:not(.anim-vu) > :not(h2):not(.surtitre):not(div),
  .anim [data-revele="titre"]:not(.anim-vu) > div > :not(h2):not(.surtitre) {
    opacity: 0;
    transform: translateY(12px);
  }

  /* Déroulé : le trait doré se trace à l'apparition de chaque étape. */
  .anim .etapes > li::after {
    transition: transform .6s var(--courbe, cubic-bezier(.2, .7, .2, 1)) calc(.3s + var(--anim-rang, 0) * 150ms);
  }
  .anim .etapes > li[data-revele]:not(.anim-vu)::after { transform: scaleX(0); }

  /* Révélé sans transition (déjà passé au-dessus, focus clavier, chien de garde). */
  .anim .anim-instant,
  .anim .anim-instant h2,
  .anim .anim-instant h2 em,
  .anim .anim-instant .surtitre,
  .anim .anim-instant .surtitre::before,
  .anim .anim-instant > :not(h2):not(.surtitre):not(div),
  .anim .anim-instant > div > :not(h2):not(.surtitre),
  .anim .etapes > li.anim-instant::after { transition: none !important; }

  /* ---------- 2.4 Lueur des boutons pleins ---------- */
  .anim .btn:not(.btn-ligne):not(.btn-fantome) {
    position: relative;
    overflow: hidden;
    isolation: isolate;
  }
  .anim .btn:not(.btn-ligne):not(.btn-fantome)::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: -1;
    width: 40%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .35), transparent);
    transform: translateX(-120%) skewX(-12deg);
    pointer-events: none;
  }
  .anim .btn:not(.btn-ligne):not(.btn-fantome):focus-visible::after {
    transform: translateX(420%) skewX(-12deg);
    transition: transform .9s var(--courbe, cubic-bezier(.2, .7, .2, 1));
  }
  @media (hover: hover) {
    .anim .btn:not(.btn-ligne):not(.btn-fantome):hover::after {
      transform: translateX(420%) skewX(-12deg);
      transition: transform .9s var(--courbe, cubic-bezier(.2, .7, .2, 1));
    }
  }

  /* ---------- 2.5 Barre mobile et filet de navigation ---------- */
  .anim .barre-mobile {
    transition:
      transform .35s var(--courbe, cubic-bezier(.2, .7, .2, 1)),
      opacity .35s ease-out,
      visibility .35s;
  }
  .anim .nav-filet { transition: transform .4s var(--courbe, cubic-bezier(.2, .7, .2, 1)), opacity .3s ease-out; }

  /* ---------- 2.6 Identité de la carte de visite (15/10/2026) ---------- */
  /* Les occasions : cascade discrète, une occasion après l'autre (--i de 0 à 5 dans le HTML). */
  .anim .occasions-liste > [data-revele="bloc"] {
    transition:
      opacity .7s ease-out calc(var(--i, 0) * 80ms),
      transform .7s var(--courbe, cubic-bezier(.2, .7, .2, 1)) calc(var(--i, 0) * 80ms);
  }
  .anim .occasions-liste > [data-revele="bloc"]:not(.anim-vu) { transform: translateY(14px); }

  /* Notes de musique du héros : elles montent une à une, comme une mélodie
     (--n de 0 à 4 dans le HTML). Opacité et translation seulement, sur des <g> sans attribut transform. */
  .anim [data-revele="notes"] .note {
    transition:
      opacity .6s ease-out calc(.3s + var(--n, 0) * 130ms),
      transform .8s var(--courbe, cubic-bezier(.2, .7, .2, 1)) calc(.3s + var(--n, 0) * 130ms);
  }
  .anim [data-revele="notes"]:not(.anim-vu) .note { opacity: 0; transform: translateY(10px); }
  .anim [data-revele="notes"].anim-instant .note { transition: none !important; }

  /* ---------- 2.7 Chorégraphie du premier écran (16/10/2026) ----------
     Quatre effets partent ensemble au premier rendu et s'enchaînent ; tout est immobile vers 2,3 s
     (README, « Chorégraphie du premier écran ») :
       0,1 → 1,9 s   la goutte d'aquarelle tombe, s'étale puis sèche (js/aquarelle.js ; petite tache à +0,35 s) ;
       0,08 → 1,18 s le cadre or du portrait se trace (js/elle-d-abord.js), puis son reflet de 1,2 à 2 s ;
       0,11 → 1,31 s « Charlotte » s'écrit (css/plume.css), barre des t 1,38 → 1,51 s ;
       0,81 → 1,89 s BARD se resserre, le cœur tombe, le filet se déroule, CHANTEUSE apparaît ;
       1,75 → 2,25 s le reflet doré passe sur le filet, puis sur le cœur (1,85 → 2,15 s), en dernier.
     Le texte n'attend rien : titre lisible vers 0,5 s, boutons vers 0,35 s.
     Réglages : --plume-echelle et --plume-depart ici ; TEMPS en tête de js/elle-d-abord.js (garder le
     reflet du filet vers la fin du déroulé du filet : 1 480 × échelle + 600 × échelle). */
  .anim .hero { --plume-echelle: .9; }
}


/* -----------------------------------------------------------------------------
   3. IMAGES CLÉS
   ----------------------------------------------------------------------------- */
@keyframes anim-apparait { from { opacity: 0; } }
@keyframes anim-filet { from { transform: scaleX(0); } }
@keyframes anim-leve {
  from {
    transform: translateY(105%);
    clip-path: inset(-.3em -.3em 100% -.3em);
  }
  to {
    transform: none;
    clip-path: inset(-.3em -.3em -.35em -.3em);
  }
}
@keyframes anim-net { from { opacity: 0; filter: blur(6px); } }
/* --anim-depart : opacité de départ (0 par défaut ; 1 pour le chapo du héros sous 900 px, voir plus haut) */
@keyframes anim-monte {
  from { opacity: var(--anim-depart, 0); transform: translateY(12px); }
  30% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
@keyframes anim-filament {
  0% { opacity: 0; }
  30% { opacity: .9; }
  55% { opacity: .25; }
  100% { opacity: 1; }
}


/* -----------------------------------------------------------------------------
   4. IMPRESSION : tout visible, sans masque ni déplacement
   ----------------------------------------------------------------------------- */
@media print {
  .anim *,
  .anim *::before,
  .anim *::after { animation: none !important; transition: none !important; }
  .anim [data-revele],
  .anim [data-revele] h2,
  .anim [data-revele] h2 em,
  .anim [data-revele] .surtitre,
  .anim [data-revele] > *,
  .anim [data-revele] > div > *,
  .anim .titre-groupe > span,
  .anim [data-revele] img,
  .anim [data-revele] svg,
  .anim [data-revele] .note,
  .anim .logotype-prenom {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    filter: none !important;
  }
  .surtitre::before,
  .etapes > li::after { transform: none !important; }
  .ampoule,
  .nav-filet { display: none !important; }
}
