/* Azelize · icônes animées · azelize-animations.css
   Proposition du 5 octobre 2026, à valider par Taha.

   Un trait qui se dessine, un point qui se pose. Les icônes bougent pour répondre à un geste
   (survol, clic, changement d'état), jamais pour attirer l'œil.
   - À poser avec azelize-animations.js (sans bibliothèque).
   - Les dessins viennent de outils/pictogrammes.py ; les fichiers de svg/ sont prêts à coller dans le HTML.
   - Les valeurs propres à chaque dessin (longueur des traits, déplacements) sont écrites dans le SVG,
     en variables : --l, --a, --b, --c, --dx, --dy...
   - Tout se règle par les variables ci-dessous. Unités : celles de la grille du dessin (24 ou 48).
*/

:root {
  --az-duree-survol: 200ms;    /* l'icône répond au survol */
  --az-duree-retour: 260ms;    /* elle revient, un peu plus lentement */
  --az-duree-retracer: 300ms;  /* le trait d'une icône se redessine */
  --az-duree-point-icone: 130ms; /* puis son point se pose */
  --az-duree-geste: 400ms;     /* un geste complet au clic : part, puis revient */
  --az-duree-aller: 360ms;     /* un aller-retour */
  --az-duree-va-et-vient: 320ms;
  --az-duree-bascule: 300ms;   /* menu et fermer, plus et moins, lecture et pause */
  --az-duree-signe: 640ms;     /* le trait d'un signe, d'un seul geste */
  --az-duree-point: 220ms;     /* le point du signe se pose */
  --az-duree-eclat: 480ms;     /* le point s'allume en or */
  --az-duree-attente: 900ms;   /* un passage du point sur le trait */
  --az-duree-fondu: 180ms;     /* quand l'appareil demande moins de mouvement */
  --az-cascade: 35ms;          /* écart entre deux éléments qui entrent */

  --az-courbe-pose: cubic-bezier(0.22, 1, 0.36, 1);     /* arrive vite, se pose doucement */
  --az-courbe-depart: cubic-bezier(0.55, 0, 1, 0.45);   /* démarre doucement, s'en va */
  --az-courbe-bascule: cubic-bezier(0.65, 0, 0.35, 1);  /* d'un état à l'autre */
  --az-courbe-geste: cubic-bezier(0.5, 0, 0.2, 1);      /* la main qui dessine (écrite aussi dans l'outil) */

  --az-eclat: #C9A54C;         /* l'or : un seul point par écran, à l'écran seulement */
}

.az-icone, .az-bascule, .az-signe, .az-attente { overflow: hidden; }
.az-icone *, .az-bascule *, .az-signe *, .az-attente * { transform-box: view-box; }
.az-signe { --az-chute: -3px; --az-retard: calc(var(--i, 0) * var(--az-cascade)); }

/* --------------------------------------------------------------------------------------------
   L'hôte : le lien ou le bouton qui porte l'icône. Survolé, ou touché (classe az-actif posée
   par le script), il donne --az-s: 1 ; les icônes « avancer », « tourner » et « régler » le suivent.
   -------------------------------------------------------------------------------------------- */
@media (hover: hover) {
  :is(a, button, summary, label, [role="button"], .az-hote):hover { --az-s: 1; }
}
:is(a, button, summary, label, [role="button"], .az-hote):focus-visible,
.az-actif { --az-s: 1; }

/* Avancer : la flèche avance, le couvercle se soulève, les coins s'écartent. */
[data-az-geste="avancer"] .az-mobile,
[data-az-geste="tourner"] .az-mobile,
[data-az-geste="regler"] :is(.az-rail, .az-mobile) {
  transition-property: transform, stroke-dasharray;
  transition-duration: calc(var(--az-duree-retour) - var(--az-s, 0) * (var(--az-duree-retour) - var(--az-duree-survol)));
  transition-timing-function: var(--az-courbe-pose);
}
[data-az-geste="avancer"] .az-mobile {
  transform: translate(calc(var(--az-s, 0) * var(--dx, 0px)), calc(var(--az-s, 0) * var(--dy, 0px)));
}

