/* ==========================================================================
   08 — MOUVEMENT

   Règles de la maison, appliquées à toutes les animations de ce fichier :

   1. Une animation a une intention. Elle explique une origine, confirme une
      action, ou hiérarchise une arrivée. Sinon elle ne se fait pas.
   2. On n'anime que `transform` et `opacity`. Ce sont les deux seules
      propriétés que le navigateur compose sans recalculer la mise en page
      ni repeindre. Animer `width`, `top` ou `box-shadow` fait retomber
      l'animation sur le fil principal, et saccade dès que la page est
      chargée.
   3. Rien ne bouge en boucle sans raison. Une boucle infinie sur un élément
      décoratif attire l'œil en permanence pour ne rien dire.
   4. `prefers-reduced-motion` n'est pas une option. Le repli est prévu pour
      chaque effet, et il affiche l'état final — jamais un élément resté
      invisible.

   Le repli global (durées à 1 ms) est déclaré dans 01-tokens.css. Ce fichier
   ajoute les reprises spécifiques, là où couper la transition ne suffit pas.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. ARRIVÉE AU DÉFILEMENT

   Intention : hiérarchiser la lecture d'une longue page. Les blocs se posent
   au lieu d'apparaître d'un bloc.

   L'état masqué n'est appliqué que si la classe `cp-js` est présente sur
   <html> — c'est le script qui la pose. Sans JavaScript, ou s'il échoue, le
   contenu reste visible : on ne masque jamais du contenu qu'on n'est pas
   certain de pouvoir révéler.
   -------------------------------------------------------------------------- */

.cp-js body.cp .cp-arrivee {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 620ms var(--cp-courbe), transform 620ms var(--cp-courbe);
  transition-delay: var(--cp-retard, 0ms);
  will-change: transform, opacity;
}
.cp-js body.cp .cp-arrivee.est-visible {
  opacity: 1;
  transform: none;
  will-change: auto;   /* libéré une fois l'animation jouée */
}

/* Décalage en cascade dans une grille. Six crans suffisent : au-delà, la
   dernière carte arrive si tard qu'on croit à un défaut de chargement. */
.cp-js body.cp .cp-cascade > *:nth-child(1) { --cp-retard: 0ms; }
.cp-js body.cp .cp-cascade > *:nth-child(2) { --cp-retard: 60ms; }
.cp-js body.cp .cp-cascade > *:nth-child(3) { --cp-retard: 120ms; }
.cp-js body.cp .cp-cascade > *:nth-child(4) { --cp-retard: 180ms; }
.cp-js body.cp .cp-cascade > *:nth-child(5) { --cp-retard: 240ms; }
.cp-js body.cp .cp-cascade > *:nth-child(n+6) { --cp-retard: 300ms; }

/* --------------------------------------------------------------------------
   2. SÉQUENCE D'OUVERTURE DE L'ACCUEIL

   Intention : donner un ordre de lecture au premier écran — surtitre, titre,
   phrase, bouton — plutôt que de tout révéler d'un coup.

   Révision du 2 octobre 2026 — mouvement seul, sans fondu, dès le premier
   affichage. L'ancienne version attendait les polices et le script du thème
   (classe `cp-ouverture` sur <body>), puis repartait d'une opacité nulle :
   le haut de page, déjà affiché, disparaissait pour réapparaître en fondu.
   Google ne compte un élément comme affiché qu'une fois visible : le titre
   n'était « peint » qu'à 5–8 s sur mobile au lieu de 2,8 s, ce qui plombait
   le LCP. Le contenu est maintenant visible d'emblée ; seule la montée de
   22 px subsiste. Les polices étant préchargées, la substitution tombe en
   général avant ou pendant le mouvement, sans saut perceptible.
   -------------------------------------------------------------------------- */

.cp-js body.cp .cp-hero > * {
  animation: cp-monte 780ms var(--cp-courbe) both;
}
.cp-js body.cp .cp-hero > *:nth-child(1) { animation-delay:  60ms; }
.cp-js body.cp .cp-hero > *:nth-child(2) { animation-delay: 150ms; }
.cp-js body.cp .cp-hero > *:nth-child(3) { animation-delay: 250ms; }
.cp-js body.cp .cp-hero > *:nth-child(4) { animation-delay: 360ms; }

