/*
  Motion Design (site A) — animations.css — version 5 (mise en ligne, 21/09/2026)
  Entrées du haut de page et boucles discrètes.
  Principe : sans JavaScript, rien n'est masqué ni animé. Le script de tête pose data-motion="full" avant le
  premier dessin ; les entrées ci-dessous ne jouent qu'avec ce repère.

  Version 5 : plus de mode d'animation réduit (décision de l'utilisateur, 21/09/2026). Le réglage
  « animations coupées » du système (Windows, macOS…) n'est plus suivi : tous les visiteurs voient le site
  animé. Le bandeau des clients garde son bouton pause.

  Version 4 : l'entrée du haut de page (barre, titre mot à mot, chapeau, boutons, films de la vitrine) est
  passée de GSAP au CSS. Elle démarre au premier affichage au lieu d'attendre le chargement de sept scripts :
  le titre et le chapeau, qui font le LCP, apparaissent 1 à 2 secondes plus tôt sur téléphone (mesuré à
  4,5 s dans Lighthouse avant ce changement). Mêmes mouvements, mêmes durées, mêmes courbes qu'en v3.
  « backwards » : l'état de départ tient pendant le délai, puis l'animation ne pèse plus sur rien.
*/

:root {
  --sortie-3: cubic-bezier(0.215, 0.61, 0.355, 1); /* équivalent de power3.out (GSAP) */
  --sortie-4: cubic-bezier(0.165, 0.84, 0.44, 1); /* équivalent de power4.out */
}

@keyframes entree-monter {
  from {
    opacity: 0;
    transform: translateY(var(--depart, 22px));
  }
}

@keyframes entree-descendre {
  from {
    opacity: 0;
    transform: translateY(-30px);
  }
}

@keyframes entree-poser {
  from {
    opacity: 0;
    transform: translateY(40px) scale(0.94);
  }
}

@keyframes entree-fondu {
  from {
    opacity: 0;
  }
}

/* Barre d'en-tête (toutes les pages) : elle descend */
[data-motion="full"] .entete__barre {
  animation: entree-descendre 0.8s var(--sortie-3) 0.1s backwards;
}

/* Ouverture de l'accueil : surtitre, titre mot à mot (mots découpés dans le HTML, --i = rang du mot),
   puis chapeau, boutons et preuves */
.mot-titre {
  display: inline-block;
}

[data-motion="full"] .ouverture .surtitre {
  animation: entree-monter 0.7s var(--sortie-3) 0.2s backwards;
}

[data-motion="full"] .ouverture__titre .mot-titre {
  --depart: 46px;
  animation: entree-monter 0.9s var(--sortie-4) calc(0.28s + var(--i, 0) * 0.05s) backwards;
}

[data-motion="full"] .ouverture__chapeau {
  animation: entree-monter 0.8s var(--sortie-3) 0.55s backwards;
}

[data-motion="full"] .ouverture__actions {
  animation: entree-monter 0.8s var(--sortie-3) 0.65s backwards;
}

[data-motion="full"] .ouverture__preuves {
  animation: entree-monter 0.8s var(--sortie-3) 0.75s backwards;
}

/* Téléphone : le chapeau est le plus grand bloc de texte du premier écran, donc l'élément du LCP. Le texte
   est là dès le premier affichage ; seul le titre entre, mot à mot (Lighthouse mobile : LCP 4,2 s quand le
   chapeau attendait 0,55 s d'animation). */
@media (max-width: 860px) {
  [data-motion="full"] .ouverture .surtitre,
  [data-motion="full"] .ouverture__chapeau,
  [data-motion="full"] .ouverture__actions,
  [data-motion="full"] .ouverture__preuves {
    animation: none;
  }
}

/* Films de la vitrine : ils se posent devant la lumière, puis respirent lentement (jamais plus de 6 px).
   La respiration anime « translate », l'entrée « transform » : les deux ne se gênent pas. */
@keyframes flotter {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: 0 -6px;
  }
}

/* Vidéo de vente du héros (30/09/2026) : elle se pose au premier affichage. Le bento des trois films, passé dans la
   section suivante, entre au défilement (data-revele, animations.js). */
[data-motion="full"] .heros-vente__film {
  animation: entree-poser 1.1s var(--sortie-3) 0.4s backwards;
}

/* Pages intérieures : les éléments du titre de page montent l'un après l'autre */
[data-motion="full"] .edito--tete .edito__corps > * {
  --depart: 26px;
  animation: entree-monter 0.8s var(--sortie-3) 0.15s backwards;
}

