/* ══════════════════════════════════════════════════════════════════
   LE GESTE AU CLIC (préfixe gst-) - « J'aime » et « Je n'aime pas »
   Spec : docs/superpowers/specs/2026-11-13-boutons-percutants-design.md (D4).
   Maquette validée : .claude/design-drafts/2026-11-13-boutons-percutants/
   (percutant-anim.css, niveau « mixte » : le « fort » de « J'aime », le
   « net » de « Je n'aime pas », sans secousse, qui se lit d'ordinaire comme
   une saisie refusée).
   Le script (geste.js) pose une classe le temps du geste, puis la retire :
     .gst-pop  : « J'aime » vient d'être enfoncé ;
     .gst-vide : un bouton du duo vient d'être relâché ;
     .gst-coup : « Je n'aime pas » vient d'être enfoncé (fiche et capsule).
   La feuille de la page donne au bouton ses couleurs (--gst-repos, son fond
   au repos ; --gst-repos-icone ; --gst-plein, enfoncé ; --gst-plein-encre),
   `position: relative` et `isolation: isolate` : les calques du geste
   (remplissage, onde, éclats) passent sous le texte et l'icône, au-dessus
   du fond. Le script mesure le point de départ (--gst-px, --gst-py), le
   rayon qui couvre le bouton (--gst-r), le centre de l'icône (--gst-ix,
   --gst-iy) et les deux instants où l'encre bascule (--gst-icone-t,
   --gst-texte-t).
   Court et net : rien ne tourne en boucle, 600 ms au plus. « Moins
   d'animations » : le script ne pose rien, l'état change d'un coup.
   ══════════════════════════════════════════════════════════════════ */

/* Les durées du niveau « mixte » ; la feuille de la page peut les changer
   (`:where` ne pèse rien). Les mesures, posées par le script, l'emportent. */
:where(.gst-pop,.gst-vide,.gst-coup){
  --gst-flot-d:280ms;     /* le remplissage */
  --gst-coeur-d:480ms;    /* le cœur */
  --gst-coeur-max:1.42;   /* son dépassement */
  --gst-pouce-d:320ms;    /* le pouce */
  --gst-px:50%;--gst-py:50%;--gst-r:140px;--gst-ix:30px;--gst-iy:50%;
  --gst-icone-t:60ms;--gst-texte-t:150ms;
}

/* ── Le remplissage : la couleur pleine part d'un point et couvre le bouton,
   liseré compris. « J'aime » part du cœur, « Je n'aime pas » du point
   d'appui (du pouce au clavier). Il reste plein jusqu'à ce que la classe
   parte : dessous, le bouton est déjà dans son état enfoncé. */
.gst-pop::before,.gst-coup::before{
  content:"";position:absolute;inset:-1px;z-index:-1;border-radius:inherit;pointer-events:none;
  background:var(--gst-plein);
  clip-path:circle(0px at var(--gst-px) var(--gst-py));
  animation:gst-flot var(--gst-flot-d) cubic-bezier(.2,.7,.3,1) 40ms forwards;
}
@keyframes gst-flot{to{clip-path:circle(var(--gst-r) at var(--gst-px) var(--gst-py))}}

/* Le temps du remplissage, le bouton garde son fond de repos sous le calque ;
   ensuite, son fond enfoncé (couvert par le calque plein). Sans `fill-mode` :
   retenu au-delà, le fond de repos réapparaîtrait au retrait de la classe.
   L'encre du libellé et celle de l'icône basculent d'un coup, chacune à
   l'instant où le plein l'atteint. Une animation l'emporte sur le survol et
   l'état enfoncé sans !important. */
@keyframes gst-tient{from,to{background-color:var(--gst-repos)}}
@keyframes gst-encre{from{color:var(--ard-ink)}to{color:var(--gst-plein-encre)}}
@keyframes gst-icone{from{color:var(--gst-repos-icone)}to{color:var(--gst-plein-encre)}}

/* ── « J'aime » enfoncé ── */
.gst-pop{
  animation:
    gst-tient calc(var(--gst-flot-d) + 40ms) linear,
    gst-encre var(--gst-texte-t) step-end both;
}
/* Le cœur se comprime, se remplit, dépasse, revient. */
.gst-pop>svg{
  transform-origin:50% 55%;
  animation:
    gst-coeur var(--gst-coeur-d) cubic-bezier(.3,.6,.35,1) both,
    gst-icone var(--gst-icone-t) step-end both;
}
@keyframes gst-coeur{
  0%  {transform:scale(1);fill:currentColor;fill-opacity:0}
  16% {transform:scale(.72);fill-opacity:0}
  30% {fill-opacity:1}
  48% {transform:scale(var(--gst-coeur-max))}
  74% {transform:scale(.95)}
  100%{transform:scale(1);fill:currentColor;fill-opacity:1}
}
/* L'onde : un anneau à l'encre du bouton enfoncé, qui part du cœur, s'élargit
   et s'efface, une seule fois. */
