/* ===========================================================================
   LE MOUVEMENT DU DIRECT — l'Arrivee, l'Eclat, le Pouls, le Sillage, la
   Cascade, le Balai (V3.5, lot 4, spec § 8)
   ===========================================================================
   Les classes que noyau/mouvement.js pose (mv-arrivee, mv-eclat, mv-record,
   mv-pouls, mv-sillage, mv-sillage-tete, mv-cascade, mv-balai, mv-balai-bande,
   mv-sortante), et rien d'autre : transform, opacity et clip-path seulement,
   jamais en boucle, chaque animation coupee sous mouvement reduit (le bloc
   de fin, selecteur par selecteur, en plus du bloc universel d'emotion.css).
   TOUTE la feuille est sous la garde d'Alpine : Alpine n'en recoit rien (la
   coquille de saison sous son domaine comprise) -- ni ces animations, ni la
   coupure des boucles de son point. Les images cles n'ecrivent aucun jeton
   de la charte : l'angle de marque y vaut -35.8deg (--biais) ou 35.8deg, le
   decalage d'une coupe 33 px sur une ligne de 46 px (0,721 x 46, --pente) ;
   seules les proprietes --mv-dx, --mv-dy et --mv-i, posees par le script,
   y entrent.
   tests/mouvement.test.mjs lit cette feuille regle par regle ;
   tools/verifier-mouvement.mjs la fait jouer dans Chrome sans tete.
   =========================================================================== */

/* --- Le point du direct ne bat plus en boucle sous E-MOTION : les trois
   boucles d'avant la charte (classement.css, vitrine.css, emotion-today.html)
   faisaient grandir un anneau VERT de 10 px, peint sur la plaque jaune et
   au-dela de ses bords (revue finale du lot 1b). Il bat desormais une fois
   par releve reussi (mv-pouls, plus bas). position: relative porte l'anneau. */
:root:not([data-theme="alpine"]) .head-right .dot,
:root:not([data-theme="alpine"]) .head-live .dot,
:root:not([data-theme="alpine"]) .hero .dot { position: relative; animation: none; box-shadow: none; }
/* La teinte de l'anneau : sur la plaque EN DIRECT, le noir de son texte ;
   ailleurs, le vert du point. */
:root:not([data-theme="alpine"]) .head-right .live .dot { color: var(--on-brand); }
:root:not([data-theme="alpine"]) .head-live .dot,
:root:not([data-theme="alpine"]) .hero .dot { color: var(--ok); }

/* --- Le Pouls : un anneau qui s'ouvre et s'efface, une fois. Il part du point
   et de 1 px autour, et s'ouvre au double : 10 px puis 20 px pour le point de
   8 px de la plaque EN DIRECT des classements (elle fait environ 21,5 px de
   haut, l'anneau y reste ; tools/verifier-mouvement.mjs le mesure), 11 puis
   22 px pour les points de 9 px de l'accueil et des chronos du jour, qui ne
   sont pas sur une plaque. */
:root:not([data-theme="alpine"]) .dot.mv-pouls::after {
  content: ""; position: absolute; inset: -1px; box-sizing: border-box; border-radius: 50%;
  border: 1.5px solid currentColor; opacity: 0; pointer-events: none;
  animation: mv-pouls var(--dur-long) var(--ease-arrivee);
}
@keyframes mv-pouls {
  from { opacity: .75; transform: scale(1); }
  to   { opacity: 0; transform: scale(2); }
}
/* L'accueil : la pastille jaune des chronos du jour bat, son biais garde. */
:root:not([data-theme="alpine"]) .today-title.mv-pouls::before { animation: mv-pouls-pastille var(--dur-moyen) var(--ease-arrivee); }
@keyframes mv-pouls-pastille {
  0%, 100% { transform: skewX(-35.8deg) scale(1); }
  35%      { transform: skewX(-35.8deg) scale(1.35); }
}

/* --- L'Arrivee : un chrono neuf se decouvre par une coupe a l'angle de
   marque, bord d'attaque en « / » comme les coupes des panneaux (0,4 s) ; la
   premiere cellule porte le rail jaune, immobile, jusqu'au rendu suivant (toute
   ligne du jour le porte deja, classement.css : il ne distingue rien, il ne
   sert qu'a une ligne qui ne serait pas du jour). Remplace, sous E-MOTION,
   tr.fresh et tr.ligne-neuve, que noyau/classement.js n'y pose plus -- et la
   teinte statique de cette derniere sous mouvement reduit, reprise en fin de
   feuille. */
:root:not([data-theme="alpine"]) tbody tr.mv-arrivee { animation: mv-arrivee .4s var(--ease-arrivee); }
:root:not([data-theme="alpine"]) tbody tr.mv-arrivee > td:first-child { box-shadow: inset 3px 0 0 var(--jaune); }
@keyframes mv-arrivee {
  from { clip-path: polygon(0 0, 0 0, -33px 100%, -33px 100%); }
  to   { clip-path: polygon(0 0, calc(100% + 33px) 0, 100% 100%, 0 100%); }
}
/* Les pastilles du bandeau de l'accueil, sur leurs copies visibles : la coupe
   seule (le bandeau porte deja le rail et la pastille jaunes). */