[data-motion="full"] .edito--tete .edito__corps > :nth-child(2) {
  animation-delay: 0.23s;
}

[data-motion="full"] .edito--tete .edito__corps > :nth-child(3) {
  animation-delay: 0.31s;
}

[data-motion="full"] .edito--tete .edito__corps > :nth-child(4) {
  animation-delay: 0.39s;
}

[data-motion="full"] .edito--tete .edito__corps > :nth-child(n + 5) {
  animation-delay: 0.47s;
}

/* Point de lecture qui bat au rythme d'un film qui tourne. L'anneau est un pseudo-élément animé en
   transform et opacity, que la carte graphique compose seule : l'ancienne animation de box-shadow
   faisait repeindre la vitrine 60 fois par seconde (trace du 21/09/2026). Même anneau : 13 → 19 px,
   opacité 0,18 → 0,05. */
@keyframes battre {
  0%,
  100% {
    transform: scale(0.85);
    opacity: 1;
  }
  50% {
    transform: scale(1.3);
    opacity: 0.3;
  }
}

.point-lecture {
  position: relative;
}

[data-motion="full"] .point-lecture {
  box-shadow: none;
}

[data-motion="full"] .point-lecture::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: rgba(228, 225, 53, 0.18);
  animation: battre 1.6s ease-in-out infinite;
}

/* Courbe du laboratoire : le point parcourt la courbe signée (posé par animations.js) */
.courbe__trace {
  stroke-dasharray: 520;
  stroke-dashoffset: 0;
}

/* Boucles arrêtées hors écran */
.hors-ecran .point-lecture::after,
.hors-ecran .vitrine__film {
  animation-play-state: paused;
}

/* ============================================================================================
   Bandeau des clients (21/09/2026) : la piste défile de droite à gauche, sans fin (deux copies de la
   liste, translation de la moitié). Arrêt au survol, au clavier, par le bouton, et hors écran.
   ============================================================================================ */
@keyframes clients-defile {
  to {
    transform: translateX(-50%);
  }
}

/* 175 s le tour : c'est la vitesse lente, celle du survol, 20,5 px/s à 1536 px (28/09/2026 ; recalée après la réduction
   des cartes verticales). Sans survol, js/main.js la multiplie par 1,4 (demande de l'utilisateur : « augmente un peu la
   vitesse ») ; sans JavaScript, le bandeau garde cette vitesse. */
.clients__defile {
  animation: clients-defile 175s linear infinite;
}

/* Logos des marques (28/09/2026) : de gauche à droite, plus lentement que les films. */
@keyframes marques-defile {
  from {
    transform: translateX(-50%);
  }

  to {
    transform: translateX(0);
  }
}

.marques__defile {
  animation: marques-defile 150s linear infinite;
}

@media (hover: hover) and (pointer: fine) {
  .marques:hover .marques__defile {
    animation-play-state: paused;
  }
}

.marques:has(:focus-visible) .marques__defile,
.marques[data-pause="1"] .marques__defile,
html:has(.lecteur[open]) .marques__defile,
.hors-ecran .marques__defile {
  animation-play-state: paused;
}

/* Le survol ne l'arrête plus (28/09/2026, demande de l'utilisateur) : il le ralentit seulement (js/main.js). Il
   s'arrête pendant qu'une vidéo est ouverte, par le bouton pause, hors écran, et pendant la navigation au clavier
   (touche Tab : html[data-clavier], posé par js/main.js) ; une vidéo fermée avec Échap ne le laisse plus arrêté. */
html[data-clavier] .clients__bandeau:has(:focus-visible) .clients__defile,
.clients__bandeau[data-pause="1"] .clients__defile,
html:has(.lecteur[open]) .clients__defile,
.hors-ecran .clients__defile {
  animation-play-state: paused;
}

/* ============================================================================================
   WhatsApp (21/09/2026) : le bouton arrive après le premier affichage (JavaScript actif) ;
   une onde part de l'icône toutes les trois secondes et le téléphone se balance brièvement, dans tous
   les cas, pour attirer l'œil.
   ============================================================================================ */
@keyframes whatsapp-entree {
  from {
    opacity: 0;
    /* 16 px : le bouton est à 18 px du bord ; à 28 px, il sortait de l'écran pendant son entrée et
       élargissait la page sur téléphone (corrigé le 25/09/2026) */
    transform: translateX(16px);
  }
}