@keyframes cp-monte {
  from { transform: translateY(22px); }
  to   { transform: none; }
}

/* --------------------------------------------------------------------------
   3. AJOUT AU PANIER

   Intention : confirmer que le clic a été pris en compte, à l'endroit où le
   client regarde — le bouton — puis à l'endroit où va l'article — la
   pastille du panier, dont la pulsation est déclarée dans 05-entete.css.

   WooCommerce pose déjà `.loading` puis `.added` sur le bouton : on s'y
   raccroche plutôt que d'inventer un état.
   -------------------------------------------------------------------------- */

body.cp .woocommerce a.button.loading,
body.cp .woocommerce button.button.loading { position: relative; color: transparent !important; }
body.cp .woocommerce a.button.loading::after,
body.cp .woocommerce button.button.loading::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: var(--cp-blanc);
  border-radius: 50%;
  animation: cp-tourne 720ms linear infinite;
}
@keyframes cp-tourne { to { transform: rotate(360deg); } }

body.cp .woocommerce a.added::before {
  content: "✓";
  margin-right: 0.4em;
  animation: cp-coche 420ms var(--cp-courbe) both;
}
@keyframes cp-coche {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   4. LE BOCAL QUI S'INCLINE

   Intention : un rappel du geste artisanal, au survol d'une carte produit.
   Deux degrés et six pixels : assez pour qu'on le sente, trop peu pour qu'on
   le remarque comme un effet.

   Combiné à l'agrandissement déclaré dans 04-woocommerce.css, en une seule
   déclaration `transform` pour ne pas écraser l'autre.
   -------------------------------------------------------------------------- */

@media (hover: hover) {
  body.cp .woocommerce ul.products li.product .product-inner:hover img {
    transform: scale(1.05) rotate(-1.6deg) translateY(-4px);
  }
}

/* --------------------------------------------------------------------------
   5. SQUELETTE DE CHARGEMENT

   Intention : pendant que WooCommerce rafraîchit les fragments du panier,
   montrer une forme plutôt qu'un vide. On garde la place de l'élément, ce
   qui évite au passage un décalage de mise en page.
   -------------------------------------------------------------------------- */

body.cp .cp-squelette {
  background: linear-gradient(90deg, var(--cp-gris-voile) 25%, var(--cp-fond) 50%, var(--cp-gris-voile) 75%);
  background-size: 200% 100%;
  animation: cp-balaye 1.4s ease-in-out infinite;
  border-radius: var(--cp-r-sm);
  color: transparent;
  pointer-events: none;
}
@keyframes cp-balaye { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* --------------------------------------------------------------------------
   6. RETOUR EN HAUT
   -------------------------------------------------------------------------- */

body.cp #scroll-top {
  background: var(--cp-bordeaux);
  color: var(--cp-blanc);
  border-radius: 50%;
  box-shadow: var(--cp-ombre-2);
  transition: transform var(--cp-vite) var(--cp-courbe), background-color var(--cp-vite) var(--cp-courbe);
}
body.cp #scroll-top:hover { background: var(--cp-bordeaux-fonce); transform: translateY(-3px); }

/* --------------------------------------------------------------------------
   7. REPLIS EXPLICITES

   Le repli global de 01-tokens.css ramène les durées à 1 ms, ce qui suffit
   pour les transitions. Il ne suffit pas ici : une animation `both` avec une
   durée de 1 ms laisse quand même son état initial le temps du retard, et
   les boucles décoratives n'ont pas à tourner du tout.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .cp-js body.cp .cp-arrivee { opacity: 1; transform: none; transition: none; }
  .cp-js body.cp .cp-hero > * { animation: none; transform: none; }
  body.cp .cp-squelette { animation: none; }
  body.cp .woocommerce a.button.loading::after,
  body.cp .woocommerce button.button.loading::after { animation-duration: 2.4s; }
  body.cp .cp-jauge__part::after { animation: none; }
  @media (hover: hover) {
    body.cp .woocommerce ul.products li.product .product-inner:hover img { transform: none; }
  }
}