.gst-pop::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  left:var(--gst-ix);top:var(--gst-iy);width:20px;height:20px;margin:-10px 0 0 -10px;
  border-radius:50%;border:2px solid var(--gst-plein-encre);opacity:0;
  animation:gst-onde 420ms cubic-bezier(.2,.7,.3,1) 110ms forwards;
}
@keyframes gst-onde{0%{transform:scale(.6);opacity:.95}100%{transform:scale(2.5);opacity:0}}
/* Les éclats : six traits courts, posés par le script. Ils partent au-delà du
   cœur à son plus gros (1,42 x 18 px, 13 px de rayon), quand il y arrive, et
   s'éteignent avant le bord du bouton (24 px). */
.gst-eclats{position:absolute;z-index:-1;left:var(--gst-ix);top:var(--gst-iy);width:0;height:0;pointer-events:none}
.gst-eclats i{
  position:absolute;left:-1px;top:-3px;width:2px;height:6px;border-radius:1px;
  background:var(--gst-plein-encre);opacity:0;
  transform:rotate(var(--gst-a)) translateY(-15px);
  animation:gst-eclat 300ms cubic-bezier(.15,.7,.3,1) 190ms forwards;
}
.gst-eclats i:nth-child(1){--gst-a:30deg}
.gst-eclats i:nth-child(2){--gst-a:90deg}
.gst-eclats i:nth-child(3){--gst-a:150deg}
.gst-eclats i:nth-child(4){--gst-a:210deg}
.gst-eclats i:nth-child(5){--gst-a:270deg}
.gst-eclats i:nth-child(6){--gst-a:330deg}
@keyframes gst-eclat{
  0%  {opacity:1;transform:rotate(var(--gst-a)) translateY(-15px) scaleY(1)}
  100%{opacity:0;transform:rotate(var(--gst-a)) translateY(-23px) scaleY(.4)}
}

/* ── Relâché : l'icône se vide simplement, un léger retrait et c'est tout. ──
   Le fond et l'encre passent d'un coup à la teinte de repos : la feuille de
   la page ne fait glisser ni l'un ni l'autre (fiche_recette.css), sinon le
   cœur ou le pouce, déjà à sa couleur de repos, resterait invisible les
   premières images (or sur or, rouge sur rouge). */
.gst-vide>svg{animation:gst-vide 220ms ease both}
@keyframes gst-vide{
  0%  {transform:scale(1);fill:currentColor;fill-opacity:1}
  45% {transform:scale(.86);fill:currentColor;fill-opacity:.2}
  100%{transform:scale(1);fill:currentColor;fill-opacity:0}
}

/* ── « Je n'aime pas » enfoncé : le bouton s'enfonce d'un coup sous le doigt,
   le rouge se remplit depuis le point d'appui. Pas de secousse. ── */
.gst-coup{
  animation:
    gst-tient calc(var(--gst-flot-d) + 40ms) linear,
    gst-encre var(--gst-texte-t) step-end both,
    gst-appui 220ms cubic-bezier(.3,0,.3,1) both;
}
@keyframes gst-appui{0%{transform:scale(1)}30%{transform:scale(.965)}100%{transform:scale(1)}}
/* Le pouce plonge (vers le bas, c'est son sens), se remplit, remonte. */
.gst-coup>svg{
  animation:
    gst-pouce var(--gst-pouce-d) cubic-bezier(.3,.6,.35,1) both,
    gst-icone var(--gst-icone-t) step-end both;
}
@keyframes gst-pouce{
  0%  {transform:none;fill:currentColor;fill-opacity:0}
  20% {transform:translateY(2.5px) scale(.8);fill-opacity:1}
  56% {transform:translateY(-1px) scale(1.06)}
  82%,100%{transform:none;fill:currentColor;fill-opacity:1}
}

/* ── Moins d'animations : le script ne pose rien ; si une classe restait, rien
   ne bougerait. ── */
@media (prefers-reduced-motion:reduce){
  .gst-pop,.gst-vide,.gst-coup,
  .gst-pop *,.gst-vide *,.gst-coup *,
  .gst-pop::before,.gst-pop::after,.gst-coup::before{animation:none!important}
  .gst-pop::before,.gst-pop::after,.gst-coup::before,.gst-eclats{display:none}
}