@keyframes whatsapp-onde {
  0% {
    transform: scale(1);
    opacity: 0.6;
  }
  70%,
  100% {
    transform: scale(1.85);
    opacity: 0;
  }
}

@keyframes whatsapp-balance {
  0%,
  84%,
  100% {
    rotate: 0deg;
  }
  88% {
    rotate: -14deg;
  }
  92% {
    rotate: 12deg;
  }
  96% {
    rotate: -6deg;
  }
}

[data-motion="full"] .whatsapp {
  animation: whatsapp-entree 0.7s var(--sortie-3) 1.2s backwards;
}

.whatsapp__icone::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid #25d366;
  border-radius: 50%;
  animation: whatsapp-onde 3s var(--sortie-3) 2s infinite;
}

.whatsapp__icone svg {
  animation: whatsapp-balance 6s ease-in-out 2.5s infinite;
}

/* === LOGO : début — généré par tools/logo-site-a.mjs (ne pas modifier à la main) ===
   En boucle, sans fin, cycle de 7 s : la balle trace le « m » (135.41 unités de trait),
   rebondit au milieu, saute et se pose en point final ; les lettres du slogan montent une à une ; puis la
   scène se rembobine (le trait s'efface derrière la balle) et recommence. Les distances sont en unités du
   dessin (grille de 64), que le SVG met à l'échelle de l'icône. */
[data-motion="full"] .marque__trace {
  animation: logo-trace 7s linear infinite both;
}

[data-motion="full"] .marque__balle {
  animation: logo-balle 7s linear infinite both;
}

/* Crayon : il se dessine au-dessus du point une fois la balle posée, s'efface au rembobinage */
[data-motion="full"] .marque__crayon {
  animation: logo-crayon 7s linear infinite both;
}

/* Slogan : les lettres entrent une à une, de la droite vers la gauche (demande de l'utilisateur,
   25/09/2026), quand la balle se pose ; elles repartent vers la gauche avant le rembobinage. */
[data-motion="full"] .marque__slogan span {
  animation: logo-slogan 7s var(--ease-sortie) calc(var(--i) * 0.045s) infinite both;
}

@keyframes logo-trace {
  0%,
  5% {
    stroke-dashoffset: 100;
    animation-timing-function: cubic-bezier(0.55, 0, 0.35, 1);
  }
  23.57% {
    stroke-dashoffset: 0;
  }
  85.71% {
    stroke-dashoffset: 0;
    animation-timing-function: cubic-bezier(0.6, 0, 0.3, 1);
  }
  96.43%,
  100% {
    stroke-dashoffset: 100;
  }
}