/* Tourner : la grande aiguille avance d'un quart d'heure. */
[data-az-geste="tourner"] .az-mobile {
  transform-origin: var(--ox, 12px) var(--oy, 12px);
  transform: rotate(calc(var(--az-s, 0) * var(--rot, 90deg)));
  transition-duration: var(--az-duree-bascule);
  transition-timing-function: var(--az-courbe-bascule);
}

/* Régler : les deux curseurs glissent sur leur rail, qui s'ouvre où ils passent. */
[data-az-geste="regler"] .az-rail {
  stroke-dasharray: calc(var(--d0) + var(--az-s, 0) * var(--dx)) var(--trou) 24px;
}
[data-az-geste="regler"] .az-mobile {
  transform: translateX(calc(var(--az-s, 0) * var(--dx)));
}
[data-az-geste="regler"] :is(.az-rail, .az-mobile) { transition-timing-function: var(--az-courbe-bascule); }

/* --------------------------------------------------------------------------------------------
   Les gestes qui se jouent une fois : le script pose la classe az-joue, puis la retire.
   -------------------------------------------------------------------------------------------- */

/* Retracer : le trait se redessine d'un seul geste, puis le point se pose. */
.az-joue[data-az-geste="retracer"] .az-trace {
  animation: az-trace calc(var(--az-duree-retracer) * var(--b, 1)) var(--c, linear)
             calc(var(--az-duree-retracer) * var(--a, 0)) backwards;
}
.az-joue[data-az-geste="retracer"] .az-point {
  animation: az-pose var(--az-duree-point-icone) var(--az-courbe-pose)
             calc(var(--az-duree-retracer) * 0.9) backwards;
}
.az-joue[data-az-geste="retracer"] .az-point.az-seul {
  animation: az-reposer var(--az-duree-aller) linear backwards;
}

/* Partir : envoyer part, puis revient ; la flèche descend dans le bac ; un message arrive. */
.az-joue[data-az-geste="partir"] .az-mobile { animation: az-partir var(--az-duree-geste) linear; }

/* Aller-retour : la copie glisse, le crayon écrit, l'anse s'ouvre et se ferme. */
.az-joue[data-az-geste="aller-retour"] .az-mobile { animation: az-aller-retour var(--az-duree-aller) linear; }

/* Va-et-vient : attention, un seul petit va-et-vient. */
.az-joue[data-az-geste="va-et-vient"] .az-mobile { animation: az-va-et-vient var(--az-duree-va-et-vient) linear; }