:root:not([data-theme="alpine"]) .tt-row.mv-arrivee { animation: mv-arrivee-puce .4s var(--ease-arrivee); }
@keyframes mv-arrivee-puce {
  from { clip-path: polygon(0 0, 0 0, -17px 100%, -17px 100%); }
  to   { clip-path: polygon(0 0, calc(100% + 17px) 0, 100% 100%, 0 100%); }
}

/* --- L'Eclat : un reflet balaie une fois le chrono (0,9 s), apres la coupe.
   Or, au degrade de la charte, pour un nouveau meilleur temps (screen : le
   chrono reste lisible dessous) ; blanc pour un record personnel ; blanc a
   faible opacite sur la carte P1, deja or. Une bande a 125,8 deg (« / »). */
:root:not([data-theme="alpine"]) tbody tr.mv-eclat > td.time-cell,
:root:not([data-theme="alpine"]) tbody tr.mv-record > td.time-cell { position: relative; overflow: hidden; }
:root:not([data-theme="alpine"]) tbody tr.mv-eclat > td.time-cell::after,
:root:not([data-theme="alpine"]) tbody tr.mv-record > td.time-cell::after,
:root:not([data-theme="alpine"]) .pod.p1.mv-eclat::after {
  content: ""; position: absolute; inset: 0; opacity: 0; pointer-events: none;
  -webkit-mask-image: linear-gradient(125.8deg, transparent 36%, #000 50%, transparent 64%);
          mask-image: linear-gradient(125.8deg, transparent 36%, #000 50%, transparent 64%);
  animation: mv-eclat var(--dur-long) var(--ease-balai) .35s backwards;
}
:root:not([data-theme="alpine"]) tbody tr.mv-eclat > td.time-cell::after { background: var(--or-degrade); mix-blend-mode: screen; }
:root:not([data-theme="alpine"]) tbody tr.mv-record > td.time-cell::after { background: rgba(251, 251, 253, .55); mix-blend-mode: screen; }
:root:not([data-theme="alpine"]) .pod.p1.mv-eclat::after { background: rgba(251, 251, 253, .3); }
@keyframes mv-eclat {
  from { opacity: 1; transform: translateX(-100%); }
  to   { opacity: 1; transform: translateX(100%); }
}

/* --- Le Sillage : les lignes que pousse un tour neuf descendent ENSEMBLE d'un
   rang (0,5 s), de leur ancienne place (--mv-dx, --mv-dy, que le script mesure
   et pose) a la nouvelle. La premiere seule traine trois rayures a 54,2 deg
   (le profil des rayures du step gradient), une fois, sur sa premiere cellule.
   LE REPOS EST LE VIDE : l'animation n'a pas de fill-mode, donc a sa fin -- ou
   des la pose de la classe sous mouvement reduit, ou elle est coupee -- la
   trainee retombe sur l'opacite de sa regle de base, 0 ; sans cela, trois
   rayures or resteraient peintes jusqu'au rendu suivant. */
:root:not([data-theme="alpine"]) .mv-sillage { animation: mv-sillage .5s var(--ease-arrivee); }
@keyframes mv-sillage {
  from { transform: translate(var(--mv-dx, 0px), var(--mv-dy, 0px)); }
  to   { transform: none; }
}
:root:not([data-theme="alpine"]) tbody tr.mv-sillage-tete > td:first-child { position: relative; }
:root:not([data-theme="alpine"]) tbody tr.mv-sillage-tete > td:first-child::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5.2em; pointer-events: none; opacity: 0;
  background: var(--gold);
  -webkit-mask-image: linear-gradient(54.2deg, transparent 18%, #000 18% 27%, transparent 27% 43%, #000 43% 52%, transparent 52% 68%, #000 68% 77%, transparent 77%);
          mask-image: linear-gradient(54.2deg, transparent 18%, #000 18% 27%, transparent 27% 43%, #000 43% 52%, transparent 52% 68%, #000 68% 77%, transparent 77%);
  animation: mv-sillage-traine .5s var(--ease-arrivee);
}
@keyframes mv-sillage-traine {
  from { opacity: .9; transform: translateY(-60%); }
  to   { opacity: 0; transform: translateY(0); }
}

/* --- La Cascade : les lignes d'une page qui entre arrivent l'une apres
   l'autre, --cascade (75 ms) par rang, le rang --mv-i etant pose par le
   script (au plus douze lignes attendent). « backwards » : la ligne attend
   son tour cachee. Seulement a un changement de page, de vue, d'ecran ou de
   rotation. */
:root:not([data-theme="alpine"]) .mv-cascade {
  animation: mv-cascade var(--dur-moyen) var(--ease-arrivee) backwards;
  animation-delay: calc(var(--mv-i, 0) * var(--cascade));
}
@keyframes mv-cascade {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

/* --- Le Balai : une bande au profil du step gradient (une masse pleine sur
   les premiers 22 %, puis trois rayures qui s'amincissent) traverse le bloc a
   54,2 deg en 0,75 s, dans un calque rogne a sa boite que le script pose hors
   de l'hote (il survit a toute reecriture de l'hote). La bande fait 60 % de la
   largeur du bloc et 124 % de sa hauteur. LA COURSE EST CALCULEE : les % d'un
   translateX sont ceux de la largeur de la bande (0,6 de celle du bloc), et la
   penche de 35,8 deg decale ses coins haut et bas de 0,447 fois la hauteur du
   bloc. Elle va de -(100 % + S) a +(170 % + S) de la largeur de la bande, S
   etant la SURCOURSE que le script pose sur le calque d'apres la boite du bloc
   (--mv-surcourse, surcourse() dans mouvement.js) : 0,7 -- soit -170 % a
   +240 %, la valeur sans variable -- pour tout bloc dont la hauteur ne
   depasse pas 0,94 de sa largeur (le mur, un bureau), davantage pour un bloc
   plus haut (le tableau du B2B empile d'un telephone, la borne en portrait),
   sans quoi la bande resterait plantee en triangle dans un coin. Ainsi, quelle
   que soit la forme du bloc, elle est entierement hors du bloc a la premiere
   et a la derniere image, et elle couvre son milieu a la moitie du temps -- ce
   que le script attend pour changer le contenu. La courbe est symetrique (ease-in-out,
   le mot-cle natif) : --ease-balai, tres en avant, la mettrait au milieu a
   12 % du temps et hors du bloc bien avant la moitie. */
:root:not([data-theme="alpine"]) .mv-balai { position: fixed; z-index: 30; overflow: hidden; pointer-events: none; }
:root:not([data-theme="alpine"]) .mv-balai-bande {
  position: absolute; top: -12%; bottom: -12%; left: 0; width: 60%;
  background: linear-gradient(90deg,
    rgba(var(--brand-rgb), .9) 0 22%, transparent 22% 34%,
    rgba(var(--brand-rgb), .9) 34% 44%, transparent 44% 58%,
    rgba(var(--brand-rgb), .9) 58% 65%, transparent 65% 80%,
    rgba(var(--brand-rgb), .9) 80% 84%, transparent 84%);
  animation: mv-balai .75s ease-in-out both;
}
@keyframes mv-balai {
  from { transform: translateX(calc(-100% - 100% * var(--mv-surcourse, .7))) skewX(35.8deg); }
  to   { transform: translateX(calc(170% + 100% * var(--mv-surcourse, .7))) skewX(35.8deg); }
}

/* --- La page sortante du B2B se cache par une classe, pendant la bande ;
   « hidden » n'est pose qu'a la fin. Plus specifique que .page { display:
   block } de b2b.css (0,4,0 contre 0,1,0). */
:root:not([data-theme="alpine"]) .page.mv-sortante { display: none; }

/* --- Mouvement reduit : rien de tout cela ne bouge ; l'anneau et les reflets,
   a l'opacite 0, ne se voient pas. UNE LIGNE NEUVE GARDE UNE TEINTE statique :
   celle que le lot 1b donne a tr.ligne-neuve sous mouvement reduit
   (classement.css), classe que ce lot ne pose plus sous E-MOTION. Le rail
   jaune ne la distinguerait pas : toute ligne du jour le porte deja. Une
   couleur de fond, rien d'anime. Meme specificite que le survol de
   classement.css (0,3,2) et chargee apres elle : la teinte tient au survol ;
   la ligne ouverte (0,4,2) garde son propre fond, comme au lot 1b. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-theme="alpine"]) .dot.mv-pouls::after,
  :root:not([data-theme="alpine"]) .today-title.mv-pouls::before,
  :root:not([data-theme="alpine"]) tbody tr.mv-arrivee,
  :root:not([data-theme="alpine"]) .tt-row.mv-arrivee,
  :root:not([data-theme="alpine"]) tbody tr.mv-eclat > td.time-cell::after,
  :root:not([data-theme="alpine"]) tbody tr.mv-record > td.time-cell::after,
  :root:not([data-theme="alpine"]) .pod.p1.mv-eclat::after,
  :root:not([data-theme="alpine"]) .mv-sillage,
  :root:not([data-theme="alpine"]) tbody tr.mv-sillage-tete > td:first-child::after,
  :root:not([data-theme="alpine"]) .mv-cascade,
  :root:not([data-theme="alpine"]) .mv-balai-bande { animation: none; }
  :root:not([data-theme="alpine"]) .mv-balai { display: none; }
  :root:not([data-theme="alpine"]) tbody tr.mv-arrivee { background-color: rgba(var(--brand-rgb), .10); }
}