@keyframes logo-balle {
  0% { transform: translate(-40.25px, 1.75px) scale(1, 1); }
  5% { transform: translate(-40.25px, 1.75px) scale(1, 1); }
  5.42% { transform: translate(-40.25px, 1.67px) scale(1, 1); }
  5.84% { transform: translate(-40.25px, 1.42px) scale(1, 1); }
  6.27% { transform: translate(-40.25px, 0.99px) scale(1, 1); }
  6.69% { transform: translate(-40.25px, 0.36px) scale(1, 1); }
  7.11% { transform: translate(-40.25px, -0.5px) scale(1, 1); }
  7.53% { transform: translate(-40.25px, -1.6px) scale(1, 1); }
  7.95% { transform: translate(-40.25px, -2.98px) scale(1, 1); }
  8.38% { transform: translate(-40.25px, -4.67px) scale(1, 1); }
  8.8% { transform: translate(-40.25px, -6.7px) scale(1, 1); }
  9.22% { transform: translate(-40.25px, -9.11px) scale(1, 1); }
  9.64% { transform: translate(-40.25px, -11.95px) scale(1, 1); }
  10.06% { transform: translate(-40.25px, -15.28px) scale(1, 1); }
  10.49% { transform: translate(-40.25px, -19.15px) scale(1, 1); }
  10.91% { transform: translate(-39.92px, -23.58px) scale(1, 1); }
  11.33% { transform: translate(-36.73px, -27.43px) scale(1, 1); }
  11.75% { transform: translate(-31.13px, -27.82px) scale(1, 1); }
  12.18% { transform: translate(-26.97px, -23.2px) scale(1, 1); }
  12.6% { transform: translate(-26.75px, -16.16px) scale(1, 1); }
  13.02% { transform: translate(-26.75px, -8.66px) scale(1, 1); }
  13.44% { transform: translate(-26.75px, -0.95px) scale(1.12, 0.91); }
  13.86% { transform: translate(-26.75px, -3.21px) scale(1.02, 0.98); }
  14.29% { transform: translate(-26.75px, -10.57px) scale(1, 1); }
  14.71% { transform: translate(-26.75px, -17.46px) scale(1, 1); }
  15.13% { transform: translate(-26.37px, -23.73px) scale(1, 1); }
  15.55% { transform: translate(-22.57px, -27.74px) scale(1, 1); }
  15.97% { transform: translate(-17.59px, -27.8px) scale(1, 1); }
  16.4% { transform: translate(-14.19px, -24.94px) scale(1, 1); }
  16.82% { transform: translate(-13.25px, -21.1px) scale(1, 1); }
  17.24% { transform: translate(-13.25px, -17.56px) scale(1, 1); }
  17.66% { transform: translate(-13.25px, -14.45px) scale(1, 1); }
  18.08% { transform: translate(-13.25px, -11.72px) scale(1, 1); }
  18.51% { transform: translate(-13.25px, -9.34px) scale(1, 1); }
  18.93% { transform: translate(-13.25px, -7.26px) scale(1, 1); }
  19.35% { transform: translate(-13.25px, -5.46px) scale(1, 1); }
  19.77% { transform: translate(-13.25px, -3.91px) scale(1.01, 0.99); }
  20.19% { transform: translate(-13.25px, -2.59px) scale(1.03, 0.97); }
  20.62% { transform: translate(-13.25px, -1.48px) scale(1.07, 0.94); }
  21.04% { transform: translate(-13.25px, -0.56px) scale(1.12, 0.9); }
  21.46% { transform: translate(-13.25px, 0.19px) scale(1.16, 0.87); }
  21.88% { transform: translate(-13.25px, 0.78px) scale(1.18, 0.85); }
  22.31% { transform: translate(-13.25px, 1.22px) scale(1.19, 0.84); }
  22.73% { transform: translate(-13.25px, 1.52px) scale(1.2, 0.84); }
  23.15% { transform: translate(-13.25px, 1.69px) scale(1.2, 0.84); }
  23.57% { transform: translate(-13.25px, 1.75px) scale(1.2, 0.84); }
  23.98% { transform: translate(-12.3px, -0.38px) scale(1, 1); }
  24.39% { transform: translate(-11.36px, -2.2px) scale(1, 1); }
  24.8% { transform: translate(-10.41px, -3.72px) scale(1, 1); }
  25.2% { transform: translate(-9.46px, -4.92px) scale(1, 1); }
  25.61% { transform: translate(-8.52px, -5.82px) scale(1, 1); }
  26.02% { transform: translate(-7.57px, -6.41px) scale(1, 1); }
  26.43% { transform: translate(-6.63px, -6.69px) scale(1, 1); }
  26.84% { transform: translate(-5.68px, -6.66px) scale(0.99, 1.01); }
  27.24% { transform: translate(-4.73px, -6.32px) scale(0.98, 1.02); }
  27.65% { transform: translate(-3.79px, -5.67px) scale(0.96, 1.04); }
  28.06% { transform: translate(-2.84px, -4.72px) scale(0.94, 1.06); }
  28.47% { transform: translate(-1.89px, -3.45px) scale(0.92, 1.08); }
  28.88% { transform: translate(-0.95px, -1.88px) scale(0.9, 1.1); }
  29.29% { transform: translate(0px, 0px) scale(0.88, 1.12); }
  30.71% { transform: translate(0px, 0px) scale(1.3, 0.72); }
  32.71% { transform: translate(0px, 0px) scale(0.93, 1.08); }
  34.14% { transform: translate(0px, 0px) scale(1.03, 0.98); }
  35% { transform: translate(0px, 0px) scale(1, 1); }
  82.14% { transform: translate(0px, 0px) scale(1, 1); }
  82.59% { transform: translate(-1.66px, -3.09px) scale(1, 1); }
  83.04% { transform: translate(-3.31px, -5.23px) scale(1, 1); }
  83.48% { transform: translate(-4.97px, -6.43px) scale(1, 1); }
  83.93% { transform: translate(-6.63px, -6.69px) scale(1, 1); }
  84.38% { transform: translate(-8.28px, -6px) scale(1, 1); }
  84.82% { transform: translate(-9.94px, -4.36px) scale(1, 1); }
  85.27% { transform: translate(-11.59px, -1.78px) scale(1, 1); }
  85.71% { transform: translate(-13.25px, 1.75px) scale(1, 1); }
  86.07% { transform: translate(-13.25px, 1.6px) scale(1.2, 0.84); }
  86.43% { transform: translate(-13.25px, 1.14px) scale(1.19, 0.85); }
  86.79% { transform: translate(-13.25px, 0.31px) scale(1.16, 0.87); }
  87.14% { transform: translate(-13.25px, -0.96px) scale(1.1, 0.92); }
  87.5% { transform: translate(-13.25px, -2.73px) scale(1.03, 0.98); }
  87.86% { transform: translate(-13.25px, -5.11px) scale(1, 1); }
  88.21% { transform: translate(-13.25px, -8.23px) scale(1, 1); }
  88.57% { transform: translate(-13.25px, -12.26px) scale(1, 1); }
  88.93% { transform: translate(-13.25px, -17.42px) scale(1, 1); }
  89.29% { transform: translate(-13.71px, -23.94px) scale(1, 1); }
  89.64% { transform: translate(-20.21px, -28.25px) scale(1, 1); }
  90% { transform: translate(-26.75px, -21.61px) scale(1, 1); }
  90.36% { transform: translate(-26.75px, -9.54px) scale(1, 1); }
  90.71% { transform: translate(-26.75px, 0.14px) scale(1.19, 0.85); }
  91.07% { transform: translate(-26.75px, -12.15px) scale(1, 1); }
  91.43% { transform: translate(-26.89px, -22.85px) scale(1, 1); }
  91.79% { transform: translate(-33.15px, -28.24px) scale(1, 1); }
  92.14% { transform: translate(-39.26px, -25.03px) scale(1, 1); }
  92.5% { transform: translate(-40.25px, -19.33px) scale(1, 1); }
  92.86% { transform: translate(-40.25px, -14.55px) scale(1, 1); }
  93.21% { transform: translate(-40.25px, -10.66px) scale(1, 1); }
  93.57% { transform: translate(-40.25px, -7.51px) scale(1, 1); }
  93.93% { transform: translate(-40.25px, -4.98px) scale(1, 1); }
  94.29% { transform: translate(-40.25px, -2.95px) scale(1, 1); }
  94.64% { transform: translate(-40.25px, -1.37px) scale(1, 1); }
  95% { transform: translate(-40.25px, -0.16px) scale(1, 1); }
  95.36% { transform: translate(-40.25px, 0.72px) scale(1, 1); }
  95.71% { transform: translate(-40.25px, 1.31px) scale(1, 1); }
  96.07% { transform: translate(-40.25px, 1.64px) scale(1, 1); }
  96.43% { transform: translate(-40.25px, 1.75px) scale(1, 1); }
  100% { transform: translate(-40.25px, 1.75px) scale(1, 1); }
}