@keyframes az-trace {
  from { stroke-dasharray: var(--l) calc(var(--l) + 1px); stroke-dashoffset: calc(var(--l) + 0.01px); }
  to   { stroke-dasharray: var(--l) calc(var(--l) + 1px); stroke-dashoffset: 0px; }
}
@keyframes az-pose {
  from { opacity: 0; transform: translateY(var(--az-chute, -2px)); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes az-reposer {
  0%   { opacity: 1; transform: translateY(0); animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45); }
  35%  { opacity: 0; transform: translateY(var(--az-chute, -2px)); animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes az-partir {
  0%    { opacity: 1; transform: translate(0, 0); animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45); }
  40%   { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)); }
  40.5% { opacity: 0; transform: translate(var(--rx, 0px), var(--ry, 0px)); animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  100%  { opacity: 1; transform: translate(0, 0); }
}
@keyframes az-aller-retour {
  0%   { transform: translate(0, 0); animation-timing-function: cubic-bezier(0.33, 0, 0.2, 1); }
  40%  { transform: translate(var(--dx, 0px), var(--dy, 0px)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  100% { transform: translate(0, 0); }
}
@keyframes az-va-et-vient {
  0%   { transform: translateX(0); animation-timing-function: cubic-bezier(0.33, 0, 0.67, 1); }
  30%  { transform: translateX(calc(var(--dx, 1px) * -1)); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  70%  { transform: translateX(var(--dx, 1px)); animation-timing-function: cubic-bezier(0.33, 0, 0.67, 1); }
  100% { transform: translateX(0); }
}

/* --------------------------------------------------------------------------------------------
   Les bascules : l'état vient de l'hôte (aria-pressed ou aria-expanded à "true"), ou de la classe az-b.
   -------------------------------------------------------------------------------------------- */
.az-bascule { --az-b: 0; }
:is([aria-pressed="true"], [aria-expanded="true"]) .az-bascule,
.az-bascule.az-b { --az-b: 1; }

/* Un trait passe d'une place à l'autre : il glisse et tourne autour de son milieu. */
.az-bascule .az-ligne {
  transform-origin: var(--ox) var(--oy);
  transform: translate(calc(var(--az-b) * var(--tx, 0px)), calc(var(--az-b) * var(--ty, 0px)))
             rotate(calc(var(--az-b) * var(--r, 0deg)))
             scaleX(calc(1 + var(--az-b) * (var(--k, 1) - 1)));
  transition: transform var(--az-duree-bascule) var(--az-courbe-bascule);
}
/* Le trait qui finit sur un autre (plus et moins) s'efface une fois posé : le dessin reste net. */
.az-bascule .az-ligne.az-confondu {
  opacity: calc(1 - var(--az-b));
  transition: transform var(--az-duree-bascule) var(--az-courbe-bascule),
              opacity 1ms linear calc(var(--az-b) * var(--az-duree-bascule));
}
/* Le trait qui n'a pas de place dans l'autre état se resserre et s'efface. */
.az-bascule .az-efface {
  transform-origin: var(--ox) var(--oy);
  transform: scaleX(calc(1 - var(--az-b) * 0.75));
  opacity: calc(1 - var(--az-b));
  transition: transform var(--az-duree-bascule) var(--az-courbe-bascule),
              opacity calc(var(--az-duree-bascule) * 0.5) linear calc((1 - var(--az-b)) * var(--az-duree-bascule) * 0.4);
}
/* Le son : les ondes se retirent, la croix se trace (et l'inverse). */
.az-bascule .az-onde, .az-bascule .az-croix {
  stroke-dasharray: var(--l) calc(var(--l) + 1px);
  transition-property: stroke-dashoffset, opacity;
  transition-duration: calc(var(--az-duree-bascule) * 0.6);
  transition-timing-function: var(--az-courbe-bascule), linear;
}
/* le trait qui se retire s'efface en même temps : il ne reste pas de bout de trait isolé */
.az-bascule .az-onde {
  stroke-dashoffset: calc(var(--az-b) * (var(--l) + 0.01px));
  opacity: calc(1 - var(--az-b));
  transition-delay: calc((1 - var(--az-b)) * var(--az-duree-bascule) * 0.4 + var(--i, 0) * 50ms);
}
.az-bascule .az-croix {
  stroke-dashoffset: calc((1 - var(--az-b)) * (var(--l) + 0.01px));
  opacity: var(--az-b);
  transition-delay: calc(var(--az-b) * var(--az-duree-bascule) * 0.4 + var(--i, 0) * 50ms);
}
/* Lecture et pause : le script fait glisser le dessin d'une forme à l'autre (attributs data-a, data-b). */

/* --------------------------------------------------------------------------------------------
   Les signes à leur entrée : classe az-entre sur le signe, ou sur un bloc qui en contient plusieurs.
   -------------------------------------------------------------------------------------------- */
:is(.az-entre .az-signe, .az-signe.az-entre) .az-trace {
  animation: az-trace calc(var(--az-duree-signe) * var(--b, 1)) var(--c, linear)
             calc(var(--az-retard) + var(--az-duree-signe) * var(--a, 0)) backwards;
}
:is(.az-entre .az-signe, .az-signe.az-entre) .az-point {
  animation: az-pose var(--az-duree-point) var(--az-courbe-pose)
             calc(var(--az-retard) + var(--az-duree-signe) * 0.94) backwards;
}
/* L'éclat : le point se pose en azur, puis s'allume en or. Une fois. Un seul signe par écran. */
:is(.az-entre .az-signe, .az-signe.az-entre).az-eclat .az-point {
  animation: az-pose var(--az-duree-point) var(--az-courbe-pose)
               calc(var(--az-retard) + var(--az-duree-signe) * 0.94) backwards,
             az-allume var(--az-duree-eclat) ease
               calc(var(--az-retard) + var(--az-duree-signe) * 0.94 + var(--az-duree-point) + 120ms) backwards;
}
/* Le point baisse un instant, puis revient en or : pas de mélange gris entre le bleu et l'or. */
@keyframes az-allume {
  0%   { fill: var(--az-point-avant, #9CC3FF); fill-opacity: 1; animation-timing-function: ease-in; }
  30%  { fill: var(--az-point-avant, #9CC3FF); fill-opacity: 0.3; }
  31%  { fill: var(--az-eclat); fill-opacity: 0.3; animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  100% { fill: var(--az-eclat); fill-opacity: 1; }
}

/* --------------------------------------------------------------------------------------------
   Les attentes : le point parcourt le trait, d'un bout à l'autre, et revient. Rien ne tourne.
   -------------------------------------------------------------------------------------------- */
.az-attente .az-attente-trait { stroke-opacity: 0.3; }
.az-attente .az-attente-point {
  animation: az-parcours var(--az-duree-attente) var(--az-courbe-bascule) infinite alternate;
}
@keyframes az-parcours {
  from { transform: translateX(0); }
  to   { transform: translateX(var(--az-course, 14px)); }
}
/* Avec une durée connue : --az-avance de 0 à 1 ; le trait se remplit jusqu'au point. */
.az-attente.az-progression .az-attente-point {
  animation: none;
  transform: translateX(calc(var(--az-avance, 0) * var(--az-course, 14px)));
  transition: transform 300ms var(--az-courbe-pose);
}
.az-attente .az-attente-plein {
  stroke-dasharray: var(--l) calc(var(--l) + 1px);
  stroke-dashoffset: calc((1 - var(--az-avance, 0)) * var(--l));
  transition: stroke-dashoffset 300ms var(--az-courbe-pose);
}
/* La fin de l'attente : le point va au bout du trait et s'y arrête. */
.az-attente.az-arrivee .az-attente-point {
  animation: none;
  transform: translateX(var(--az-course, 14px));
  transition: transform var(--az-duree-retour) var(--az-courbe-pose);
}

/* --------------------------------------------------------------------------------------------
   Moins de mouvement (réglage de l'appareil) : un simple fondu, rien ne se déplace.
   -------------------------------------------------------------------------------------------- */
@keyframes az-fondu { from { opacity: 0.25; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  :is(.az-icone, .az-bascule, .az-signe) * {
    animation: none !important;
    transition-property: opacity !important;
  }
  [data-az-geste] .az-mobile { transform: none !important; }
  [data-az-geste="regler"] .az-rail { stroke-dasharray: var(--d0) var(--trou) 24px !important; }
  .az-icone.az-joue, .az-bascule.az-fondu { animation: az-fondu var(--az-duree-fondu) ease; }
  :is(.az-entre .az-signe, .az-signe.az-entre) { animation: az-fondu 300ms ease var(--az-retard) backwards; }
  .az-attente .az-attente-point { animation: none; transform: translateX(calc(var(--az-course, 14px) / 2)); }
  .az-attente.az-progression .az-attente-point { transform: translateX(calc(var(--az-avance, 0) * var(--az-course, 14px))); }
}