@keyframes logo-crayon {
  0%,
  33.57% {
    stroke-dashoffset: 100;
    animation-timing-function: cubic-bezier(0.45, 0, 0.25, 1);
  }
  42.86% {
    stroke-dashoffset: 0;
  }
  82.14% {
    stroke-dashoffset: 0;
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4);
  }
  85.71%,
  100% {
    stroke-dashoffset: 100;
  }
}

@keyframes logo-slogan {
  0%,
  29.29% { opacity: 0; transform: translateX(1.2em); }
  36.29% { opacity: 1; transform: translateX(0); }
  81.14% {
    opacity: 1;
    transform: translateX(0);
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4);
  }
  86.14%,
  100% { opacity: 0; transform: translateX(-0.7em); }
}
/* === LOGO : fin === */

/* ============================================================================================
   Boutons de lecture des films : l'onde (27/09/2026), deux anneaux (blanc puis jaune) qui s'écartent en 1,4 s et se
   dissipent à 78 % du cycle. Depuis le 30/09/2026 (audit apple-design C1 et § 4) :
   - dessinée par deux disques placés sous le bouton (z-index -1) qui grandissent et s'effacent — transform et opacity,
     calculés par la carte graphique — au lieu d'une ombre animée qui faisait repeindre les cartes à chaque image
     (mesuré dans le vrai Chrome : 43,5 im/s sur « Nos derniers travaux », 49,9 sur « Projets » ; 58 à 60 avec les
     disques). Même dessin, comparé aux mêmes instants du cycle : le jaune va jusqu'à 26 px autour du bouton, le blanc
     jusqu'à 14 px. Les rapports d'agrandissement de chaque bouton (--onde-jx…) sont mesurés par js/main.js ; valeurs
     de repli pour un rond moyen ;
   - trois battements quand la vidéo arrive à l'écran, puis le bouton se tait (un signal, pas un bruit de fond) ; ils
     reprennent à chaque retour de la section à l'écran (animation remise à zéro hors écran) ;
   - décalée d'un film à l'autre dans la vitrine ; aucune onde en mouvement réduit.
   ============================================================================================ */
@keyframes lecture-onde-disque-jaune {
  0% {
    transform: scale(1);
    opacity: 1;
  }

  78% {
    transform: scale(var(--onde-jx, 2.1), var(--onde-jy, 2.1));
    opacity: 0;
  }

  100% {
    transform: scale(1);
    opacity: 0;
  }
}

@keyframes lecture-onde-disque-blanc {
  0% {
    transform: scale(1);
    opacity: 1;
  }

  78% {
    transform: scale(var(--onde-bx, 1.6), var(--onde-by, 1.6));
    opacity: 0;
  }

  100% {
    transform: scale(1);
    opacity: 0;
  }
}

.lecture__onde::before,
.lecture__onde::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  border-radius: inherit;
  background: rgba(228, 225, 53, 0.42);
  opacity: 0;
  animation: lecture-onde-disque-jaune 1.4s var(--ease-sortie) 3;
}

.lecture__onde::after {
  background: rgba(255, 255, 255, 0.5);
  animation-name: lecture-onde-disque-blanc;
}

.vitrine__film--gauche-bas .lecture__onde::before,
.vitrine__film--gauche-bas .lecture__onde::after {
  animation-delay: 0.47s;
}

.vitrine__film--droite .lecture__onde::before,
.vitrine__film--droite .lecture__onde::after {
  animation-delay: 0.93s;
}

.hors-ecran .lecture__onde::before,
.hors-ecran .lecture__onde::after,
[data-motion="reduce"] .lecture__onde::before,
[data-motion="reduce"] .lecture__onde::after {
  animation: none;
}

/* Lecteur des films : le fond s'assombrit, le conteneur du film monte et se pose */
@keyframes lecteur-fond {
  from {
    opacity: 0;
  }
}

@keyframes lecteur-entree {
  from {
    opacity: 0;
    transform: translateY(22px) scale(0.97);
  }
}

.lecteur[open]::backdrop {
  animation: lecteur-fond 0.35s var(--ease-doux);
}

.lecteur[open] .lecteur__cadre {
  animation: lecteur-entree 0.5s var(--ease-sortie);
}

/* ============================================================================================
   Tarifs (28/09/2026) — ce que racontent les animations : le prix de lancement remplace l'ancien (le trait barre
   l'ancien prix, le montant descend jusqu'au nouveau : animations.js), ce qui est compris s'affiche ligne par ligne, et
   la carte la plus demandée est entourée d'un liseré jaune qui tourne. État de départ posé par animations.js
   (classe tarif--attente) : sans ce script, tout est affiché tel quel.
   ============================================================================================ */
@property --tarif-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.tarif--vedette::before {
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1.5px;
  border-radius: inherit;
  background: conic-gradient(from var(--tarif-angle), rgba(228, 225, 53, 0) 0deg, rgba(228, 225, 53, 0.95) 70deg, rgba(228, 225, 53, 0) 140deg, rgba(228, 225, 53, 0) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  animation: tarif-lisere 6s linear infinite;
}

@keyframes tarif-lisere {
  to {
    --tarif-angle: 360deg;
  }
}

.tarif__barre::after {
  transition: transform 0.55s var(--ease-sortie) 0.15s;
}

.tarif--attente .tarif__barre::after {
  transform: scaleX(0);
}

.tarif.est-visible .tarif__ligne {
  animation: tarif-ligne 0.5s var(--ease-sortie) both;
  animation-delay: calc(0.35s + var(--i, 0) * 0.055s);
}

@keyframes tarif-ligne {
  from {
    opacity: 0;
    transform: translateX(-8px);
  }
}

/* ============================================================================================
   Animation d'entrée (28/09/2026) : la lumière jaune respire, le bienvenue et l'infographie montent, le logo se pose
   (entrée en fondu seulement : sa transformation appartient ensuite à main.js). Secours : si le script ne la termine
   pas, la couche s'efface seule au bout de 6,5 s.
   ============================================================================================ */
.intro-en-cours .intro {
  animation: intro-secours 0.5s ease 6.5s forwards;
}

@keyframes intro-secours {
  to {
    opacity: 0;
    visibility: hidden;
  }
}

.intro__fond::before {
  animation: intro-lumiere 3.4s ease-in-out infinite alternate;
}

@keyframes intro-lumiere {
  from {
    transform: translate(-54%, -48%) scale(0.92);
  }
  to {
    transform: translate(-46%, -52%) scale(1.08);
  }
}

.intro__bienvenue {
  animation: entree-monter 0.7s var(--sortie-3) 0.1s backwards;
}

.intro__chargement {
  animation: intro-infographie 0.7s var(--sortie-3) 0.25s backwards;
}

@keyframes intro-infographie {
  from {
    opacity: 0;
    translate: 0 16px;
  }
}

.intro__marque {
  animation: entree-fondu 0.6s ease 0.05s backwards;
}

/* ============================================================================================
   AUDIT « APPLE-DESIGN » (30/09/2026, accord de l'utilisateur) — réglages de mouvement transverses.
   Rapport : docs/sites/motion-design-pro/AUDIT-DESIGN-APPLE.md (numéros entre crochets).
   ============================================================================================ */

/* [§ 4] Logo : il reste animé en boucle, sans fin (demande de l'utilisateur du 30/09/2026, qui annule le « dessiné une
   fois » du même jour). */

/* [§ 4] WhatsApp : trois ondes et deux balancements pour se faire remarquer, puis le bouton reste tranquille */
.whatsapp__icone::after {
  animation-iteration-count: 3;
}

.whatsapp__icone svg {
  animation-iteration-count: 2;
}

/* [A1] Retour à l'appui : tout ce qui se clique s'enfonce légèrement dès que le doigt ou le clic se pose (100 à
   160 ms, courbe de sortie), et remonte au relâchement. */
.bouton,
.btn,
.lecture,
.tarifs__type,
.tarifs__conseil,
.voix-exemple,
.voix-exemples__lien,
.clients__pause,
.entete__menu,
.lecteur__fermer,
.edito__lire,
.edito-outil__bouton,
.whatsapp,
.sommaire__raccourci {
  /* « scale » (propriété à part) : elle se compose avec le transform posé par GSAP sur les boutons aimantés */
  transition-property: scale, transform, background-color, border-color, color, box-shadow, opacity, translate;
  transition-duration: 0.14s, 0.25s, 0.25s, 0.25s, 0.25s, 0.25s, 0.25s, 0.35s;
  transition-timing-function: var(--ease-sortie), var(--ease-sortie), var(--ease-doux), var(--ease-doux), var(--ease-doux), var(--ease-doux), var(--ease-doux), var(--ease-sortie);
}

.bouton:active,
.btn:active,
.tarifs__type:active,
.tarifs__conseil:active,
.voix-exemples__lien:active,
.clients__pause:active,
.edito__lire:active,
.edito-outil__bouton:active,
.sommaire__raccourci:active,
.whatsapp:active {
  scale: 0.97;
}

.lecture:active,
.entete__menu:active,
.lecteur__fermer:active,
.voix-exemple:active {
  scale: 0.94;
}

.sommaire__liste a:active,
.reperes__lien:active {
  opacity: 0.7;
}

/* [B1] Menu complet : il naît du bouton ☰ (en haut à droite) et y retourne ; transition, donc interruptible */
.menu:not([hidden]) {
  transform-origin: calc(100% - 28px) -12px;
  opacity: 0;
  transform: translateY(-6px) scale(0.96);
  transition:
    opacity 0.16s var(--ease-sortie),
    transform 0.16s var(--ease-sortie);
}

.menu.est-ouvert {
  opacity: 1;
  transform: none;
  transition-duration: 0.22s;
}

[data-motion="reduce"] .menu:not([hidden]) {
  transform: none;
}

/* [B2] Lecteur : la sortie reprend le chemin de l'entrée, en plus court (200 ms) */
@keyframes lecteur-sortie {
  to {
    opacity: 0;
    transform: translateY(22px) scale(0.97);
  }
}

@keyframes lecteur-fond-sortie {
  to {
    opacity: 0;
  }
}

.lecteur.est-sortie::backdrop {
  animation: lecteur-fond-sortie 0.2s var(--ease-doux) forwards;
}

.lecteur.est-sortie .lecteur__cadre {
  animation: lecteur-sortie 0.2s var(--ease-sortie) forwards;
}

[data-motion="reduce"] .lecteur[open] .lecteur__cadre {
  animation: entree-fondu 0.2s ease;
}

/* [B3] Réponses de la FAQ et chapitres : ouverture en douceur (hauteur et fondu, 250 ms). Amélioration progressive :
   les navigateurs qui ne savent pas animer la hauteur ouvrent directement. */
@supports (interpolate-size: allow-keywords) {
  :root {
    interpolate-size: allow-keywords;
  }

  .edito-question::details-content {
    block-size: 0;
    overflow: clip;
    opacity: 0;
    transition:
      block-size 0.25s var(--ease-sortie),
      opacity 0.25s var(--ease-sortie),
      content-visibility 0.25s allow-discrete;
  }

  .edito-question[open]::details-content {
    block-size: auto;
    opacity: 1;
  }
}

/* [B3] « Écouter les voix » : le panneau grandit depuis son bouton (en bas à droite) */
.voix-exemples[open] .voix-exemples__panneau {
  transform-origin: calc(100% - 40px) 100%;
  transition:
    opacity 0.18s var(--ease-sortie),
    transform 0.18s var(--ease-sortie);

  @starting-style {
    opacity: 0;
    transform: translateY(6px) scale(0.96);
  }
}

/* [J1] Entrée de l'anneau : depuis un anneau déjà formé (20 %), jamais depuis rien ; version douce : fondu seul */
.est-anneau.est-attente .studio__perspective {
  transform: scale(0.2);
}

[data-motion="reduce"] .est-anneau.est-attente .studio__perspective {
  transform: none;
}

/* [J2] L'anneau se saisit à la main : curseur de préhension, pas de sélection de texte pendant le geste, et le
   glissement vertical du doigt reste au défilement de la page */
.est-anneau {
  cursor: grab;
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}

.est-anneau.est-saisi {
  cursor: grabbing;
}

/* [§ 14] Version douce (visiteur qui a demandé moins d'animations à son système) : les bandeaux ne défilent plus seuls
   (on les fait glisser à la main), le reste entre en fondu ; les vidéos jouent toujours (c'est le produit). */
[data-motion="reduce"] .clients__defile,
[data-motion="reduce"] .marques__defile {
  animation: none;
}

[data-motion="reduce"] .clients__bandeau,
[data-motion="reduce"] .marques {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

[data-motion="reduce"] .whatsapp__icone::after,
[data-motion="reduce"] .whatsapp__icone svg,
[data-motion="reduce"] .tarif--vedette::before {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* [H2] Au bureau aussi, la pastille WhatsApp se replie sur son icône après 8 s (déployée, elle couvrait le bas des
   cartes de tarifs) ; au téléphone, le même repli existe déjà (responsive.css). */
@keyframes whatsapp-replier-texte {
  to {
    max-width: 0;
    opacity: 0;
  }
}

@keyframes whatsapp-replier-bouton {
  to {
    gap: 0;
    padding-right: 7px;
  }
}

@media (min-width: 768px) {
  .whatsapp__texte {
    max-width: 220px;
    overflow: hidden;
    white-space: nowrap;
    animation: whatsapp-replier-texte 0.5s var(--ease-doux) 8s forwards;
  }

  .whatsapp {
    animation: whatsapp-replier-bouton 0.5s var(--ease-doux) 8s forwards;
  }

  [data-motion="full"] .whatsapp {
    animation:
      whatsapp-entree 0.7s var(--sortie-3) 1.2s backwards,
      whatsapp-replier-bouton 0.5s var(--ease-doux) 8s forwards;
  }
}

/* Titres H2 découpés en lettres pendant leur entrée (animations.js, version 4, 30/09/2026) : mots insécables, lettres
   déplaçables ; le titre retrouve son texte d'origine à la fin de l'animation. */
.titre-mot {
  display: inline-block;
  white-space: nowrap;
}

.titre-lettre {
  display: inline-block;
}

/* Titres du haut du site (jusqu'aux tarifs) : chaque mot monte derrière un masque pendant l'entrée (animations.js, 30/09/2026) ;
   le masque laisse la place des accents et des jambages sans changer la hauteur de ligne. Texte d'origine rendu à la fin. */
.titre-masque {
  display: inline-flex;
  overflow: hidden;
  padding: 0.1em 0 0.18em;
  margin: -0.1em 0 -0.18em;
  vertical-align: baseline;
}

.titre-masque__mot {
  display: inline-block;
  transform-origin: 0% 100%;
}

/* Textes d'introduction du haut : chaque mot s'allume au rythme du défilement */
.mot-lu {
  display: inline;
}
